[soqt] 04/09: Add files from SoGui as a patch. Need for build.

Anton Gladky gladk at alioth.debian.org
Tue Sep 17 19:21:56 UTC 2013


This is an automated email from the git hooks/post-receive script.

gladk pushed a commit to branch master
in repository soqt.

commit 8b79572b925294e78fd2760633b22f572f057f35
Author: Anton Gladky <gladky.anton at gmail.com>
Date:   Tue Sep 17 21:00:08 2013 +0200

    Add files from SoGui as a patch. Need for build.
---
 debian/patches/add_sogui.patch |41764 ++++++++++++++++++++++++++++++++++++++++
 debian/patches/series          |    1 +
 2 files changed, 41765 insertions(+)

diff --git a/debian/patches/add_sogui.patch b/debian/patches/add_sogui.patch
new file mode 100644
index 0000000..77f5332
--- /dev/null
+++ b/debian/patches/add_sogui.patch
@@ -0,0 +1,41764 @@
+Description: add SoGui into the soqt.
+ The latest VCS-version of SoQT does not build without SoGui-files. 
+ The source is added here as a patch.
+ https://bitbucket.org/Coin3D/sogui/src
+Author: Anton Gladky <gladk at debian.org>
+Last-Update: 2013-09-17
+
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/.hg_archival.txt
+@@ -0,0 +1,5 @@
++repo: 14ca99190cb55f414982b9a037817ced369b28a3
++node: 229ba2f86292cd8b89bbd7381c2cf22e138cdc84
++branch: default
++latesttag: soqt-1_4_0
++latesttagdistance: 63
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/BUGS.txt
+@@ -0,0 +1,161 @@
++=====================================================================
++NOTE: see also So at Gui@/BUGS.txt.
++=====================================================================
++
++000 SoText2 won't show with drawstyle == hidden line. Bug reported by
++    Jean Davy. Reproduce with this minimal, stand-alone example:
++
++    ----8<--- [snip] ---------8<--- [snip] ---------8<--- [snip] ---
++    #include <Inventor/Qt/SoQt.h>
++    #include <Inventor/Qt/viewers/SoQtExaminerViewer.h>
++    #include <Inventor/nodes/SoCone.h>
++    #include <Inventor/nodes/SoSeparator.h>
++    #include <Inventor/nodes/SoText2.h>
++    
++    int
++    main(int argc, char* argv[])
++    {
++      QWidget * mainwin = SoQt::init(argv[0]);
++      SoSeparator * root = new SoSeparator;
++    
++      root->addChild(new SoCone);
++      SoText2 * text2d = new SoText2;
++      root->addChild(text2d);
++      text2d->string = "tjo-bing";
++    
++      SoQtExaminerViewer * viewer = new SoQtExaminerViewer(mainwin);
++      viewer->setSceneGraph(root);
++      viewer->setDrawStyle(SoQtExaminerViewer::STILL,
++                           SoQtExaminerViewer::VIEW_HIDDEN_LINE);
++    
++      SoQt::show(mainwin);
++      SoQt::mainLoop();
++    
++      return 0;
++    }
++    ----8<--- [snip] ---------8<--- [snip] ---------8<--- [snip] ---
++
++    This is the cause of the bug, according to <pederb at sim.no>:
++
++      We use GL polygon offset to do hidden line rendering, and this
++      caused problems since the SoText2 characters are rendered twice
++      (for the first pass we just draw everything black, with an
++      z-buffer offset). SoText2 characters are drawn as bitmaps, which
++      are not affected by polygon offset.
++
++    Consider this a fairly low priority bug.
++
++    <mortene at sim.no> 20020521.
++
++=====================================================================
++
++002 Should search for and pick up VRML97 Viewpoint and other bindable
++    nodes.
++
++    As of now, the SoGuiViewer only scans a newly set scene graph for
++    SoCamera nodes. (If found, it will "attach" the viewer controls to
++    the first one.) If none is found, the viewer sets up it's own in
++    it's private "control graph".
++
++    This doesn't work with VRML97 scene graphs, obviously, so
++    SoGuiViewer should also scan for Viewpoint nodes to be set up as
++    the viewer's camera. 
++
++    Note that matters are complicated a bit by the fact that we can't
++    be sure that an implementation of any VRML97 nodes is actually
++    present in the Coin / Inventor library (it could be SGI Inventor,
++    or it could be Coin configured to exclude VRML97 support). So we
++    need to search for them by using the SoType::fromName("Viewpoint")
++    type (check that this is != SoType::badType() to see whether
++    VRML97 is supported), and connect up it's position, orientation
++    and fieldOfViewer fields by using the introspection features of
++    SoFieldContainer.
++
++    In addition to the Viewpoint nodes, other bindable nodes should
++    also be handled (Fog and Background).
++
++    20030107 mortene.
++
++=====================================================================
++
++003 View volume settings becomes incorrect for "point scene".
++
++    If the scene graph just contains a single point in 3D space, the
++    view volume setup will cause heaps of error messages when running
++    on top of debug-mode Coin.
++
++    Can be reproduced by loading this into an examinerviewer and
++    interacting with the camera:
++
++    ----8<--- [snip] ---------8<--- [snip] ---------8<--- [snip] ---
++    #Inventor V2.1 ascii
++    
++    Coordinate3 { point 42 4242 424242 }
++    PointSet { }
++    ----8<--- [snip] ---------8<--- [snip] ---------8<--- [snip] ---
++
++    A suggestion for a solution: should most likely handle this
++    problem by detecting when the scene bounding sphere is below a
++    certain radius, and then "artificially" expand it to a minimum
++    value.
++
++    20030916 mortene.
++
++=====================================================================
++
++004 Switching back and forth between camera types causes bugs in
++    height / heightAngle fields.
++
++    To reproduce, load a simple scene into the SoGuiExaminerViewer,
++    then switch camera modes, zoom back and forth, switch, zoom,
++    etc. Eventually, the field-of-view for the SoPerspectiveCamera
++    will go bonkers.
++
++    20040726 mortene.
++
++=====================================================================
++
++005 Switching back and forth between camera types causes weird
++    behavior with "view all".
++
++    To reproduce buggy behavior: load an iv-file just containing an
++    SoSphere node into an SoGuiExaminerViewer. Go to ortho camera,
++    click "view all", switch to perspective camera, click "view
++    all". The camera will now be a great deal further away from the
++    sphere than when in ortho camera mode.
++
++    This bug may be related to the generally buggy re-calculation of
++    height / heightAngle when switching back and forth between ortho
++    and perspective camera, as described in bug #004.
++
++    20040726 mortene.
++
++=====================================================================
++
++006 Static building of the So* libraries under Windows linking with a
++    staticly built Coin causes Coin to be included within the So*
++    lib-file.
++
++    This will typically cause multiple Coin instances in the final
++    executable, as the user is likely to link with Coin again for the
++    app code. The same problem also probably manifests itself with
++    e.g. SIM Voleon, SIM Aruba, and our other libraries dependent on
++    Coin.
++
++    20041021 mortene.
++
++    Update 20041103 larsa: Fixed, but not for SIM Voleon and
++    SmallChange.  WIll fix for those and remove this item RSN.
++
++=====================================================================
++
++007 Catch GL errors in a proper manner.
++
++    glGetError() should always be called in a loop, i.e. as we do in
++    Coin with the coin_catch_gl_errors() call in src/glue/gl.c.
++
++    Audit and fix all code in the So* libraries in this regard.
++
++    20051115 mortene.
++
++=====================================================================
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/HACKING
+@@ -0,0 +1,35 @@
++This file describes some hacking techniques and tips & tricks that are
++common for the GUI interface toolkits.
++
++Be sure to check Coin/HACKING for Coin-specific tricks and more
++generic information, plus the file HACKING (if present) on the
++sourcecode root of the "parent" toolkit CVS module.
++
++
++0 Finding Component Information
++===============================
++
++  We have added some easter eggs to the debug versions of the
++  GUI toolkit libraries that can be used to find information
++  about which components are in use.
++
++  Typing 'glinfo' in a viewer will probe into all kinds of information
++  from the GL driver and open a window displaying it.
++
++  Typing 'ivinfo' in a viewer will probe about the underlying Open
++  Inventor implementation and display it in a new window.
++
++  Typing 'soinfo' in a viewer will open a window with some basic
++  information about the toolkit library and possibly the native
++  toolkit it has been built on.
++
++
++1 Performance profiling / debugging
++===================================
++
++  If you are doing work related to rendering performance, you will
++  probably want to see frames-per-second statistics when spinning
++  models, etc.  If you set the environment variable
++  COIN_SHOW_FPS_COUNTER to "1", a fps counter should show up in the
++  bottom left corner of the GL canvas when you do animation (spinning,
++  zooming, etc) in the viewer components.
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/Makefile.common
+@@ -0,0 +1,785 @@
++############################################################################
++# src/Inventor/@Gui@/common/Makefile.common
++#
++# This file takes care of all the common code generation that is happening
++# across all the Coin3D GUI toolkit libraries.
++#
++
++SoGui_BuiltFiles = \
++  $(top_builddir)/sogui.doxygen \
++  $(top_builddir)/so at gui@-config \
++  $(top_builddir)/so at gui@- at CONFIG@.cfg
++
++SoGui_src_BuiltFiles = \
++  $(top_builddir)/src/so at gui@defs.h
++##$(top_builddir)/src/config.h
++
++SoGui_build_BuiltFiles = 
++
++SoGui_src_Inventor_BuiltFiles =
++
++SoGui_src_Inventor_Gui_BuiltFiles = \
++  $(top_builddir)/src/Inventor/@Gui@/SoAny.h \
++  $(top_builddir)/src/Inventor/@Gui@/SoAny.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/So at Gui@Basic.h \
++  $(top_builddir)/src/Inventor/@Gui@/So at Gui@Cursor.h \
++  $(top_builddir)/src/Inventor/@Gui@/So at Gui@Cursor.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/So at Gui@Object.h \
++  $(top_builddir)/src/Inventor/@Gui@/So at Gui@Object.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/So at Gui@.h \
++  $(top_builddir)/src/Inventor/@Gui@/SoGuiP.h \
++  $(top_builddir)/src/Inventor/@Gui@/So at Gui@Common.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/So at Gui@ComponentCommon.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/So at Gui@Component.h \
++  $(top_builddir)/src/Inventor/@Gui@/SoGuiComponentP.h \
++  $(top_builddir)/src/Inventor/@Gui@/So at Gui@GLWidget.h \
++  $(top_builddir)/src/Inventor/@Gui@/SoGuiGLWidgetP.h \
++  $(top_builddir)/src/Inventor/@Gui@/So at Gui@GLWidgetCommon.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/So at Gui@RenderArea.h \
++  $(top_builddir)/src/Inventor/@Gui@/So at Gui@RenderArea.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/So at Gui@ColorEditor.h \
++  $(top_builddir)/src/Inventor/@Gui@/So at Gui@MaterialEditor.h \
++  $(SoGui_src_Inventor_Gui_common_BuiltFiles)
++
++SoGui_src_Inventor_Gui_common_BuiltFiles = \
++  $(top_builddir)/src/Inventor/@Gui@/common/gl.h
++
++SoGui_src_Inventor_Gui_devices_BuiltFiles = \
++  $(top_builddir)/src/Inventor/@Gui@/devices/spwinput.h \
++  $(top_builddir)/src/Inventor/@Gui@/devices/spwinput_win32.h \
++  $(top_builddir)/src/Inventor/@Gui@/devices/spwinput_x11.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/devices/spwinput_win32.c \
++  $(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@DeviceCommon.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/devices/SoGuiDeviceP.h \
++  $(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@Device.h \
++  $(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@InputFocusCommon.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@InputFocus.h \
++  $(top_builddir)/src/Inventor/@Gui@/devices/SoGuiInputFocusP.h \
++  $(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@KeyboardCommon.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@Keyboard.h \
++  $(top_builddir)/src/Inventor/@Gui@/devices/SoGuiKeyboardP.h \
++  $(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@MouseCommon.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@Mouse.h \
++  $(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@SpacenavDevice.h \
++  $(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@SpacenavDevice.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/devices/SoGuiMouseP.h
++
++SoGui_src_Inventor_Gui_editors_BuiltFiles = \
++  $(top_builddir)/src/Inventor/@Gui@/editors/So at Gui@ColorEditor.h \
++  $(top_builddir)/src/Inventor/@Gui@/editors/So at Gui@ColorEditor.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/editors/So at Gui@MaterialEditor.h \
++  $(top_builddir)/src/Inventor/@Gui@/editors/So at Gui@MaterialEditor.cpp
++
++SoGui_src_Inventor_Gui_nodes_BuiltFiles = \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiNodes.h \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/Nodes.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiSceneTexture2.h \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/SceneTexture2.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiViewportFix.h \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/ViewportFix.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiViewpointWrapper.h \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/ViewpointWrapper.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiPane.h \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/Pane.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiPosition.h \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/Position.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiTranslation.h \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/Translation.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiFrame.h \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/Frame.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiImage.h \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/Image.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiLabel.h \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/Label.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiToggleButton.h \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/ToggleButton.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiRadioButton.h \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/RadioButton.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiClickCounter.h \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/ClickCounter.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiSlider1.h \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/Slider1.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiSlider2.h \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/Slider2.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiColorEditor.h \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/ColorEditor.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiMaterialEditor.h \
++  $(top_builddir)/src/Inventor/@Gui@/nodes/MaterialEditor.cpp
++
++SoGui_src_Inventor_Gui_engines_BuiltFiles = \
++  $(top_builddir)/src/Inventor/@Gui@/engines/SoGuiEngines.h \
++  $(top_builddir)/src/Inventor/@Gui@/engines/Engines.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/engines/SoGuiRadioGroup.h \
++  $(top_builddir)/src/Inventor/@Gui@/engines/RadioGroup.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/engines/SoGuiFormat.h \
++  $(top_builddir)/src/Inventor/@Gui@/engines/Format.cpp
++
++SoGui_src_Inventor_Gui_viewers_BuiltFiles = \
++  $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@Viewer.h \
++  $(top_builddir)/src/Inventor/@Gui@/viewers/SoGuiViewerP.h \
++  $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@Viewer.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.h \
++  $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@FlyViewer.h \
++  $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@FlyViewer.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@FullViewer.h \
++  $(top_builddir)/src/Inventor/@Gui@/viewers/SoGuiFullViewerP.h \
++  $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@FullViewer.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/viewers/SoGuiExaminerViewerP.h \
++  $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.h \
++  $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@PlaneViewer.h \
++  $(top_builddir)/src/Inventor/@Gui@/viewers/SoGuiPlaneViewerP.h \
++  $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@PlaneViewer.cpp
++
++SoGui_src_Inventor_Gui_widgets_BuiltFiles = \
++  $(top_builddir)/src/Inventor/@Gui@/widgets/SoAnyThumbWheel.h \
++  $(top_builddir)/src/Inventor/@Gui@/widgets/SoAnyThumbWheel.cpp \
++  $(top_builddir)/src/Inventor/@Gui@/widgets/So at Gui@PopupMenu.h \
++  $(top_builddir)/src/Inventor/@Gui@/widgets/So at Gui@PopupMenu.cpp
++
++SoGui_man_man1_BuiltFiles = \
++  $(top_builddir)/man/man1/so at gui@-config.1
++
++SoGuiBuiltFiles = \
++  $(SoGui_BuiltFiles) \
++  $(SoGui_build_BuiltFiles) \
++  $(SoGui_src_BuiltFiles) \
++  $(SoGui_src_Inventor_BuiltFiles) \
++  $(SoGui_src_Inventor_Gui_BuiltFiles) \
++  $(SoGui_src_Inventor_Gui_devices_BuiltFiles) \
++  $(SoGui_src_Inventor_Gui_editors_BuiltFiles) \
++  $(SoGui_src_Inventor_Gui_engines_BuiltFiles) \
++  $(SoGui_src_Inventor_Gui_nodes_BuiltFiles) \
++  $(SoGui_src_Inventor_Gui_viewers_BuiltFiles) \
++  $(SoGui_src_Inventor_Gui_widgets_BuiltFiles) \
++  $(SoGui_man_man1_BuiltFiles)
++
++if BUILD_METAFILES
++
++SoGui_BuiltMetaFiles =
++SoGui_src_BuiltMetaFiles =
++SoGui_src_Inventor_BuiltMetaFiles =
++
++SoGui_src_Inventor_Gui_BuiltMetaFiles = \
++  $(top_builddir)/src/Inventor/@Gui@/@meta_prefix at So@Gui at P.icc \
++  $(top_builddir)/src/Inventor/@Gui@/@meta_prefix at So@Gui at ComponentP.icc \
++  $(top_builddir)/src/Inventor/@Gui@/@meta_prefix at So@Gui at GLWidgetP.icc
++
++if HAVE_JOYSTICK_LINUX
++SoGui_src_Inventor_Gui_devices_LinuxJoystickMetaFiles = \
++  $(top_builddir)/src/Inventor/@Gui@/devices/@meta_prefix at So@Gui at LinuxJoystickP.icc
++else
++SoGui_src_Inventor_Gui_devices_LinuxJoystickMetaFiles =
++endif
++
++SoGui_src_Inventor_Gui_devices_BuiltMetaFiles = \
++  $(SoGui_src_Inventor_Gui_devices_LinuxJoystickMetaFiles)
++
++SoGui_src_Inventor_Gui_viewers_BuiltMetaFiles = \
++  $(top_builddir)/src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at FullViewerP.icc \
++  $(top_builddir)/src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at ExaminerViewerP.icc \
++  $(top_builddir)/src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at PlaneViewerP.icc
++
++SoGui_src_Inventor_Gui_widgets_BuiltMetaFiles = \
++  $(top_builddir)/src/Inventor/@Gui@/widgets/@meta_prefix@@Gui at NativePopupMenu.icc \
++  $(top_builddir)/src/Inventor/@Gui@/widgets/@meta_prefix at So@Gui at GLArea.icc \
++  $(top_builddir)/src/Inventor/@Gui@/widgets/@meta_prefix at So@Gui at ThumbWheel.icc
++
++else
++
++SoGui_src_Inventor_Gui_BuiltMetaFiles =
++SoGui_src_Inventor_Gui_devices_BuiltMetaFiles =
++SoGui_src_Inventor_Gui_viewers_BuiltMetaFiles =
++SoGui_src_Inventor_Gui_widgets_BuiltMetaFiles =
++
++endif
++
++SoGuiBuiltMetaFiles = \
++  $(SoGui_BuiltMetaFiles) \
++  $(SoGui_src_BuiltMetaFiles) \
++  $(SoGui_src_Inventor_BuiltMetaFiles) \
++  $(SoGui_src_Inventor_Gui_BuiltMetaFiles) \
++  $(SoGui_src_Inventor_Gui_devices_BuiltMetaFiles) \
++  $(SoGui_src_Inventor_Gui_editors_BuiltMetaFiles) \
++  $(SoGui_src_Inventor_Gui_engines_BuiltMetaFiles) \
++  $(SoGui_src_Inventor_Gui_nodes_BuiltMetaFiles) \
++  $(SoGui_src_Inventor_Gui_viewers_BuiltMetaFiles) \
++  $(SoGui_src_Inventor_Gui_widgets_BuiltMetaFiles)
++
++SoGuiAllBuiltFiles = \
++  $(SoGuiBuiltFiles) \
++  $(SoGuiBuiltMetaFiles)
++
++SoGuiCommonWinFiles = \
++  cfg/errors.txt \
++  cfg/doxy4win.pl \
++  cfg/gendsp.pl \
++  cfg/wrapmsvc.exe
++
++SoGuiCommonDistFiles = \
++  BUGS.txt \
++  src/Inventor/@Gui@/common/BUGS.txt \
++  \
++  src/Inventor/@Gui@/common/Makefile.common \
++  src/Inventor/@Gui@/common/sogui-config.in \
++  src/Inventor/@Gui@/common/sogui.doxygen.in \
++  src/Inventor/@Gui@/common/sogui-config.1.in \
++  src/Inventor/@Gui@/common/sogui.cfg.in \
++  src/Inventor/@Gui@/common/SoGuiBasic.h.in \
++  src/Inventor/@Gui@/common/SoGuiCursor.h.in \
++  src/Inventor/@Gui@/common/SoGuiCursor.cpp.in \
++  src/Inventor/@Gui@/common/SoGuiObject.h.in \
++  src/Inventor/@Gui@/common/SoGuiObject.cpp.in \
++  src/Inventor/@Gui@/common/SoGui.h.in \
++  src/Inventor/@Gui@/common/SoGuiP.h.in \
++  src/Inventor/@Gui@/common/SoGuiCommon.cpp.in \
++  src/Inventor/@Gui@/common/SoGuiComponentCommon.cpp.in \
++  src/Inventor/@Gui@/common/SoGuiComponent.h.in \
++  src/Inventor/@Gui@/common/SoGuiComponentP.h.in \
++  src/Inventor/@Gui@/common/SoGuiGLWidget.h.in \
++  src/Inventor/@Gui@/common/SoGuiGLWidgetP.h.in \
++  src/Inventor/@Gui@/common/SoGuiGLWidgetCommon.cpp.in \
++  src/Inventor/@Gui@/common/SoGuiRenderArea.h.in \
++  src/Inventor/@Gui@/common/SoGuiRenderArea.cpp.in \
++  src/Inventor/@Gui@/common/SoGuiColorEditor.h.in \
++  src/Inventor/@Gui@/common/SoGuiMaterialEditor.h.in \
++  src/Inventor/@Gui@/common/SbGuiList.h \
++  src/Inventor/@Gui@/common/SoAny.h.in \
++  src/Inventor/@Gui@/common/SoAny.cpp.in \
++  src/Inventor/@Gui@/common/widgets/SoGuiPopupMenu.h.in \
++  src/Inventor/@Gui@/common/widgets/SoGuiPopupMenu.cpp.in \
++  src/Inventor/@Gui@/common/widgets/SoAnyThumbWheel.h.in \
++  src/Inventor/@Gui@/common/widgets/SoAnyThumbWheel.cpp.in \
++  src/Inventor/@Gui@/common/gl.h.in \
++  src/Inventor/@Gui@/common/soguidefs.h.in \
++  src/Inventor/@Gui@/common/spwinput.h.in \
++  src/Inventor/@Gui@/common/spwinput_win32.h.in \
++  src/Inventor/@Gui@/common/spwinput_x11.cpp.in \
++  src/Inventor/@Gui@/common/spwinput_win32.c.in \
++  src/Inventor/@Gui@/common/devices/SoGuiDevice.cpp.in \
++  src/Inventor/@Gui@/common/devices/SoGuiDeviceP.h.in \
++  src/Inventor/@Gui@/common/devices/SoGuiDevice.h.in \
++  src/Inventor/@Gui@/common/devices/SoGuiInputFocus.cpp.in \
++  src/Inventor/@Gui@/common/devices/SoGuiInputFocus.h.in \
++  src/Inventor/@Gui@/common/devices/SoGuiInputFocusP.h.in \
++  src/Inventor/@Gui@/common/devices/SoGuiKeyboard.cpp.in \
++  src/Inventor/@Gui@/common/devices/SoGuiKeyboard.h.in \
++  src/Inventor/@Gui@/common/devices/SoGuiKeyboardP.h.in \
++  src/Inventor/@Gui@/common/devices/SoGuiMouse.cpp.in \
++  src/Inventor/@Gui@/common/devices/SoGuiMouse.h.in \
++  src/Inventor/@Gui@/common/devices/SoGuiMouseP.h.in \
++  src/Inventor/@Gui@/common/docs/doxygen/header.html \
++  src/Inventor/@Gui@/common/docs/doxygen/footer.html \
++  src/Inventor/@Gui@/common/docs/doxygen/stylesheet.css \
++  src/Inventor/@Gui@/common/docs/doxygen/Coin_logo.png \
++  src/Inventor/@Gui@/common/editors/SoGuiColorEditor.h.in \
++  src/Inventor/@Gui@/common/editors/SoGuiColorEditor.cpp.in \
++  src/Inventor/@Gui@/common/editors/SoGuiMaterialEditor.h.in \
++  src/Inventor/@Gui@/common/editors/SoGuiMaterialEditor.cpp.in \
++  src/Inventor/@Gui@/common/engines/Engines.h.in \
++  src/Inventor/@Gui@/common/engines/Engines.cpp.in \
++  src/Inventor/@Gui@/common/engines/RadioGroup.h.in \
++  src/Inventor/@Gui@/common/engines/RadioGroup.cpp.in \
++  src/Inventor/@Gui@/common/engines/Format.h.in \
++  src/Inventor/@Gui@/common/engines/Format.cpp.in \
++  src/Inventor/@Gui@/common/nodes/Nodes.h.in \
++  src/Inventor/@Gui@/common/nodes/Nodes.cpp.in \
++  src/Inventor/@Gui@/common/nodes/SceneTexture2.h.in \
++  src/Inventor/@Gui@/common/nodes/SceneTexture2.cpp.in \
++  src/Inventor/@Gui@/common/nodes/ViewportFix.h.in \
++  src/Inventor/@Gui@/common/nodes/ViewportFix.cpp.in \
++  src/Inventor/@Gui@/common/nodes/ViewpointWrapper.h.in \
++  src/Inventor/@Gui@/common/nodes/ViewpointWrapper.cpp.in \
++  src/Inventor/@Gui@/common/nodes/Pane.h.in \
++  src/Inventor/@Gui@/common/nodes/Pane.cpp.in \
++  src/Inventor/@Gui@/common/nodes/Position.h.in \
++  src/Inventor/@Gui@/common/nodes/Position.cpp.in \
++  src/Inventor/@Gui@/common/nodes/Translation.h.in \
++  src/Inventor/@Gui@/common/nodes/Translation.cpp.in \
++  src/Inventor/@Gui@/common/nodes/Frame.h.in \
++  src/Inventor/@Gui@/common/nodes/Frame.cpp.in \
++  src/Inventor/@Gui@/common/nodes/Image.h.in \
++  src/Inventor/@Gui@/common/nodes/Image.cpp.in \
++  src/Inventor/@Gui@/common/nodes/Label.h.in \
++  src/Inventor/@Gui@/common/nodes/Label.cpp.in \
++  src/Inventor/@Gui@/common/nodes/ToggleButton.h.in \
++  src/Inventor/@Gui@/common/nodes/ToggleButton.cpp.in \
++  src/Inventor/@Gui@/common/nodes/RadioButton.h.in \
++  src/Inventor/@Gui@/common/nodes/RadioButton.cpp.in \
++  src/Inventor/@Gui@/common/nodes/ClickCounter.h.in \
++  src/Inventor/@Gui@/common/nodes/ClickCounter.cpp.in \
++  src/Inventor/@Gui@/common/nodes/Slider1.h.in \
++  src/Inventor/@Gui@/common/nodes/Slider1.cpp.in \
++  src/Inventor/@Gui@/common/nodes/Slider2.h.in \
++  src/Inventor/@Gui@/common/nodes/Slider2.cpp.in \
++  src/Inventor/@Gui@/common/nodes/ColorEditor.h.in \
++  src/Inventor/@Gui@/common/nodes/ColorEditor.cpp.in \
++  src/Inventor/@Gui@/common/nodes/MaterialEditor.h.in \
++  src/Inventor/@Gui@/common/nodes/MaterialEditor.cpp.in \
++  src/Inventor/@Gui@/common/viewers/SoGuiConstrainedViewer.cpp.in \
++  src/Inventor/@Gui@/common/viewers/SoGuiConstrainedViewer.h.in \
++  src/Inventor/@Gui@/common/viewers/SoGuiFlyViewer.cpp.in \
++  src/Inventor/@Gui@/common/viewers/SoGuiFlyViewer.h.in \
++  src/Inventor/@Gui@/common/viewers/SoGuiFullViewer.cpp.in \
++  src/Inventor/@Gui@/common/viewers/SoGuiFullViewer.h.in \
++  src/Inventor/@Gui@/common/viewers/SoGuiFullViewerP.h.in \
++  src/Inventor/@Gui@/common/viewers/SoGuiExaminerViewer.cpp.in \
++  src/Inventor/@Gui@/common/viewers/SoGuiExaminerViewer.h.in \
++  src/Inventor/@Gui@/common/viewers/SoGuiExaminerViewerP.h.in \
++  src/Inventor/@Gui@/common/viewers/SoGuiPlaneViewer.cpp.in \
++  src/Inventor/@Gui@/common/viewers/SoGuiPlaneViewer.h.in \
++  src/Inventor/@Gui@/common/viewers/SoGuiPlaneViewerP.h.in \
++  src/Inventor/@Gui@/common/viewers/SoGuiViewer.cpp.in \
++  src/Inventor/@Gui@/common/viewers/SoGuiViewer.h.in \
++  src/Inventor/@Gui@/common/viewers/SoGuiViewerP.h.in \
++  src/Inventor/@Gui@/common/pixmaps/home.xpm \
++  src/Inventor/@Gui@/common/pixmaps/ortho.xpm \
++  src/Inventor/@Gui@/common/pixmaps/perspective.xpm \
++  src/Inventor/@Gui@/common/pixmaps/pick.xpm \
++  src/Inventor/@Gui@/common/pixmaps/seek.xpm \
++  src/Inventor/@Gui@/common/pixmaps/set_home.xpm \
++  src/Inventor/@Gui@/common/pixmaps/view.xpm \
++  src/Inventor/@Gui@/common/pixmaps/view_all.xpm \
++  src/Inventor/@Gui@/common/pixmaps/x.xpm \
++  src/Inventor/@Gui@/common/pixmaps/y.xpm \
++  src/Inventor/@Gui@/common/pixmaps/z.xpm
++
++############################################################################
++## the toolkit-specific anomalies
++
++SoQt_ExtraBuiltMetaFiles = \
++  $(top_builddir)/src/Inventor/Qt/widgets/moc_SoQtGLArea.cpp
++
++############################################################################
++## the actual gory rules for generating the sources, invokable from *any*
++## dir in So at Gui@
++
++$(top_builddir)/sogui.doxygen: $(top_srcdir)/src/Inventor/@Gui@/common/sogui.doxygen.in $(top_builddir)/config.status
++	@cd $(top_builddir); \
++	$(SHELL) config.status --file=sogui.doxygen:src/Inventor/@Gui@/common/sogui.doxygen.in; \
++	$(top_srcdir)/cfg/doxy4win.pl sogui.doxygen; \
++	rm -f sogui.doxygen.bak;
++
++$(top_builddir)/so at gui@-config: $(top_srcdir)/src/Inventor/@Gui@/common/sogui-config.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=so at gui@-config:src/Inventor/@Gui@/common/sogui-config.in && chmod +x so at gui@-config )
++
++$(top_builddir)/so at gui@- at CONFIG@.cfg: $(top_srcdir)/src/Inventor/@Gui@/common/sogui.cfg.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=so at gui@- at CONFIG@.cfg:src/Inventor/@Gui@/common/sogui.cfg.in )
++
++############################################################################
++
++## src/
++
++$(top_builddir)/src/config.h: $(top_srcdir)/src/config.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status src/config.h )
++
++$(top_builddir)/src/so at gui@defs.h: $(top_srcdir)/src/Inventor/@Gui@/common/soguidefs.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/so at gui@defs.h:src/Inventor/@Gui@/common/soguidefs.h.in )
++
++## src/Inventor/@Gui@/
++
++$(top_builddir)/src/Inventor/@Gui@/SoAny.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoAny.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/SoAny.h:src/Inventor/@Gui@/common/SoAny.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/SoAny.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/SoAny.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/SoAny.cpp:src/Inventor/@Gui@/common/SoAny.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@Basic.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiBasic.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=-:src/Inventor/@Gui@/common/SoGuiBasic.h.in | $(SHELL) config.status --header=src/Inventor/@Gui@/So at Gui@Basic.h:- )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@Object.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiObject.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@Object.h:src/Inventor/@Gui@/common/SoGuiObject.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@Object.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiObject.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@Object.cpp:src/Inventor/@Gui@/common/SoGuiObject.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@Cursor.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiCursor.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@Cursor.h:src/Inventor/@Gui@/common/SoGuiCursor.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@Cursor.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiCursor.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@Cursor.cpp:src/Inventor/@Gui@/common/SoGuiCursor.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGui.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@.h:src/Inventor/@Gui@/common/SoGui.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/SoGuiP.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiP.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/SoGuiP.h:src/Inventor/@Gui@/common/SoGuiP.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@Common.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiCommon.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@Common.cpp:src/Inventor/@Gui@/common/SoGuiCommon.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@ComponentCommon.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiComponentCommon.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@ComponentCommon.cpp:src/Inventor/@Gui@/common/SoGuiComponentCommon.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@Component.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiComponent.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@Component.h:src/Inventor/@Gui@/common/SoGuiComponent.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/SoGuiComponentP.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiComponentP.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/SoGuiComponentP.h:src/Inventor/@Gui@/common/SoGuiComponentP.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@GLWidget.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiGLWidget.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@GLWidget.h:src/Inventor/@Gui@/common/SoGuiGLWidget.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/SoGuiGLWidgetP.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiGLWidgetP.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/SoGuiGLWidgetP.h:src/Inventor/@Gui@/common/SoGuiGLWidgetP.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@GLWidgetCommon.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiGLWidgetCommon.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@GLWidgetCommon.cpp:src/Inventor/@Gui@/common/SoGuiGLWidgetCommon.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@RenderArea.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiRenderArea.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@RenderArea.h:src/Inventor/@Gui@/common/SoGuiRenderArea.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@RenderArea.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiRenderArea.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@RenderArea.cpp:src/Inventor/@Gui@/common/SoGuiRenderArea.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@ColorEditor.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiColorEditor.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@ColorEditor.h:src/Inventor/@Gui@/common/SoGuiColorEditor.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@MaterialEditor.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiMaterialEditor.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@MaterialEditor.h:src/Inventor/@Gui@/common/SoGuiMaterialEditor.h.in )
++
++## src/Inventor/@Gui@/common/
++
++$(top_builddir)/src/Inventor/@Gui@/common/gl.h: $(top_srcdir)/src/Inventor/@Gui@/common/gl.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); \
++	if test -d src/Inventor/@Gui@/common; then :; else \
++	  echo "mkdir src/Inventor/@Gui@/common"; \
++	  mkdir src/Inventor/@Gui@/common; \
++	fi; \
++	$(SHELL) config.status --file=src/Inventor/@Gui@/common/gl.h:src/Inventor/@Gui@/common/gl.h.in )
++
++## src/Inventor/@Gui@/devices/
++
++$(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@DeviceCommon.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiDevice.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/So at Gui@DeviceCommon.cpp:src/Inventor/@Gui@/common/devices/SoGuiDevice.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@Device.h: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiDevice.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/So at Gui@Device.h:src/Inventor/@Gui@/common/devices/SoGuiDevice.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/SoGuiDeviceP.h: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiDeviceP.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/SoGuiDeviceP.h:src/Inventor/@Gui@/common/devices/SoGuiDeviceP.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@InputFocusCommon.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiInputFocus.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/So at Gui@InputFocusCommon.cpp:src/Inventor/@Gui@/common/devices/SoGuiInputFocus.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@InputFocus.h: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiInputFocus.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/So at Gui@InputFocus.h:src/Inventor/@Gui@/common/devices/SoGuiInputFocus.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/SoGuiInputFocusP.h: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiInputFocusP.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/SoGuiInputFocusP.h:src/Inventor/@Gui@/common/devices/SoGuiInputFocusP.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@KeyboardCommon.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiKeyboard.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/So at Gui@KeyboardCommon.cpp:src/Inventor/@Gui@/common/devices/SoGuiKeyboard.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@Keyboard.h: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiKeyboard.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/So at Gui@Keyboard.h:src/Inventor/@Gui@/common/devices/SoGuiKeyboard.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/SoGuiKeyboardP.h: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiKeyboardP.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/SoGuiKeyboardP.h:src/Inventor/@Gui@/common/devices/SoGuiKeyboardP.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@MouseCommon.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiMouse.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/So at Gui@MouseCommon.cpp:src/Inventor/@Gui@/common/devices/SoGuiMouse.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@Mouse.h: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiMouse.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/So at Gui@Mouse.h:src/Inventor/@Gui@/common/devices/SoGuiMouse.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/SoGuiMouseP.h: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiMouseP.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/SoGuiMouseP.h:src/Inventor/@Gui@/common/devices/SoGuiMouseP.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/SoGuiSpacenavDevice.h: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiSpacenavDevice.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/SoGuiSpacenavDevice.h:src/Inventor/@Gui@/common/devices/SoGuiSpacenavDevice.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/SoGuiSpacenavDevice.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiSpacenavDevice.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/SoGuiSpacenavDevice.cpp:src/Inventor/@Gui@/common/devices/SoGuiSpacenavDevice.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/spwinput.h: $(top_srcdir)/src/Inventor/@Gui@/common/spwinput.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/spwinput.h:src/Inventor/@Gui@/common/spwinput.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/spwinput_win32.h: $(top_srcdir)/src/Inventor/@Gui@/common/spwinput_win32.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/spwinput_win32.h:src/Inventor/@Gui@/common/spwinput_win32.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/spwinput_x11.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/spwinput_x11.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/spwinput_x11.cpp:src/Inventor/@Gui@/common/spwinput_x11.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/spwinput_win32.c: $(top_srcdir)/src/Inventor/@Gui@/common/spwinput_win32.c.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/spwinput_win32.c:src/Inventor/@Gui@/common/spwinput_win32.c.in )
++
++## src/Inventor/@Gui@/editors/
++
++$(top_builddir)/src/Inventor/@Gui@/editors/So at Gui@ColorEditor.h: $(top_srcdir)/src/Inventor/@Gui@/common/editors/SoGuiColorEditor.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/editors/So at Gui@ColorEditor.h:src/Inventor/@Gui@/common/editors/SoGuiColorEditor.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/editors/So at Gui@ColorEditor.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/editors/SoGuiColorEditor.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/editors/So at Gui@ColorEditor.cpp:src/Inventor/@Gui@/common/editors/SoGuiColorEditor.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/editors/So at Gui@MaterialEditor.h: $(top_srcdir)/src/Inventor/@Gui@/common/editors/SoGuiMaterialEditor.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/editors/So at Gui@MaterialEditor.h:src/Inventor/@Gui@/common/editors/SoGuiMaterialEditor.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/editors/So at Gui@MaterialEditor.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/editors/SoGuiMaterialEditor.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/editors/So at Gui@MaterialEditor.cpp:src/Inventor/@Gui@/common/editors/SoGuiMaterialEditor.cpp.in )
++
++## src/Inventor/@Gui@/engines/
++
++$(top_builddir)/src/Inventor/@Gui@/engines/SoGuiEngines.h: $(top_srcdir)/src/Inventor/@Gui@/common/engines/Engines.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/engines/SoGuiEngines.h:src/Inventor/@Gui@/common/engines/Engines.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/engines/Engines.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/engines/Engines.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/engines/Engines.cpp:src/Inventor/@Gui@/common/engines/Engines.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/engines/SoGuiRadioGroup.h: $(top_srcdir)/src/Inventor/@Gui@/common/engines/RadioGroup.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/engines/SoGuiRadioGroup.h:src/Inventor/@Gui@/common/engines/RadioGroup.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/engines/RadioGroup.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/engines/RadioGroup.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/engines/RadioGroup.cpp:src/Inventor/@Gui@/common/engines/RadioGroup.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/engines/SoGuiFormat.h: $(top_srcdir)/src/Inventor/@Gui@/common/engines/Format.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/engines/SoGuiFormat.h:src/Inventor/@Gui@/common/engines/Format.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/engines/Format.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/engines/Format.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/engines/Format.cpp:src/Inventor/@Gui@/common/engines/Format.cpp.in )
++
++## src/Inventor/@Gui@/nodes/
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiNodes.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Nodes.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiNodes.h:src/Inventor/@Gui@/common/nodes/Nodes.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/Nodes.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Nodes.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/Nodes.cpp:src/Inventor/@Gui@/common/nodes/Nodes.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiSceneTexture2.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/SceneTexture2.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiSceneTexture2.h:src/Inventor/@Gui@/common/nodes/SceneTexture2.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SceneTexture2.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/SceneTexture2.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SceneTexture2.cpp:src/Inventor/@Gui@/common/nodes/SceneTexture2.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiViewportFix.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/ViewportFix.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiViewportFix.h:src/Inventor/@Gui@/common/nodes/ViewportFix.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/ViewportFix.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/ViewportFix.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/ViewportFix.cpp:src/Inventor/@Gui@/common/nodes/ViewportFix.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiViewpointWrapper.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/ViewpointWrapper.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiViewpointWrapper.h:src/Inventor/@Gui@/common/nodes/ViewpointWrapper.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/ViewpointWrapper.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/ViewpointWrapper.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/ViewpointWrapper.cpp:src/Inventor/@Gui@/common/nodes/ViewpointWrapper.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiPane.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Pane.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiPane.h:src/Inventor/@Gui@/common/nodes/Pane.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/Pane.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Pane.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/Pane.cpp:src/Inventor/@Gui@/common/nodes/Pane.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiPosition.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Position.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiPosition.h:src/Inventor/@Gui@/common/nodes/Position.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/Position.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Position.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/Position.cpp:src/Inventor/@Gui@/common/nodes/Position.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiTranslation.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Translation.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiTranslation.h:src/Inventor/@Gui@/common/nodes/Translation.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/Translation.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Translation.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/Translation.cpp:src/Inventor/@Gui@/common/nodes/Translation.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiFrame.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Frame.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiFrame.h:src/Inventor/@Gui@/common/nodes/Frame.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/Frame.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Frame.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/Frame.cpp:src/Inventor/@Gui@/common/nodes/Frame.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiImage.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Image.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiImage.h:src/Inventor/@Gui@/common/nodes/Image.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/Image.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Image.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/Image.cpp:src/Inventor/@Gui@/common/nodes/Image.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiLabel.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Label.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiLabel.h:src/Inventor/@Gui@/common/nodes/Label.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/Label.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Label.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/Label.cpp:src/Inventor/@Gui@/common/nodes/Label.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiToggleButton.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/ToggleButton.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiToggleButton.h:src/Inventor/@Gui@/common/nodes/ToggleButton.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/ToggleButton.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/ToggleButton.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/ToggleButton.cpp:src/Inventor/@Gui@/common/nodes/ToggleButton.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiRadioButton.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/RadioButton.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiRadioButton.h:src/Inventor/@Gui@/common/nodes/RadioButton.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/RadioButton.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/RadioButton.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/RadioButton.cpp:src/Inventor/@Gui@/common/nodes/RadioButton.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiClickCounter.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/ClickCounter.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiClickCounter.h:src/Inventor/@Gui@/common/nodes/ClickCounter.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/ClickCounter.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/ClickCounter.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/ClickCounter.cpp:src/Inventor/@Gui@/common/nodes/ClickCounter.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiSlider1.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Slider1.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiSlider1.h:src/Inventor/@Gui@/common/nodes/Slider1.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/Slider1.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Slider1.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/Slider1.cpp:src/Inventor/@Gui@/common/nodes/Slider1.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiSlider2.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Slider2.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiSlider2.h:src/Inventor/@Gui@/common/nodes/Slider2.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/Slider2.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Slider2.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/Slider2.cpp:src/Inventor/@Gui@/common/nodes/Slider2.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiColorEditor.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/ColorEditor.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiColorEditor.h:src/Inventor/@Gui@/common/nodes/ColorEditor.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/ColorEditor.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/ColorEditor.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/ColorEditor.cpp:src/Inventor/@Gui@/common/nodes/ColorEditor.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiMaterialEditor.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/MaterialEditor.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiMaterialEditor.h:src/Inventor/@Gui@/common/nodes/MaterialEditor.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/MaterialEditor.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/MaterialEditor.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/MaterialEditor.cpp:src/Inventor/@Gui@/common/nodes/MaterialEditor.cpp.in )
++
++## src/Inventor/@Gui@/viewers/
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@Viewer.h: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiViewer.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@Viewer.h:src/Inventor/@Gui@/common/viewers/SoGuiViewer.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/SoGuiViewerP.h: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiViewerP.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/SoGuiViewerP.h:src/Inventor/@Gui@/common/viewers/SoGuiViewerP.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@Viewer.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiViewer.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@Viewer.cpp:src/Inventor/@Gui@/common/viewers/SoGuiViewer.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.h: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiConstrainedViewer.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.h:src/Inventor/@Gui@/common/viewers/SoGuiConstrainedViewer.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiConstrainedViewer.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.cpp:src/Inventor/@Gui@/common/viewers/SoGuiConstrainedViewer.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@FlyViewer.h: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiFlyViewer.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@FlyViewer.h:src/Inventor/@Gui@/common/viewers/SoGuiFlyViewer.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@FlyViewer.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiFlyViewer.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@FlyViewer.cpp:src/Inventor/@Gui@/common/viewers/SoGuiFlyViewer.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@FullViewer.h: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiFullViewer.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@FullViewer.h:src/Inventor/@Gui@/common/viewers/SoGuiFullViewer.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/SoGuiFullViewerP.h: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiFullViewerP.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/SoGuiFullViewerP.h:src/Inventor/@Gui@/common/viewers/SoGuiFullViewerP.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@FullViewer.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiFullViewer.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@FullViewer.cpp:src/Inventor/@Gui@/common/viewers/SoGuiFullViewer.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.h: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiExaminerViewer.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.h:src/Inventor/@Gui@/common/viewers/SoGuiExaminerViewer.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/SoGuiExaminerViewerP.h: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiExaminerViewerP.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/SoGuiExaminerViewerP.h:src/Inventor/@Gui@/common/viewers/SoGuiExaminerViewerP.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiExaminerViewer.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.cpp:src/Inventor/@Gui@/common/viewers/SoGuiExaminerViewer.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@PlaneViewer.h: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiPlaneViewer.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@PlaneViewer.h:src/Inventor/@Gui@/common/viewers/SoGuiPlaneViewer.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/SoGuiPlaneViewerP.h: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiPlaneViewerP.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/SoGuiPlaneViewerP.h:src/Inventor/@Gui@/common/viewers/SoGuiPlaneViewerP.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@PlaneViewer.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiPlaneViewer.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@PlaneViewer.cpp:src/Inventor/@Gui@/common/viewers/SoGuiPlaneViewer.cpp.in )
++
++## src/Inventor/@Gui@/widgets/
++
++$(top_builddir)/src/Inventor/@Gui@/widgets/SoAnyThumbWheel.h: $(top_srcdir)/src/Inventor/@Gui@/common/widgets/SoAnyThumbWheel.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/widgets/SoAnyThumbWheel.h:src/Inventor/@Gui@/common/widgets/SoAnyThumbWheel.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/widgets/SoAnyThumbWheel.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/widgets/SoAnyThumbWheel.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/widgets/SoAnyThumbWheel.cpp:src/Inventor/@Gui@/common/widgets/SoAnyThumbWheel.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/widgets/So at Gui@PopupMenu.h: $(top_srcdir)/src/Inventor/@Gui@/common/widgets/SoGuiPopupMenu.h.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/widgets/So at Gui@PopupMenu.h:src/Inventor/@Gui@/common/widgets/SoGuiPopupMenu.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/widgets/So at Gui@PopupMenu.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/widgets/SoGuiPopupMenu.cpp.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/widgets/So at Gui@PopupMenu.cpp:src/Inventor/@Gui@/common/widgets/SoGuiPopupMenu.cpp.in )
++
++## build/
++
++## ..nothing at the moment..
++
++## man/man1/
++
++$(top_builddir)/man/man1/so at gui@-config.1: $(top_srcdir)/src/Inventor/@Gui@/common/sogui-config.1.in $(top_builddir)/config.status
++	@( cd $(top_builddir); $(SHELL) config.status --file=man/man1/so at gui@-config.1:src/Inventor/@Gui@/common/sogui-config.1.in )
++
++# **************************************************************************
++# auto-generated Qt moc files.
++
++if BUILD_METAFILES
++
++## src/Inventor/@Gui@/
++
++$(top_builddir)/src/Inventor/@Gui@/@meta_prefix at So@Gui at P.icc: $(top_srcdir)/src/Inventor/@Gui@/So at Gui@P.h $(top_builddir)/config.status
++	@( cd $(top_builddir); \
++	echo " $(MOC) -i -o src/Inventor/@Gui@/@meta_prefix at So@Gui at P.icc $(top_srcdir)/src/Inventor/@Gui@/So at Gui@P.h"; \
++	$(MOC) -i -o src/Inventor/@Gui@/@meta_prefix at So@Gui at P.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/So at Gui@P.h` )
++
++$(top_builddir)/src/Inventor/@Gui@/@meta_prefix at So@Gui at ComponentP.icc: $(top_srcdir)/src/Inventor/@Gui@/So at Gui@ComponentP.h $(top_builddir)/config.status
++	@( cd $(top_builddir); \
++	echo " $(MOC) -i -o src/Inventor/@Gui@/@meta_prefix at So@Gui at ComponentP.icc src/Inventor/@Gui@/So at Gui@ComponentP.h"; \
++	$(MOC) -i -o src/Inventor/@Gui@/@meta_prefix at So@Gui at ComponentP.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/So at Gui@ComponentP.h` )
++
++$(top_builddir)/src/Inventor/@Gui@/@meta_prefix at So@Gui at GLWidgetP.icc: $(top_srcdir)/src/Inventor/@Gui@/So at Gui@GLWidgetP.h $(top_builddir)/config.status
++	@( cd $(top_builddir); \
++	echo " $(MOC) -i -o src/Inventor/@Gui@/@meta_prefix at So@Gui at GLWidgetP.icc src/Inventor/@Gui@/So at Gui@GLWidgetP.h"; \
++	$(MOC) -i -o src/Inventor/@Gui@/@meta_prefix at So@Gui at GLWidgetP.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/So at Gui@GLWidgetP.h` )
++
++## src/Inventor/@Gui@/devices/
++
++$(top_builddir)/src/Inventor/@Gui@/devices/@meta_prefix at So@Gui at LinuxJoystickP.icc: $(top_srcdir)/src/Inventor/@Gui@/devices/So at Gui@LinuxJoystickP.h $(top_builddir)/config.status
++	@( cd $(top_builddir); \
++	echo " $(MOC) -i -o src/Inventor/@Gui@/devices/@meta_prefix at So@Gui at LinuxJoystickP.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/devices/So at Gui@LinuxJoystickP.h`"; \
++	$(MOC) -i -o src/Inventor/@Gui@/devices/@meta_prefix at So@Gui at LinuxJoystickP.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/devices/So at Gui@LinuxJoystickP.h` )
++
++## src/Inventor/@Gui@/viewers/
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at FullViewerP.icc: $(top_srcdir)/src/Inventor/@Gui@/viewers/So at Gui@FullViewerP.h $(top_builddir)/config.status
++	@( cd $(top_builddir); \
++	echo " $(MOC) -i -o src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at FullViewerP.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/viewers/So at Gui@FullViewerP.h`"; \
++	$(MOC) -i -o src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at FullViewerP.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/viewers/So at Gui@FullViewerP.h` )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at ExaminerViewerP.icc: $(top_srcdir)/src/Inventor/@Gui@/viewers/So at Gui@ExaminerViewerP.h $(top_builddir)/config.status
++	@( cd $(top_builddir); \
++	echo " $(MOC) -i -o src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at ExaminerViewerP.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/viewers/So at Gui@ExaminerViewerP.h`"; \
++	$(MOC) -i -o src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at ExaminerViewerP.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/viewers/So at Gui@ExaminerViewerP.h` )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at PlaneViewerP.icc: $(top_srcdir)/src/Inventor/@Gui@/viewers/So at Gui@PlaneViewerP.h $(top_builddir)/config.status
++	@( cd $(top_builddir); \
++	echo " $(MOC) -i -o src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at PlaneViewerP.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/viewers/So at Gui@PlaneViewerP.h`"; \
++	$(MOC) -i -o src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at PlaneViewerP.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/viewers/So at Gui@PlaneViewerP.h` )
++
++## src/Inventor/@Gui@/widgets/
++
++# $(top_builddir)/src/Inventor/@Gui@/widgets/@meta_prefix at So@Gui at ThumbWheel.icc: $(top_srcdir)/src/Inventor/@Gui@/widgets/So at Gui@ThumbWheel.h $(top_builddir)/config.status
++# 	@( cd $(top_builddir); \
++# 	echo " $(MOC) -i -o src/Inventor/@Gui@/widgets/@meta_prefix at So@Gui at ThumbWheel.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/widgets/So at Gui@ThumbWheel.h`"; \
++# 	$(MOC) -i -o src/Inventor/@Gui@/widgets/@meta_prefix at So@Gui at ThumbWheel.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/widgets/So at Gui@ThumbWheel.h` )
++# 
++# $(top_builddir)/src/Inventor/@Gui@/widgets/@meta_prefix at So@Gui at GLArea.icc: $(top_srcdir)/src/Inventor/@Gui@/widgets/So at Gui@GLArea.h $(top_builddir)/config.status
++# 	@( cd $(top_builddir); \
++# 	echo " $(MOC) -i -o src/Inventor/@Gui@/widgets/@meta_prefix at So@Gui at GLArea.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/widgets/So at Gui@GLArea.h`"; \
++# 	$(MOC) -i -o src/Inventor/@Gui@/widgets/@meta_prefix at So@Gui at GLArea.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/widgets/So at Gui@GLArea.h` )
++# 
++# $(top_builddir)/src/Inventor/@Gui@/widgets/@meta_prefix@@Gui at NativePopupMenu.icc: $(top_srcdir)/src/Inventor/@Gui@/widgets/@Gui at NativePopupMenu.h $(top_builddir)/config.status
++# 	@( cd $(top_builddir); \
++# 	echo " $(MOC) -i -o src/Inventor/@Gui@/widgets/@meta_prefix@@Gui at NativePopupMenu.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/widgets/@Gui at NativePopupMenu.h`"; \
++# 	$(MOC) -i -o src/Inventor/@Gui@/widgets/@meta_prefix@@Gui at NativePopupMenu.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/widgets/@Gui at NativePopupMenu.h` )
++
++endif
++
++## src/Inventor/@Gui@/common/Makefile.common EOF
++############################################################################
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/NEWS
+@@ -0,0 +1,2 @@
++NEWS
++====
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/README
+@@ -0,0 +1,8 @@
++README
++======
++
++This directory is a distinct Subversion repository, named SoGUI. The
++purpose of this repository is to collect code that is common for all
++Coin GUI component sets, so it can be shared and reused (and to round
++up all the bugs in one place :).
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SbGuiList.h
+@@ -0,0 +1,226 @@
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SOGUI_SBGUILIST_H
++#define SOGUI_SBGUILIST_H
++
++/**************************************************************************/
++
++// IMPORTANT NOTES:
++//
++//   * This file is a duplicate of Coin's lists/SbList.h file, and any
++//   important fixes/improvements here should be migrated.
++//
++//   * This file contains definitions which should only be used during
++//   library build for now. It is not yet installed for use by the
++//   application programmer.
++
++/**************************************************************************/
++
++#include <Inventor/SbBasic.h>
++#include <assert.h>
++#include <stddef.h> // NULL definition
++
++// We usually implement inline functions below the class definition,
++// since we think that makes the file more readable. However, this is
++// not done for this class, since Visual C++ is not too happy about
++// having functions declared as inline for a template class.
++// pederb, 2001-10-12
++
++template <class Type>
++class SbGuiList {
++  // Older compilers aren't too happy about const declarations in the
++  // class definitions, so use the enum trick described by Scott
++  // Meyers in "Effective C++".
++  enum { DEFAULTSIZE = 4 };
++
++public:
++
++  SbGuiList(const int sizehint = DEFAULTSIZE)
++    : itembuffersize(DEFAULTSIZE), numitems(0), itembuffer(builtinbuffer) {
++    if (sizehint > DEFAULTSIZE) this->grow(sizehint);
++  }
++
++  SbGuiList(const SbGuiList<Type> & l)
++    : itembuffersize(DEFAULTSIZE), numitems(0), itembuffer(builtinbuffer) {
++    this->copy(l);
++  }
++
++  ~SbGuiList() {
++    if (this->itembuffer != builtinbuffer) delete[] this->itembuffer;
++  }
++
++  void copy(const SbGuiList<Type> & l) {
++    if (this == &l) return;
++    const int n = l.numitems;
++    this->expand(n);
++    for (int i = 0; i < n; i++) this->itembuffer[i] = l.itembuffer[i];
++  }
++
++  SbGuiList <Type> & operator=(const SbGuiList<Type> & l) {
++    this->copy(l);
++    return *this;
++  }
++
++  void fit(void) {
++    const int items = this->numitems;
++
++    if (items < this->itembuffersize) {
++      Type * newitembuffer = this->builtinbuffer;
++      if (items > DEFAULTSIZE) newitembuffer = new Type[items];
++
++      if (newitembuffer != this->itembuffer) {
++        for (int i = 0; i < items; i++) newitembuffer[i] = this->itembuffer[i];
++      }
++
++      if (this->itembuffer != this->builtinbuffer) delete[] this->itembuffer;
++      this->itembuffer = newitembuffer;
++      this->itembuffersize = items > DEFAULTSIZE ? items : DEFAULTSIZE;
++    }
++  }
++
++  void append(const Type item) {
++    if (this->numitems == this->itembuffersize) this->grow();
++    this->itembuffer[this->numitems++] = item;
++  }
++
++  int find(const Type item) const {
++    for (int i = 0; i < this->numitems; i++)
++      if (this->itembuffer[i] == item) return i;
++    return -1;
++  }
++
++  void insert(const Type item, const int insertbefore) {
++    assert(insertbefore >= 0 && insertbefore <= this->numitems);
++    if (this->numitems == this->itembuffersize) this->grow();
++
++    for (int i = this->numitems; i > insertbefore; i--)
++      this->itembuffer[i] = this->itembuffer[i-1];
++    this->itembuffer[insertbefore] = item;
++    this->numitems++;
++  }
++
++  void removeItem(const Type item) {
++    int idx = this->find(item);
++    assert(idx != -1);
++    this->remove(idx);
++  }
++
++  void remove(const int index) {
++    assert(index >= 0 && index < this->numitems);
++    this->numitems--;
++    for (int i = index; i < this->numitems; i++)
++      this->itembuffer[i] = this->itembuffer[i + 1];
++  }
++
++  void removeFast(const int index) {
++    assert(index >= 0 && index < this->numitems);
++    this->itembuffer[index] = this->itembuffer[--this->numitems];
++  }
++
++  int getLength(void) const {
++    return this->numitems;
++  }
++
++  void truncate(const int length, const int fit = 0) {
++    assert(length <= this->numitems);
++    this->numitems = length;
++    if (fit) this->fit();
++  }
++
++  void push(const Type item) {
++    this->append(item);
++  }
++
++  Type pop(void) {
++    assert(this->numitems > 0);
++    return this->itembuffer[--this->numitems];
++  }
++
++  const Type * getArrayPtr(const int start = 0) const {
++    return &this->itembuffer[start];
++  }
++
++  Type operator[](const int index) const {
++    assert(index >= 0 && index < this->numitems);
++    return this->itembuffer[index];
++  }
++
++  Type & operator[](const int index) {
++    assert(index >= 0 && index < this->numitems);
++    return this->itembuffer[index];
++  }
++
++  int operator==(const SbGuiList<Type> & l) const {
++    if (this == &l) return TRUE;
++    if (this->numitems != l.numitems) return FALSE;
++    for (int i = 0; i < this->numitems; i++)
++      if (this->itembuffer[i] != l.itembuffer[i]) return FALSE;
++    return TRUE;
++  }
++
++  int operator!=(const SbGuiList<Type> & l) const {
++    return !(*this == l);
++  }
++
++protected:
++
++  void expand(const int size) {
++    this->grow(size);
++    this->numitems = size;
++  }
++
++  int getArraySize(void) const {
++    return this->itembuffersize;
++  }
++
++private:
++  void grow(const int size = -1) {
++    // Default behavior is to double array size.
++    if (size == -1) this->itembuffersize <<= 1;
++    else if (size <= this->itembuffersize) return;
++    else { this->itembuffersize = size; }
++
++    Type * newbuffer = new Type[this->itembuffersize];
++    const int n = this->numitems;
++    for (int i = 0; i < n; i++) newbuffer[i] = this->itembuffer[i];
++    if (this->itembuffer != this->builtinbuffer) delete[] this->itembuffer;
++    this->itembuffer = newbuffer;
++  }
++
++  int itembuffersize;
++  int numitems;
++  Type * itembuffer;
++  Type builtinbuffer[DEFAULTSIZE];
++};
++
++#endif // !SOGUI_SBGUILIST_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoAny.cpp.in
+@@ -0,0 +1,690 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/*!
++  \class SoAny SoAny.h
++  \brief The SoAny class is a collection of common toolkit methods.
++
++  SoAny contains internal (ie not accessible to the application
++  programmer) functionality which needs to be "globally" visible to
++  all parts of the toolkit.
++*/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif /* HAVE_CONFIG_H */
++
++#ifdef HAVE_WINDOWS_H
++#include <windows.h> /* GetEnvironmentVariable() */
++#endif /* HAVE_WINDOWS_H */
++
++#include <stdlib.h>
++#include <string.h>
++#include <assert.h>
++
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/elements/SoGLCacheContextElement.h>
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/actions/SoSearchAction.h>
++#include <Inventor/SoInput.h>
++#include <Inventor/SoDB.h>
++#include <Inventor/@Gui@/So at Gui@Object.h>
++#include <Inventor/@Gui@/So at Gui@Cursor.h>
++#include <Inventor/@Gui@/nodes/SoGuiNodes.h>
++#include <Inventor/@Gui@/engines/SoGuiEngines.h>
++
++#include <Inventor/@Gui@/SoAny.h>
++
++static SoAny * single_instance = NULL;
++
++SoSearchAction * SoAny::finder = NULL;
++
++// Following block explains OpenGL cache context handling in some
++// depth. Copied from an email write-up by pederb:
++//
++// The SoGui toolkits use the SoAny class to handle cache context ids
++// and cache context id sharing (cache context ids can be shared on
++// Windows and on Unix if the display and screen are equal).
++//
++// E.g. in SoQt, when a new GL-widget is created, it is registered
++// using SoAny::registerGLContext (from SoQtGLWidget.cpp). When the
++// GL-widget is destructed, SoAny::unregisterGLContext() must be
++// called. Then, in SoGuiRenderArea::initGraphic(),
++// SoAny::getSharedCacheContextId() is called to find a valid cache
++// context id for SoGLRenderAction.
++//
++// What one needs to do is to detect when the GL-context is
++// destructed, and then call SoAny::unregisterGLContext(). Then
++// SoAny::registerGLContext() to register the new context, and then
++// set the new cache context id in the SoGLRenderAction. This can
++// probably be done just by calling SoGuiRenderArea::initGraphic().
++
++class soany_cache_context {
++public:
++  soany_cache_context(void * display, void * screen)
++    : display(display), screen(screen), cacheid(-1) { } 
++  ~soany_cache_context() { }
++
++  SbBool isSameCacheContext(void * displayarg, void * screenarg) const {
++    return (this->display == displayarg && this->screen == screenarg);
++  }
++  SbBool findContext(void * context) const {
++    for (int i = 0; i < this->contextlist.getLength(); i++) {
++      if (this->contextlist[i] == context) return TRUE;
++    }
++    return FALSE;
++  }
++  void * getFirstContext(void) const {
++    assert(this->contextlist.getLength());
++    return this->contextlist[0];
++  }
++  void addContext(void * context) {
++    assert(!this->findContext(context));
++    this->contextlist.append(context);
++  }
++
++  SbBool tryRemoveContext(void * context) {
++    for (int i = 0; i < this->contextlist.getLength(); i++) {
++      if (this->contextlist[i] == context) {
++        this->contextlist.remove(i);
++        return TRUE;
++      }
++    }
++    return FALSE;
++  }
++  SbBool isEmpty(void) const {
++    return this->contextlist.getLength() == 0;
++  }
++  int getCacheContextId(void) {
++    if (this->cacheid < 0) {
++#ifdef __COIN__
++      // Coin has a method for generating an unique cache context id.
++      // Unfortunately, this method does not exists for SGI/TGS Inventor.
++      this->cacheid = (int) SoGLCacheContextElement::getUniqueCacheContext();
++#else // ! __COIN__
++      this->cacheid = soany_cache_context::oiv_counter++;
++#endif // ! __COIN__
++    }
++    return this->cacheid;
++  }
++
++private:
++  void * display;
++  void * screen;
++  int cacheid;
++  SbPList contextlist;
++  static int oiv_counter;
++};
++
++#if 0 // FIXME: not sure if this is ok, check with pederb. 20010806 mortene.
++// A semi-random magic number -- we want to avoid crashing with any
++// cache context id values internally used in SGI / TGS OIV as magic
++// numbers.
++int soany_cache_context::oiv_counter = 4242;
++#else
++int soany_cache_context::oiv_counter = 0;
++#endif
++
++// *************************************************************************
++
++static void soany_atexit_cleanup(void);
++
++void
++SoAny::init()
++{
++  So at Gui@Object::init();
++  So at Gui@Cursor::initClass();
++  SoGuiNodes::initClasses();
++  SoGuiEngines::initClasses();
++  SoAny::atexit((SoAny::atexit_f*)soany_atexit_cleanup, 0);
++  SoAny::atexit((SoAny::atexit_f*)SoAny::cleanup_si, 0);
++}
++
++// private constructor
++SoAny::SoAny(void) 
++  : fatalcb(NULL)
++{
++}
++ 
++// private destructor
++SoAny::~SoAny()
++{
++  for (int i = 0; i < this->cclist.getLength(); i++) {
++    delete (soany_cache_context*) this->cclist[i];
++  }
++}
++
++/*!
++  Returns pointer to the single instance of this class (implemented
++  according to the singleton design pattern).
++*/
++SoAny * 
++SoAny::si(void)
++{
++  if (single_instance == NULL) single_instance = new SoAny;
++  return single_instance;
++}
++
++//  Free memory/resources used by the singleton object. Will be called
++//  automatically on exit.
++void 
++SoAny::cleanup_si(void)
++{
++  delete single_instance;
++  single_instance = NULL;
++  if (SoAny::finder) {
++    delete SoAny::finder;
++    SoAny::finder = NULL;
++  }
++}
++
++/*!  
++  Returns a pointer to any previous context with which GL sharing
++  is possible, or \e NULL if none found.  
++*/
++void * 
++SoAny::getSharedGLContext(void * display, void * screen)
++{
++  for (int i = 0; i < this->cclist.getLength(); i++) {
++    soany_cache_context * cc = (soany_cache_context*) this->cclist[i];
++    if (cc->isSameCacheContext(display, screen)) {
++      return cc->getFirstContext();
++    }
++  }
++  return NULL;
++}
++
++/*!
++  Adds GL context information. Might be platform dependent what the \a
++  display and \a screen will be. Call this method once when the
++  context is created. In the Coin GUI toolkits, \a context will be a
++  pointer to a So at Gui@GLWidget.
++*/
++void 
++SoAny::registerGLContext(void * context, void * display, void * screen)
++{
++#if SO at GUI@_DEBUG && 0 // debug
++  SoDebugError::postInfo("SoAny::registerGLContext",
++                         "context==%p, display==%p, screen==%p",
++                         context, display, screen);
++#endif // debug
++
++  int i, n = this->cclist.getLength();
++  for (i = 0; i < n; i++) {
++    soany_cache_context * cc = (soany_cache_context*) this->cclist[i];
++    if (cc->isSameCacheContext(display, screen)) break;
++  }
++  if (i == n) this->cclist.append(new soany_cache_context(display, screen));
++  soany_cache_context * cc = (soany_cache_context*) this->cclist[i];
++  cc->addContext(context);
++}
++
++/*!
++  Removes a GL context from the list of contexts. Should be called
++  when the context/widget is destructed.
++*/
++void 
++SoAny::unregisterGLContext(void * context)
++{
++#if SO at GUI@_DEBUG && 0 // debug
++  SoDebugError::postInfo("SoAny::unregisterGLContext", "context==%p", context);
++#endif // debug
++
++  for (int i = 0; i < this->cclist.getLength(); i++) {
++    soany_cache_context * cc = (soany_cache_context*) this->cclist[i];
++    if (cc->tryRemoveContext(context)) {
++      if (cc->isEmpty()) {
++        delete cc;
++        this->cclist.remove(i);
++      }
++      return;
++    }
++  }
++  assert(FALSE && "couldn't find context in internal list");
++}
++
++/*!
++  Returns a shared cache context id, to be used as argument
++  in SoGLRenderAction::setCacheContext().
++*/
++int 
++SoAny::getSharedCacheContextId(void * context)
++{
++  for (int i = 0; i < this->cclist.getLength(); i++) {
++    soany_cache_context * cc = (soany_cache_context*) this->cclist[i];
++    if (cc->findContext(context)) return cc->getCacheContextId();
++  }
++#if SO at GUI@_DEBUG
++  SoDebugError::post("SoAny::getSharedCacheContextId",
++                     "could not find shared cache context for context %p "
++                     "(shared context handling not implemented for this "
++                     "toolkit?)", context);
++#endif // SO at GUI@_DEBUG
++  return 0;
++}
++
++/*!
++  Set up a fatal error handler in case of "impossible" errors.  Calls
++  to this function are calls forwarded from
++  So at Gui@::setFatalErrorHandler().
++
++  Returns previous fatal error handler callback, or \c NULL if none.
++
++  \sa So at Gui@::setFatalErrorHandler()
++ */
++So at Gui@::FatalErrorCB *
++SoAny::setFatalErrorHandler(So at Gui@::FatalErrorCB * cb, void * userdataarg)
++{
++  So at Gui@::FatalErrorCB * oldcb = this->fatalcb;
++  this->fatalcb = cb;
++  this->userdata = userdataarg;
++  return oldcb;
++}
++
++/*!
++  In the case of a fatal error condition in the library, this method
++  should be used to invoke the application fatal error handler.
++
++  Returns \c TRUE if an error handler was set up, or \c FALSE if none.
++
++  If no handler was set up, a dialog box with the error string will be
++  shown and then the application will exit.
++
++  A very important issue to be aware of for "client code" around in
++  the So*-libraries is that this function will not return if the
++  application programmer has set up a fatal error handler which throws
++  an exception. Because of this, the "as good as possible" clean-up
++  code around the points of fatal error failures needs to be executed
++  \e before calling this function.
++
++  \sa SoAny::setFatalErrorHandler()
++ */
++SbBool
++SoAny::invokeFatalErrorHandler(SbString errmsg, So at Gui@::FatalErrors errcode)
++{
++  // First trigger the internal clean-up routines.
++  int internals = this->internalfehandlers.getLength();
++  for (int idx = 0; idx < internals; idx++) {
++    SoAny::InternalFatalErrorCB * cb =
++      (SoAny::InternalFatalErrorCB *)this->internalfehandlers[idx];
++    (*cb)(this->internalfedata[idx]);
++  }
++
++  // If no app-programmer registered callback, throw up our own
++  // message dialog.
++  if (this->fatalcb == NULL) {
++    So at Gui@::createSimpleErrorDialog(NULL,
++                                     "Fatal application error",
++                                     errmsg.getString(),
++                                     "Application will exit.");
++    return FALSE;
++  }
++
++  fatalcb(errmsg, errcode, this->userdata);
++  return TRUE;
++}
++
++
++/*!
++  Lets us register an internal callback to run when a fatal error is
++  detected.
++
++  Internal clean-up functions is sometimes necessary because we set up
++  external references to internal resources which may not be valid
++  after a fatal error hits.
++*/
++void
++SoAny::addInternalFatalErrorHandler(SoAny::InternalFatalErrorCB * cb,
++                                    void * userdataarg)
++{
++  this->internalfehandlers.append((void *)cb);
++  this->internalfedata.append(userdataarg);
++}
++
++
++/**************************************************************************/
++
++/*** Singlelinked list for the environment variables. *********************/
++
++/*
++  FIXME: should implement a generic (macro-based) singlelinked list
++  abstraction in C (the following code could be a good starting
++  point). Then axe this code. Then move the various listhandling stuff
++  in the Coin library from the SbList<> template to the C-based one to
++  aid any future transition to pure C. 20010821 mortene.
++
++  UPDATE: SbList isn't really a linked list, but in fact a growable
++  array -- so the code below can not be used as a replacement. Still,
++  we should have a generic linked list class. 20011220 mortene.
++*/
++
++static struct envvar_data * envlist_head = NULL;
++static struct envvar_data * envlist_tail = NULL;
++
++struct envvar_data {
++  char * name;
++  char * val;
++  struct envvar_data * next;
++};
++
++static void
++envlist_append(struct envvar_data * item)
++{
++  item->next = NULL;
++  if (envlist_head == NULL) {
++    envlist_head = item;
++    envlist_tail = item;
++  }
++  else {
++    envlist_tail->next = item;
++    envlist_tail = item;
++  }
++}
++
++/**************************************************************************/
++
++/*
++  When working with MSWindows applications using the library as a DLL,
++  setenv() / getenv() will not work as expected, as the application
++  and the DLL has different instances of the C library with different
++  datastructures on different heaps. That's why we need this
++  abstraction around the C-libs getenv() vs the Win32 API
++  GetEnvironmentVariable() function.
++
++  Note: do not deallocate the returned string -- they are supposed to
++  be permanently available to all callers. Deallocating the resources
++  is the responsibility of the application exit cleanup code.
++*/
++
++const char *
++SoAny::getenv(const char * envname)
++{
++  /* Important note: this code is dulplicated in Coin, Coin-1,
++     So at Gui@/.../common/SoAny.cpp.in (and possibly stable forks of the
++     toolkits).  If you do bugfixes or whatever, keep them in sync! */
++#ifdef HAVE_GETENVIRONMENTVARIABLE
++  int neededsize;
++  neededsize = GetEnvironmentVariable(envname, NULL, 0);
++  /* neededsize includes the \0-terminating character */
++  if ( neededsize >= 1 ) {
++    int resultsize;
++    struct envvar_data * envptr;
++    char * valbuf = (char *) malloc(neededsize);
++    if ( valbuf == NULL ) {
++      /* Augh. Could we handle this any better? */
++      /* If we already bookkeep a buffer for this variable, we /could/ try
++         to reuse it (much work for a non-100% solution).  20030205 larsa */
++      return NULL;
++    }
++    resultsize = GetEnvironmentVariable(envname, valbuf, neededsize);
++    if ( resultsize != (neededsize - 1) ) {
++      /* Augh. Could we handle this any better? */
++      /* How about looping to top and trying again (in case the reason is mt
++         and envval being changed in the background, or maybe just asserting?
++         20030205 larsa */
++      free(valbuf);
++      return NULL;
++    }
++
++    /*
++      The GetEnvironmentVariable() signature forces us to allocate the space
++      for the value string on the outside of the call, as opposed to the UNIX
++      getenv() function.  We therefore have to do bookkeeping and maintain
++      this linked list of allocated buffers that should be cleaned up on exit
++      (atexit()).  We don't keep it for lookup of values - we actually can't
++      use the valus as value caches in case they have been changed from other
++      parts of the application.  We only keep them so we can free them later.
++    */
++
++    /* Try to find bookkeeped envvar buffer among those registered earlier. */
++    envptr = envlist_head;
++    while ( (envptr != NULL) && (strcmp(envptr->name, envname) != 0) )
++      envptr = envptr->next;
++
++    /* We can avoid this if-else by always freeing the envvar_data for the
++       variable upfront, but it's a tad less efficient. */
++    if ( envptr != NULL ) {
++      /* We are already bookkeeping a buffer for this variable.
++       * => free previous value buffer and bookkeep the new one instead */
++      free(envptr->val);
++      envptr->val = valbuf;
++    } else {
++      /* We aren't bookkeeping a buffer for this one yet. */
++      envptr = (struct envvar_data *) malloc(sizeof(struct envvar_data));
++      if ( envptr == NULL ) {
++        /* Augh. Could we handle this any better? */
++	/* We can alternatively ignore the bookkeeping and leak the buffer
++           - 20030205 larsa */
++        free(valbuf);
++        return NULL;
++      }
++      envptr->name = strdup(envname);
++      if ( envptr->name == NULL ) {
++        /* Augh. Could we handle this any better? */
++	/* We can alternatively ignore the bookkeeping and leak the buffer
++           - 20030205 larsa */
++	free(envptr);
++	free(valbuf);
++	return NULL;
++      }
++      envptr->val = valbuf;
++      envlist_append(envptr);
++    }
++    return envptr->val;
++  }
++  return NULL;
++#else /* !HAVE_GETENVIRONMENTVARIABLE */
++  return ::getenv(envname);
++#endif /* !HAVE_GETENVIRONMENTVARIABLE */
++}
++
++/**************************************************************************/
++
++#if defined(HAVE_WIN32_LOADLIBRARY) && defined(HAVE_TLHELP32_H)
++
++#include <tlhelp32.h>
++
++
++typedef HANDLE (WINAPI * CreateToolhelp32Snapshot_t)(DWORD, DWORD);
++typedef BOOL (WINAPI * Module32First_t)(HANDLE, LPMODULEENTRY32);
++typedef BOOL (WINAPI * Module32Next_t)(HANDLE, LPMODULEENTRY32);
++
++static CreateToolhelp32Snapshot_t funCreateToolhelp32Snapshot = NULL;
++static Module32First_t funModule32First = NULL;
++static Module32Next_t funModule32Next = NULL;
++
++
++void
++SoAny::listWin32ProcessModules(void)
++{
++  BOOL ok;
++
++  HINSTANCE kernel32dll = LoadLibrary("kernel32.dll");
++  assert(kernel32dll && "LoadLibrary(''kernel32.dll'') failed");
++
++  funCreateToolhelp32Snapshot = (CreateToolhelp32Snapshot_t)
++    GetProcAddress(kernel32dll, "CreateToolhelp32Snapshot");
++  funModule32First = (Module32First_t)
++    GetProcAddress(kernel32dll, "Module32First");
++  funModule32Next = (Module32Next_t)
++    GetProcAddress(kernel32dll, "Module32Next");
++
++
++  do {
++    if (!funCreateToolhelp32Snapshot || !funModule32First || !funModule32Next) {
++      SoDebugError::postWarning("SoAny::listWin32ProcessModules",
++                                "Tool Help Library not available (NT4?)");
++      break; // goto end of do-while loop
++    }
++    
++    HANDLE tool32snap = funCreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
++    assert((tool32snap != (void *)-1) && "CreateToolhelp32Snapshot() failed");
++    
++    MODULEENTRY32 moduleentry;
++    moduleentry.dwSize = sizeof(MODULEENTRY32);
++    ok = funModule32First(tool32snap, &moduleentry);
++    assert(ok && "Module32First() failed"); 
++    
++    SoDebugError::postInfo("SoAny::listWin32ProcessModules",
++                           "MODULEENTRY32.szModule=='%s', .szExePath=='%s'",
++                           moduleentry.szModule, moduleentry.szExePath);
++    
++    while (funModule32Next(tool32snap, &moduleentry)) {
++      SoDebugError::postInfo("SoAny::listWin32ProcessModules",
++                             "MODULEENTRY32.szModule=='%s', .szExePath=='%s'",
++                             moduleentry.szModule, moduleentry.szExePath);
++    }
++    
++    assert(GetLastError()==ERROR_NO_MORE_FILES && "Module32Next() failed"); 
++
++    ok = CloseHandle(tool32snap);
++    assert(ok && "CloseHandle() failed");
++  } while (0);
++
++  ok = FreeLibrary(kernel32dll);
++  assert(ok && "FreeLibrary() failed");
++}
++
++
++#else // !HAVE_WIN32_LOADLIBRARY || !HAVE_TLHELP32_H
++
++void
++SoAny::listWin32ProcessModules(void)
++{
++  SoDebugError::postWarning("SoAny::listWin32ProcessModules",
++                            "Tool Help Library not available "
++                            "(non-win32 platform?)");
++}
++
++#endif // !HAVE_WIN32_LOADLIBRARY || !HAVE_TLHELP32_H
++
++/**************************************************************************/
++
++char *
++SoAny::strconcat(const char ** stringlist, const char * glue, SbBool glueend) // static
++{
++  int i, gluelen, buflen;
++  char * buffer, * ptr;
++  assert(stringlist);
++  gluelen = 0;
++  buflen = 1; // The Terminator (1982)
++  if ( glue ) gluelen = strlen(glue);
++  for ( i = 0; stringlist[i] != NULL; i++ )
++    buflen += strlen(stringlist[i]) + gluelen;
++  if ( !glueend ) buflen -= gluelen;
++  buffer = new char [buflen];
++  assert(buffer);
++  ptr = buffer;
++  for ( i = 0; stringlist[i] != NULL; i++ ) {
++    int len;
++    len = strlen(stringlist[i]);
++    memcpy(ptr, stringlist[i], len);
++    ptr += len;
++    if ( gluelen && ((stringlist[i+1] != NULL) || glueend) ) {
++      memcpy(ptr, glue, gluelen);
++      ptr += gluelen;
++    }
++  }
++  *ptr = '\0';
++  return buffer;
++}
++
++SoNode *
++SoAny::loadSceneGraph(const char ** stringlist) // static
++{
++  char * buffer = SoAny::strconcat(stringlist, "\n");
++  SoNode * root = SoAny::loadSceneGraph(buffer);
++  delete [] buffer;
++  return root;
++}
++
++SoNode *
++SoAny::loadSceneGraph(char * buffer, unsigned int bufsize) // static
++{
++  SoSeparator * root;
++  SoInput in;
++  in.setBuffer(buffer, bufsize ? bufsize : strlen(buffer));
++  root = SoDB::readAll(&in);
++  return root;
++}
++
++SoNode *
++SoAny::scanSceneForName(SoNode * scene, const char * name, SbBool searchAll)
++{
++  assert(scene->getRefCount() > 0);
++  SoPath * path;
++  if ( SoAny::finder == NULL )
++    SoAny::finder = new SoSearchAction;
++  SoAny::finder->reset();
++  SoAny::finder->setName(SbName(name));
++  SoAny::finder->setInterest(SoSearchAction::FIRST);
++  if ( searchAll ) SoAny::finder->setSearchingAll(TRUE);
++  SoAny::finder->apply(scene);
++  path = SoAny::finder->getPath();
++  return path ? path->getTail() : NULL;
++}
++
++// FIXME: Dummy implementation of sogui_atexit(). Replace with real
++// implementation. kintel 20060209
++void 
++SoAny::atexit(SoAny::atexit_f * fp, int priority)
++{
++  // disabled this, as it is not safe to clean up So at Gui@ after Coin
++  // has been cleaned up. -mortene
++  //
++  // atexit(fp);
++}
++
++static void
++soany_atexit_cleanup(void)
++{
++  struct envvar_data * ptr = envlist_head;
++  while (ptr != NULL) {
++    struct envvar_data * tmp = ptr;
++    free(ptr->name);
++    free(ptr->val);
++    ptr = ptr->next;
++    free(tmp);
++  }
++  envlist_head = NULL;
++  envlist_tail = NULL;
++
++#if defined(HAVE_WIN32_LOADLIBRARY) && defined(HAVE_TLHELP32_H)
++  funCreateToolhelp32Snapshot = NULL;
++  funModule32First = NULL;
++  funModule32Next = NULL;
++#endif
++}
++
++/**************************************************************************/
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoAny.h.in
+@@ -0,0 +1,106 @@
++#ifndef SOANY_H
++#define SOANY_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// This file contains definitions which should _only_ be used during
++// library build. It is not installed for use by the application
++// programmer.
++#ifndef SO at GUI@_INTERNAL
++#error Only for internal use during library build.
++#endif /* !SO at GUI@_INTERNAL */
++
++// ************************************************************************
++
++#include <Inventor/SbPList.h>
++
++#include <Inventor/@Gui@/So at Gui@.h>
++
++class SoNode;
++class SoSearchAction;
++
++// ************************************************************************
++
++class SoAny {
++public:
++  static void init();
++
++  // use the singleton design pattern for access
++  static SoAny * si(void);
++
++  static const char * getenv(const char * e);
++
++  void * getSharedGLContext(void * display, void * screen);
++  void registerGLContext(void * context, void * display, void * screen);
++  void unregisterGLContext(void * context);
++  int getSharedCacheContextId(void * context);
++
++  static void listWin32ProcessModules(void);
++
++  So at Gui@::FatalErrorCB * setFatalErrorHandler(So at Gui@::FatalErrorCB * cb, void * userdata);
++  SbBool invokeFatalErrorHandler(SbString errmsg, So at Gui@::FatalErrors errcode);
++  typedef void InternalFatalErrorCB(void * userdata);
++  void addInternalFatalErrorHandler(SoAny::InternalFatalErrorCB * cb,
++                                    void * ud);
++
++  static char * strconcat(const char ** stringlist, const char * glue = NULL, SbBool glueend = TRUE);
++  static SoNode * loadSceneGraph(const char ** stringlist);
++  static SoNode * loadSceneGraph(char * buffer, unsigned int bufsize = 0);
++  static SoNode * scanSceneForName(SoNode * scene, const char * name, SbBool searchAll = FALSE);
++
++  // FIXME: Dummy sogui_atexit(). Replace with real
++  // implementation. kintel 20060209
++  typedef void atexit_f(void);
++  static void atexit(atexit_f * fp, int priority);
++
++private:
++  SoAny(void);
++  ~SoAny();
++  static void cleanup_si(void);
++
++  // (use SbPList instances to be able to compile properly on SGI /
++  // TGS Inventor aswell as Coin)
++  SbPList cclist;
++  SbPList internalfehandlers, internalfedata;
++
++  So at Gui@::FatalErrorCB * fatalcb;
++  void * userdata;
++
++  static SoSearchAction * finder;
++}; // class SoAny
++
++// ************************************************************************
++
++#endif // ! SOANY_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoAnyMaterialList.cpp.in
+@@ -0,0 +1,457 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif /* HAVE_CONFIG_H */
++
++#include <assert.h>
++#include <string.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#ifdef HAVE_DIRENT_H
++#include <dirent.h>
++#endif
++#ifdef HAVE_UNISTD_H
++#include <unistd.h>
++#endif
++#include <stdlib.h>
++
++#include <Inventor/SbPList.h>
++#include <Inventor/errors/SoDebugError.h>
++
++#include <so at gui@defs.h>
++#include <Inventor/@Gui@/SoAnyMaterialList.h>
++#include <Inventor/@Gui@/SoAny.h>
++
++struct So at Gui@MaterialListCallbackInfo {
++  So at Gui@MaterialListCB * callback;
++  void * closure;
++};
++
++/*!
++  \class SoAnyMaterialList Inventor/@Gui@/SoAnyMaterialList.h
++  \brief The SoAnyMaterialList class is the common code for the MaterialList
++  component classes.
++*/
++
++// *************************************************************************
++
++/*!
++*/
++
++SoAnyMaterialList::SoAnyMaterialList(
++  const char * const dir)
++{
++  this->callbacks = NULL;
++  this->dirpath = NULL;
++  this->directory = NULL;
++  if (dir != NULL)
++    this->dirpath = strcpy(new char [strlen(dir)+1], dir);
++}
++
++/*!
++*/
++
++SoAnyMaterialList::~SoAnyMaterialList(
++  void)
++{
++  if (this->callbacks != NULL) {
++    const int num = this->callbacks->getLength();
++    for (int i = 0; i < num; i++)
++      delete (So at Gui@MaterialListCallbackInfo *) (*this->callbacks)[i];
++    delete this->callbacks;
++  }
++  if (this->dirpath)
++    delete [] this->dirpath;
++  if (this->directory != NULL)
++    this->freeMaterialDirectory();
++}
++
++// *************************************************************************
++
++/*!
++*/
++
++void
++SoAnyMaterialList::addCallback(
++  So at Gui@MaterialListCB * const callback,
++  void * const closure)
++{
++  if (this->callbacks == NULL)
++    this->callbacks = new SbPList;
++  So at Gui@MaterialListCallbackInfo * info =
++    new So at Gui@MaterialListCallbackInfo;
++  info->callback = callback;
++  info->closure = closure;
++  this->callbacks->append(info);
++} // addCallback()
++
++/*!
++*/
++
++void
++SoAnyMaterialList::removeCallback(
++  So at Gui@MaterialListCB * const callback,
++  void * const closure)
++{
++  if (! this->callbacks) {
++#if SO at GUI@_DEBUG
++    SoDebugError::postInfo("SoAnyMaterialList::removeCallback",
++      "component has zero callbacks set.");
++#endif // SO at GUI@_DEBUG
++    return;
++  }
++
++  const int numcallbacks = this->callbacks->getLength();
++  for (int i = 0; i < numcallbacks; i++) {
++    So at Gui@MaterialListCallbackInfo * info =
++      (So at Gui@MaterialListCallbackInfo *) (*this->callbacks)[i];
++    if (info->callback == callback && info->closure == closure) {
++      this->callbacks->remove(i);
++      delete info;
++      return;
++    }
++  }
++
++#if SO at GUI@_DEBUG
++  SoDebugError::postInfo("SoAnyMaterialList::removeCallback",
++    "callback was not set for component.");
++#endif // SO at GUI@_DEBUG
++} // removeCallback()
++
++/*!
++*/
++
++void
++SoAnyMaterialList::invokeCallbacks(
++  SoMaterial * material)
++{
++  if (this->callbacks) {
++    const int numCallbacks = this->callbacks->getLength();
++    for (int i = 0; i < numCallbacks; i++) {
++      So at Gui@MaterialListCallbackInfo * info =
++        (So at Gui@MaterialListCallbackInfo *) (*this->callbacks)[i];
++      info->callback(info->closure, (SoMaterial *) material);
++    }
++  }
++} // invokeCallbacks()
++
++// *************************************************************************
++
++/*!
++  \internal
++
++  This method frees up the memory used by the material-index data strucure.
++*/
++
++void
++SoAnyMaterialList::freeMaterialDirectory(
++  void)
++{
++  if (this->directory == NULL)
++    return;
++  int i, j;
++  if ((this->directory->flags & SO at GUI@_BUILTIN_MATERIALS) == 0) {
++    // all data is allocated
++    for (i = 0; i < this->directory->numGroups; i++) {
++      for (j = 0; j < this->directory->groups[i]->numMaterials; j++) {
++        delete [] (char *) this->directory->groups[i]->materials[j]->data;
++        delete [] (char *) this->directory->groups[i]->materials[j]->name;
++        delete this->directory->groups[i]->materials[j];
++      }
++      delete [] (char *) this->directory->groups[i]->name;
++      delete [] this->directory->groups[i]->materials;
++      delete this->directory->groups[i];
++    }
++    delete [] this->directory->groups;
++  } else {
++    // lots of data is static and should therefore not be freed
++    for (i = 0; i < this->directory->numGroups; i++) {
++      for (j = 0; j < this->directory->groups[i]->numMaterials; j++)
++        delete this->directory->groups[i]->materials[j];
++      delete [] this->directory->groups[i]->materials;
++      delete this->directory->groups[i];
++    }
++    delete [] this->directory->groups;
++  }
++  delete this->directory;
++  this->directory = NULL;
++} // freeMaterialDirectory()
++
++// *************************************************************************
++
++const char *
++SoAnyMaterialList::getMaterialDirectoryPath(
++  void) const
++{
++  return this->dirpath;
++} // getMaterialDirectoryPath()
++
++// *************************************************************************
++
++/*!
++  \internal
++*/
++
++static
++int
++containsFiles(
++  const char * const path)
++{
++#ifdef HAVE_DIRENT_H
++  DIR * directory = opendir(path);
++  struct dirent * entry;
++  struct stat entrystats;
++  if (directory != NULL) {
++    const int pathnamelen = strlen(path);
++    int foundfile = 0;
++    while (! foundfile && (entry = readdir(directory)) != NULL) {
++      if (entry->d_name[0] == '.') continue;
++      char * entrypath = new char [pathnamelen + strlen(entry->d_name) + 2];
++      sprintf(entrypath, "%s/%s", path, entry->d_name);
++      if (stat(entrypath, &entrystats) == 0 &&
++           S_ISREG(entrystats.st_mode)) {
++        delete [] entrypath;
++        closedir(directory);
++        return 1;
++      }
++      delete [] entrypath;
++    }
++    closedir(directory);
++  }
++#endif
++  return 0;
++} // containsFiles()
++
++/*!
++  \internal
++*/
++
++char **
++SoAnyMaterialList::getNonemptySubdirs(// static, private
++  const char * const path)
++{
++#ifdef HAVE_DIRENT_H
++  DIR * dir = opendir(path);
++  if (! dir) return NULL;
++
++  SbPList subdirs;
++  DIR * subdir;
++  const int pathlen = strlen(path) + 2;
++  struct dirent * entry, * subentry;
++  struct stat statbuf, substatbuf;
++  while ((entry = readdir(dir)) != NULL) {
++    if (entry->d_name[0] == '.') continue;
++    int pathnamelen = pathlen + strlen(entry->d_name);
++    char * pathname = new char [ pathnamelen ];
++    sprintf(pathname, "%s/%s", path, entry->d_name);
++    if ((stat(pathname, &statbuf) == 0) && S_ISDIR(statbuf.st_mode)) {
++      if ((subdir = opendir(pathname)) != NULL) {
++        int foundfile = 0;
++        while (! foundfile && (subentry = readdir(subdir)) != NULL) {
++          if (subentry->d_name[0] == '.') continue;
++          char * entrypathname =
++            new char [pathnamelen + strlen(subentry->d_name) + 1];
++          sprintf(entrypathname, "%s/%s", pathname, subentry->d_name);
++          if (stat(entrypathname, &substatbuf) == 0 &&
++               S_ISREG(substatbuf.st_mode)) {
++            foundfile = 1;
++          }
++          delete [] entrypathname;
++        }
++        if (foundfile)
++          subdirs.append(strcpy(new char [strlen(entry->d_name)+1],
++                                  entry->d_name));
++        closedir(subdir);
++      }
++    }
++    delete [] pathname;
++  }
++  closedir(dir);
++
++  const int num = subdirs.getLength();
++  char ** subdirarray = new char * [ num + 1 ];
++  for (int i = 0; i < num; i++)
++    subdirarray[i] = (char *) subdirs[i];
++  subdirarray[num] = NULL;
++  return subdirarray;
++#endif
++  return NULL;
++} // numNonemptySubdirs()
++
++
++/*!
++  \internal
++*/
++
++char **
++SoAnyMaterialList::getRegularFiles(// static, private
++  const char * const path)
++{
++#ifdef HAVE_DIRENT_H
++  DIR * dir = opendir(path);
++  if (! dir) return NULL;
++
++  const int pathlen = strlen(path);
++  SbPList files;
++  struct dirent * entry;
++  while ((entry = readdir(dir)) != NULL) {
++    if (entry->d_name[0] == '.') continue;
++    char * pathname = new char [pathlen + 2 + strlen(entry->d_name)];
++    sprintf(pathname, "%s/%s", path, entry->d_name);
++    struct stat statbuf;
++    if ((stat(pathname, &statbuf) == 0) && S_ISREG(statbuf.st_mode))
++      files.append(strcpy(new char [strlen(entry->d_name)+1],
++                            entry->d_name));
++    delete [] pathname;
++  }
++  closedir(dir);
++
++  const int num = files.getLength();
++  char ** filearray = new char * [ num + 1 ];
++  for (int i = 0; i < num; i++)
++    filearray[i] = (char *) files[i];
++  filearray[num] = NULL;
++  return filearray;
++#endif
++  return NULL;
++} // getRegularFiles()
++
++/*!
++  \internal
++
++  Used for qsort().
++*/
++
++int
++SoAnyMaterialList::qsort_comparator(// static, private
++  const void * itemA,
++  const void * itemB)
++{
++  SO at GUI@_STUB();
++  return 0;
++} // qsort_comparator()
++
++/*!
++*/
++
++So at Gui@MaterialDirectory *
++SoAnyMaterialList::getMaterialDirectory(
++  void)
++{
++  if (this->directory != NULL) // already created
++    return this->directory;
++
++  // get the path to search for materials in
++  SbString path;
++  if (this->dirpath) { path = this->dirpath; }
++
++  const char * envvars[] = {
++    // FIXME: where the hell does the "WALLET" env-var come from?
++    // 20020109 mortene.
++    "SO_MATERIAL_DIR", "WALLET", "COIN_HOME"
++  };
++
++  for (unsigned int i=0; i < (sizeof(envvars) / sizeof(char *)); i++) {
++    if (path.getLength() == 0) {
++      const char * p = SoAny::si()->getenv(envvars[i]);
++      if (p) { path = p; }
++    }
++  }
++
++  if (path.getLength() > 0) { path += "/materials"; }
++  else {
++    const char * p = SoAny::si()->getenv("OIVHOME");
++    if (p) {
++      path = p;
++      // FIXME: use DIRSEP string? ????-??-?? larsa.
++      path += "/data/materials";
++    }
++  }
++
++  this->directory = new So at Gui@MaterialDirectory;
++  this->directory->flags = 0;
++  this->directory->current = 0;
++
++  SbBool founddiskmaterials = FALSE;
++
++  if (path.getLength() > 0) {
++#if SO at GUI@_DEBUG && 0 // debug
++    SoDebugError::postInfo("SoAnyMaterialList::getMaterialDirectory",
++                           "scanning '%s'", path.getString());
++#endif // debug
++    char ** subdirs = SoAnyMaterialList::getNonemptySubdirs(path.getString());
++    if (subdirs) {
++      founddiskmaterials = TRUE;
++      int numsubdirs;
++      for (numsubdirs = 0; subdirs[numsubdirs] != NULL; numsubdirs++) { }
++      this->directory->numGroups = numsubdirs;
++      this->directory->groups = new So at Gui@MaterialGroup * [ numsubdirs ];
++      for (int subdir = 0; subdir < numsubdirs; subdir++) {
++        this->directory->groups[subdir] = new So at Gui@MaterialGroup;
++        this->directory->groups[subdir]->name = subdirs[subdir];
++        char * subdirname =
++          new char [strlen(path.getString()) + strlen(subdirs[subdir]) + 2];
++        sprintf(subdirname, "%s/%s", path.getString(), subdirs[subdir]);
++        char ** files = SoAnyMaterialList::getRegularFiles(subdirname);
++        assert(files != NULL);
++        int numfiles;
++        for (numfiles = 0; files[numfiles] != NULL; numfiles++) { }
++        this->directory->groups[subdir]->numMaterials = numfiles;
++        this->directory->groups[subdir]->materials =
++          new So at Gui@Material * [ numfiles ];
++        for (int file = 0; file < numfiles; file++) {
++          this->directory->groups[subdir]->materials[file] =
++            new So at Gui@Material;
++          this->directory->groups[subdir]->materials[file]->name =
++            files[file];
++          char * buf = new char [strlen(subdirname) + strlen(files[file]) + 2];
++          sprintf(buf, "%s/%s", subdirname, files[file]);
++          this->directory->groups[subdir]->materials[file]->data = buf;
++        }
++        delete [] files; // actual strings are transfered, don't delete them!
++        delete [] subdirname;
++      }
++      delete [] subdirs; // actual strings are transfered, don't delete them!
++    }
++  }
++
++  // fallback on builtins
++  if (!founddiskmaterials) { this->setupBuiltinMaterials(this->directory); }
++  return this->directory;
++} // getMaterialDirectory()
++
++// *************************************************************************
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoAnyMaterialList.h.in
+@@ -0,0 +1,100 @@
++#ifndef SOANY_MATERIALLIST_H
++#define SOANY_MATERIALLIST_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/So at Gui@MaterialList.h>
++
++class SbPList;
++class SoMaterial;
++
++// *************************************************************************
++
++#define SO at GUI@_BUILTIN_MATERIALS 0x0001
++
++struct So at Gui@Material {
++  const char * name;
++  const char * data;
++};
++
++struct So at Gui@MaterialGroup {
++  const char * name;
++  short numMaterials;
++  So at Gui@Material ** materials;
++  @WIDGET@ menuitem;
++};
++
++struct So at Gui@MaterialDirectory {
++  short flags;
++  short numGroups;
++  So at Gui@MaterialGroup ** groups;
++  short current;
++};
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API SoAnyMaterialList {
++public:
++  SoAnyMaterialList(const char * const dir);
++  ~SoAnyMaterialList(void);
++
++  void addCallback(
++    So at Gui@MaterialListCB * const callback, void * const closure);
++  void removeCallback(
++    So at Gui@MaterialListCB * const callback, void * const closure);
++  void invokeCallbacks(SoMaterial * material);
++
++  const char * getMaterialDirectoryPath(void) const;
++  So at Gui@MaterialDirectory * getMaterialDirectory(void);
++
++private:
++  void setupBuiltinMaterials(So at Gui@MaterialDirectory * const index) const;
++  void freeMaterialDirectory(void);
++
++  static char ** getNonemptySubdirs(const char * const path);
++  static char ** getRegularFiles(const char * const path);
++
++  static int qsort_comparator(const void * itemA, const void * itemB);
++
++private:
++  SbPList * callbacks;
++  char * dirpath;
++  So at Gui@MaterialDirectory * directory;
++
++}; // class SoAnyMaterialList
++
++// *************************************************************************
++
++#endif // ! SOANY_MATERIALLIST_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoAnyMaterialListBuiltins.cpp.in
+@@ -0,0 +1,1492 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/**************************************************************************
++ * IMPORTANT NOTICE
++ * Be aware that the file So at Gui@MaterialListBuiltins.cpp is generated from
++ * the file So at Gui@MaterialListBuiltins.cpp.m4, so changes has to be done in
++ * the source file with the m4 macros.  The generation is done manually,
++ * since it is no point in making this project depend on the user having
++ * m4 installed.
++ **************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <assert.h>
++#include <string.h>
++
++#include <so at gui@defs.h>
++#include <Inventor/@Gui@/SoAnyMaterialList.h>
++
++#ifdef WITH_STATIC_DEFAULTS
++#include <materials/materials.h>
++#endif // WITH_STATIC_DEFAULTS
++
++// *************************************************************************
++
++#ifdef WITH_STATIC_DEFAULTS
++static
++const char *
++builtin_material_names[] = {
++  "artdeco",
++    "artdeco.0",
++    "artdeco.1",
++    "artdeco.2",
++    "artdeco.3",
++    "artdeco.4",
++    "artdeco.5",
++    "artdeco.6",
++    "artdeco.7",
++    "artdeco.8",
++    "artdeco.9",
++    "artdeco.10",
++    "artdeco.11",
++    "artdeco.12",
++    "artdeco.13",
++    "artdeco.14",
++    "artdeco.15",
++    "artdeco.16",
++    "artdeco.17",
++    "artdeco.18",
++    "artdeco.19",
++    "artdeco.20",
++    "artdeco.21",
++    "artdeco.22",
++    "artdeco.23",
++    "artdeco.24",
++    "artdeco.25",
++    "artdeco.26",
++    "artdeco.27",
++    "artdeco.28",
++    "artdeco.29",
++    "artdeco.30",
++    "artdeco.31",
++    "artdeco.32",
++    "artdeco.33",
++    "artdeco.34",
++  "autumn",
++    "autumn.0",
++    "autumn.1",
++    "autumn.2",
++    "autumn.3",
++    "autumn.4",
++    "autumn.5",
++    "autumn.6",
++    "autumn.7",
++    "autumn.8",
++    "autumn.9",
++    "autumn.10",
++    "autumn.11",
++    "autumn.12",
++    "autumn.13",
++    "autumn.14",
++    "autumn.15",
++    "autumn.16",
++    "autumn.17",
++    "autumn.18",
++    "autumn.19",
++    "autumn.20",
++    "autumn.21",
++    "autumn.22",
++    "autumn.23",
++    "autumn.24",
++    "autumn.25",
++    "autumn.26",
++    "autumn.27",
++    "autumn.28",
++    "autumn.29",
++    "autumn.30",
++    "autumn.31",
++    "autumn.32",
++    "autumn.33",
++    "autumn.34",
++  "glass",
++    "glass.0",
++    "glass.1",
++    "glass.2",
++    "glass.3",
++    "glass.4",
++    "glass.5",
++    "glass.6",
++    "glass.7",
++    "glass.8",
++    "glass.9",
++    "glass.10",
++    "glass.11",
++    "glass.12",
++    "glass.13",
++    "glass.14",
++    "glass.15",
++    "glass.16",
++    "glass.17",
++    "glass.18",
++    "glass.19",
++    "glass.20",
++    "glass.21",
++    "glass.22",
++    "glass.23",
++    "glass.24",
++    "glass.25",
++    "glass.26",
++    "glass.27",
++    "glass.28",
++    "glass.29",
++    "glass.30",
++    "glass.31",
++    "glass.32",
++    "glass.33",
++    "glass.34",
++  "metal",
++    "metal.0",
++    "metal.1",
++    "metal.2",
++    "metal.3",
++    "metal.4",
++    "metal.5",
++    "metal.6",
++    "metal.7",
++    "metal.8",
++    "metal.9",
++    "metal.10",
++    "metal.11",
++    "metal.12",
++    "metal.13",
++    "metal.14",
++    "metal.15",
++    "metal.16",
++    "metal.17",
++    "metal.18",
++    "metal.19",
++    "metal.20",
++    "metal.21",
++    "metal.22",
++    "metal.23",
++    "metal.24",
++    "metal.25",
++    "metal.26",
++    "metal.27",
++    "metal.28",
++    "metal.29",
++    "metal.30",
++    "metal.31",
++    "metal.32",
++    "metal.33",
++    "metal.34",
++  "neon",
++    "neon.0",
++    "neon.1",
++    "neon.2",
++    "neon.3",
++    "neon.4",
++    "neon.5",
++    "neon.6",
++    "neon.7",
++    "neon.8",
++    "neon.9",
++    "neon.10",
++    "neon.11",
++    "neon.12",
++    "neon.13",
++    "neon.14",
++    "neon.15",
++    "neon.16",
++    "neon.17",
++    "neon.18",
++    "neon.19",
++    "neon.20",
++    "neon.21",
++    "neon.22",
++    "neon.23",
++    "neon.24",
++    "neon.25",
++    "neon.26",
++    "neon.27",
++    "neon.28",
++    "neon.29",
++    "neon.30",
++    "neon.31",
++    "neon.32",
++    "neon.33",
++    "neon.34",
++  "rococo",
++    "rococo.0",
++    "rococo.1",
++    "rococo.2",
++    "rococo.3",
++    "rococo.4",
++    "rococo.5",
++    "rococo.6",
++    "rococo.7",
++    "rococo.8",
++    "rococo.9",
++    "rococo.10",
++    "rococo.11",
++    "rococo.12",
++    "rococo.13",
++    "rococo.14",
++    "rococo.15",
++    "rococo.16",
++    "rococo.17",
++    "rococo.18",
++    "rococo.19",
++    "rococo.20",
++    "rococo.21",
++    "rococo.22",
++    "rococo.23",
++    "rococo.24",
++    "rococo.25",
++    "rococo.26",
++    "rococo.27",
++    "rococo.28",
++    "rococo.29",
++    "rococo.30",
++    "rococo.31",
++    "rococo.32",
++    "rococo.33",
++    "rococo.34",
++  "santafe",
++    "santafe.0",
++    "santafe.1",
++    "santafe.2",
++    "santafe.3",
++    "santafe.4",
++    "santafe.5",
++    "santafe.6",
++    "santafe.7",
++    "santafe.8",
++    "santafe.9",
++    "santafe.10",
++    "santafe.11",
++    "santafe.12",
++    "santafe.13",
++    "santafe.14",
++    "santafe.15",
++    "santafe.16",
++    "santafe.17",
++    "santafe.18",
++    "santafe.19",
++    "santafe.20",
++    "santafe.21",
++    "santafe.22",
++    "santafe.23",
++    "santafe.24",
++    "santafe.25",
++    "santafe.26",
++    "santafe.27",
++    "santafe.28",
++    "santafe.29",
++    "santafe.30",
++    "santafe.31",
++    "santafe.32",
++    "santafe.33",
++    "santafe.34",
++  "sheen",
++    "sheen.0",
++    "sheen.1",
++    "sheen.2",
++    "sheen.3",
++    "sheen.4",
++    "sheen.5",
++    "sheen.6",
++    "sheen.7",
++    "sheen.8",
++    "sheen.9",
++    "sheen.10",
++    "sheen.11",
++    "sheen.12",
++    "sheen.13",
++    "sheen.14",
++    "sheen.15",
++    "sheen.16",
++    "sheen.17",
++    "sheen.18",
++    "sheen.19",
++    "sheen.20",
++    "sheen.21",
++    "sheen.22",
++    "sheen.23",
++    "sheen.24",
++    "sheen.25",
++    "sheen.26",
++    "sheen.27",
++    "sheen.28",
++    "sheen.29",
++    "sheen.30",
++    "sheen.31",
++    "sheen.32",
++    "sheen.33",
++    "sheen.34",
++  "silky",
++    "silky.0",
++    "silky.1",
++    "silky.2",
++    "silky.3",
++    "silky.4",
++    "silky.5",
++    "silky.6",
++    "silky.7",
++    "silky.8",
++    "silky.9",
++    "silky.10",
++    "silky.11",
++    "silky.12",
++    "silky.13",
++    "silky.14",
++    "silky.15",
++    "silky.16",
++    "silky.17",
++    "silky.18",
++    "silky.19",
++    "silky.20",
++    "silky.21",
++    "silky.22",
++    "silky.23",
++    "silky.24",
++    "silky.25",
++    "silky.26",
++    "silky.27",
++    "silky.28",
++    "silky.29",
++    "silky.30",
++    "silky.31",
++    "silky.32",
++    "silky.33",
++    "silky.34",
++  "spring",
++    "spring.0",
++    "spring.1",
++    "spring.2",
++    "spring.3",
++    "spring.4",
++    "spring.5",
++    "spring.6",
++    "spring.7",
++    "spring.8",
++    "spring.9",
++    "spring.10",
++    "spring.11",
++    "spring.12",
++    "spring.13",
++    "spring.14",
++    "spring.15",
++    "spring.16",
++    "spring.17",
++    "spring.18",
++    "spring.19",
++    "spring.20",
++    "spring.21",
++    "spring.22",
++    "spring.23",
++    "spring.24",
++    "spring.25",
++    "spring.26",
++    "spring.27",
++    "spring.28",
++    "spring.29",
++    "spring.30",
++    "spring.31",
++    "spring.32",
++    "spring.33",
++    "spring.34",
++  "summer",
++    "summer.0",
++    "summer.1",
++    "summer.2",
++    "summer.3",
++    "summer.4",
++    "summer.5",
++    "summer.6",
++    "summer.7",
++    "summer.8",
++    "summer.9",
++    "summer.10",
++    "summer.11",
++    "summer.12",
++    "summer.13",
++    "summer.14",
++    "summer.15",
++    "summer.16",
++    "summer.17",
++    "summer.18",
++    "summer.19",
++    "summer.20",
++    "summer.21",
++    "summer.22",
++    "summer.23",
++    "summer.24",
++    "summer.25",
++    "summer.26",
++    "summer.27",
++    "summer.28",
++    "summer.29",
++    "summer.30",
++    "summer.31",
++    "summer.32",
++    "summer.33",
++    "summer.34",
++  "tropical",
++    "tropical.0",
++    "tropical.1",
++    "tropical.2",
++    "tropical.3",
++    "tropical.4",
++    "tropical.5",
++    "tropical.6",
++    "tropical.7",
++    "tropical.8",
++    "tropical.9",
++    "tropical.10",
++    "tropical.11",
++    "tropical.12",
++    "tropical.13",
++    "tropical.14",
++    "tropical.15",
++    "tropical.16",
++    "tropical.17",
++    "tropical.18",
++    "tropical.19",
++    "tropical.20",
++    "tropical.21",
++    "tropical.22",
++    "tropical.23",
++    "tropical.24",
++    "tropical.25",
++    "tropical.26",
++    "tropical.27",
++    "tropical.28",
++    "tropical.29",
++    "tropical.30",
++    "tropical.31",
++    "tropical.32",
++    "tropical.33",
++    "tropical.34",
++  "winter",
++    "winter.0",
++    "winter.1",
++    "winter.2",
++    "winter.3",
++    "winter.4",
++    "winter.5",
++    "winter.6",
++    "winter.7",
++    "winter.8",
++    "winter.9",
++    "winter.10",
++    "winter.11",
++    "winter.12",
++    "winter.13",
++    "winter.14",
++    "winter.15",
++    "winter.16",
++    "winter.17",
++    "winter.18",
++    "winter.19",
++    "winter.20",
++    "winter.21",
++    "winter.22",
++    "winter.23",
++    "winter.24",
++    "winter.25",
++    "winter.26",
++    "winter.27",
++    "winter.28",
++    "winter.29",
++    "winter.30",
++    "winter.31",
++    "winter.32",
++    "winter.33",
++    "winter.34",
++  NULL
++}; // builtin_material_names
++#endif // WITH_STATIC_DEFAULTS
++
++// *************************************************************************
++
++/*!
++  \internal
++
++  This method fills in the So at Gui@MaterialDirectory structure with the builtin
++  material data.
++*/
++
++void
++SoAnyMaterialList::setupBuiltinMaterials(// private
++  So at Gui@MaterialDirectory * const index) const
++{
++  assert(index != NULL);
++  index->numGroups = 0;
++  index->groups = NULL;
++#ifdef WITH_STATIC_DEFAULTS
++  index->flags |= SO at GUI@_BUILTIN_MATERIALS;
++  index->numGroups = 13;
++  index->groups = new So at Gui@MaterialGroup * [ 13 ];
++  for (int i = 0; i < index->numGroups; i++) {
++    index->groups[i] = new So at Gui@MaterialGroup;
++    index->groups[i]->numMaterials = 35;
++    index->groups[i]->materials = new So at Gui@Material * [ 35 ];
++    for (int j = 0; j < 35; j++) {
++      index->groups[i]->materials[j] = new So at Gui@Material;
++    }
++  }
++
++  index->groups[0]->name = builtin_material_names[0];
++  index->groups[0]->materials[0]->name = builtin_material_names[1];
++  index->groups[0]->materials[0]->data = artdeco0_iv;
++  index->groups[0]->materials[1]->name = builtin_material_names[2];
++  index->groups[0]->materials[1]->data = artdeco1_iv;
++  index->groups[0]->materials[2]->name = builtin_material_names[3];
++  index->groups[0]->materials[2]->data = artdeco2_iv;
++  index->groups[0]->materials[3]->name = builtin_material_names[4];
++  index->groups[0]->materials[3]->data = artdeco3_iv;
++  index->groups[0]->materials[4]->name = builtin_material_names[5];
++  index->groups[0]->materials[4]->data = artdeco4_iv;
++  index->groups[0]->materials[5]->name = builtin_material_names[6];
++  index->groups[0]->materials[5]->data = artdeco5_iv;
++  index->groups[0]->materials[6]->name = builtin_material_names[7];
++  index->groups[0]->materials[6]->data = artdeco6_iv;
++  index->groups[0]->materials[7]->name = builtin_material_names[8];
++  index->groups[0]->materials[7]->data = artdeco7_iv;
++  index->groups[0]->materials[8]->name = builtin_material_names[9];
++  index->groups[0]->materials[8]->data = artdeco8_iv;
++  index->groups[0]->materials[9]->name = builtin_material_names[10];
++  index->groups[0]->materials[9]->data = artdeco9_iv;
++  index->groups[0]->materials[10]->name = builtin_material_names[11];
++  index->groups[0]->materials[10]->data = artdeco10_iv;
++  index->groups[0]->materials[11]->name = builtin_material_names[12];
++  index->groups[0]->materials[11]->data = artdeco11_iv;
++  index->groups[0]->materials[12]->name = builtin_material_names[13];
++  index->groups[0]->materials[12]->data = artdeco12_iv;
++  index->groups[0]->materials[13]->name = builtin_material_names[14];
++  index->groups[0]->materials[13]->data = artdeco13_iv;
++  index->groups[0]->materials[14]->name = builtin_material_names[15];
++  index->groups[0]->materials[14]->data = artdeco14_iv;
++  index->groups[0]->materials[15]->name = builtin_material_names[16];
++  index->groups[0]->materials[15]->data = artdeco15_iv;
++  index->groups[0]->materials[16]->name = builtin_material_names[17];
++  index->groups[0]->materials[16]->data = artdeco16_iv;
++  index->groups[0]->materials[17]->name = builtin_material_names[18];
++  index->groups[0]->materials[17]->data = artdeco17_iv;
++  index->groups[0]->materials[18]->name = builtin_material_names[19];
++  index->groups[0]->materials[18]->data = artdeco18_iv;
++  index->groups[0]->materials[19]->name = builtin_material_names[20];
++  index->groups[0]->materials[19]->data = artdeco19_iv;
++  index->groups[0]->materials[20]->name = builtin_material_names[21];
++  index->groups[0]->materials[20]->data = artdeco20_iv;
++  index->groups[0]->materials[21]->name = builtin_material_names[22];
++  index->groups[0]->materials[21]->data = artdeco21_iv;
++  index->groups[0]->materials[22]->name = builtin_material_names[23];
++  index->groups[0]->materials[22]->data = artdeco22_iv;
++  index->groups[0]->materials[23]->name = builtin_material_names[24];
++  index->groups[0]->materials[23]->data = artdeco23_iv;
++  index->groups[0]->materials[24]->name = builtin_material_names[25];
++  index->groups[0]->materials[24]->data = artdeco24_iv;
++  index->groups[0]->materials[25]->name = builtin_material_names[26];
++  index->groups[0]->materials[25]->data = artdeco25_iv;
++  index->groups[0]->materials[26]->name = builtin_material_names[27];
++  index->groups[0]->materials[26]->data = artdeco26_iv;
++  index->groups[0]->materials[27]->name = builtin_material_names[28];
++  index->groups[0]->materials[27]->data = artdeco27_iv;
++  index->groups[0]->materials[28]->name = builtin_material_names[29];
++  index->groups[0]->materials[28]->data = artdeco28_iv;
++  index->groups[0]->materials[29]->name = builtin_material_names[30];
++  index->groups[0]->materials[29]->data = artdeco29_iv;
++  index->groups[0]->materials[30]->name = builtin_material_names[31];
++  index->groups[0]->materials[30]->data = artdeco30_iv;
++  index->groups[0]->materials[31]->name = builtin_material_names[32];
++  index->groups[0]->materials[31]->data = artdeco31_iv;
++  index->groups[0]->materials[32]->name = builtin_material_names[33];
++  index->groups[0]->materials[32]->data = artdeco32_iv;
++  index->groups[0]->materials[33]->name = builtin_material_names[34];
++  index->groups[0]->materials[33]->data = artdeco33_iv;
++  index->groups[0]->materials[34]->name = builtin_material_names[35];
++  index->groups[0]->materials[34]->data = artdeco34_iv;
++  index->groups[1]->name = builtin_material_names[36];
++  index->groups[1]->materials[0]->name = builtin_material_names[37];
++  index->groups[1]->materials[0]->data = autumn0_iv;
++  index->groups[1]->materials[1]->name = builtin_material_names[38];
++  index->groups[1]->materials[1]->data = autumn1_iv;
++  index->groups[1]->materials[2]->name = builtin_material_names[39];
++  index->groups[1]->materials[2]->data = autumn2_iv;
++  index->groups[1]->materials[3]->name = builtin_material_names[40];
++  index->groups[1]->materials[3]->data = autumn3_iv;
++  index->groups[1]->materials[4]->name = builtin_material_names[41];
++  index->groups[1]->materials[4]->data = autumn4_iv;
++  index->groups[1]->materials[5]->name = builtin_material_names[42];
++  index->groups[1]->materials[5]->data = autumn5_iv;
++  index->groups[1]->materials[6]->name = builtin_material_names[43];
++  index->groups[1]->materials[6]->data = autumn6_iv;
++  index->groups[1]->materials[7]->name = builtin_material_names[44];
++  index->groups[1]->materials[7]->data = autumn7_iv;
++  index->groups[1]->materials[8]->name = builtin_material_names[45];
++  index->groups[1]->materials[8]->data = autumn8_iv;
++  index->groups[1]->materials[9]->name = builtin_material_names[46];
++  index->groups[1]->materials[9]->data = autumn9_iv;
++  index->groups[1]->materials[10]->name = builtin_material_names[47];
++  index->groups[1]->materials[10]->data = autumn10_iv;
++  index->groups[1]->materials[11]->name = builtin_material_names[48];
++  index->groups[1]->materials[11]->data = autumn11_iv;
++  index->groups[1]->materials[12]->name = builtin_material_names[49];
++  index->groups[1]->materials[12]->data = autumn12_iv;
++  index->groups[1]->materials[13]->name = builtin_material_names[50];
++  index->groups[1]->materials[13]->data = autumn13_iv;
++  index->groups[1]->materials[14]->name = builtin_material_names[51];
++  index->groups[1]->materials[14]->data = autumn14_iv;
++  index->groups[1]->materials[15]->name = builtin_material_names[52];
++  index->groups[1]->materials[15]->data = autumn15_iv;
++  index->groups[1]->materials[16]->name = builtin_material_names[53];
++  index->groups[1]->materials[16]->data = autumn16_iv;
++  index->groups[1]->materials[17]->name = builtin_material_names[54];
++  index->groups[1]->materials[17]->data = autumn17_iv;
++  index->groups[1]->materials[18]->name = builtin_material_names[55];
++  index->groups[1]->materials[18]->data = autumn18_iv;
++  index->groups[1]->materials[19]->name = builtin_material_names[56];
++  index->groups[1]->materials[19]->data = autumn19_iv;
++  index->groups[1]->materials[20]->name = builtin_material_names[57];
++  index->groups[1]->materials[20]->data = autumn20_iv;
++  index->groups[1]->materials[21]->name = builtin_material_names[58];
++  index->groups[1]->materials[21]->data = autumn21_iv;
++  index->groups[1]->materials[22]->name = builtin_material_names[59];
++  index->groups[1]->materials[22]->data = autumn22_iv;
++  index->groups[1]->materials[23]->name = builtin_material_names[60];
++  index->groups[1]->materials[23]->data = autumn23_iv;
++  index->groups[1]->materials[24]->name = builtin_material_names[61];
++  index->groups[1]->materials[24]->data = autumn24_iv;
++  index->groups[1]->materials[25]->name = builtin_material_names[62];
++  index->groups[1]->materials[25]->data = autumn25_iv;
++  index->groups[1]->materials[26]->name = builtin_material_names[63];
++  index->groups[1]->materials[26]->data = autumn26_iv;
++  index->groups[1]->materials[27]->name = builtin_material_names[64];
++  index->groups[1]->materials[27]->data = autumn27_iv;
++  index->groups[1]->materials[28]->name = builtin_material_names[65];
++  index->groups[1]->materials[28]->data = autumn28_iv;
++  index->groups[1]->materials[29]->name = builtin_material_names[66];
++  index->groups[1]->materials[29]->data = autumn29_iv;
++  index->groups[1]->materials[30]->name = builtin_material_names[67];
++  index->groups[1]->materials[30]->data = autumn30_iv;
++  index->groups[1]->materials[31]->name = builtin_material_names[68];
++  index->groups[1]->materials[31]->data = autumn31_iv;
++  index->groups[1]->materials[32]->name = builtin_material_names[69];
++  index->groups[1]->materials[32]->data = autumn32_iv;
++  index->groups[1]->materials[33]->name = builtin_material_names[70];
++  index->groups[1]->materials[33]->data = autumn33_iv;
++  index->groups[1]->materials[34]->name = builtin_material_names[71];
++  index->groups[1]->materials[34]->data = autumn34_iv;
++  index->groups[2]->name = builtin_material_names[72];
++  index->groups[2]->materials[0]->name = builtin_material_names[73];
++  index->groups[2]->materials[0]->data = glass0_iv;
++  index->groups[2]->materials[1]->name = builtin_material_names[74];
++  index->groups[2]->materials[1]->data = glass1_iv;
++  index->groups[2]->materials[2]->name = builtin_material_names[75];
++  index->groups[2]->materials[2]->data = glass2_iv;
++  index->groups[2]->materials[3]->name = builtin_material_names[76];
++  index->groups[2]->materials[3]->data = glass3_iv;
++  index->groups[2]->materials[4]->name = builtin_material_names[77];
++  index->groups[2]->materials[4]->data = glass4_iv;
++  index->groups[2]->materials[5]->name = builtin_material_names[78];
++  index->groups[2]->materials[5]->data = glass5_iv;
++  index->groups[2]->materials[6]->name = builtin_material_names[79];
++  index->groups[2]->materials[6]->data = glass6_iv;
++  index->groups[2]->materials[7]->name = builtin_material_names[80];
++  index->groups[2]->materials[7]->data = glass7_iv;
++  index->groups[2]->materials[8]->name = builtin_material_names[81];
++  index->groups[2]->materials[8]->data = glass8_iv;
++  index->groups[2]->materials[9]->name = builtin_material_names[82];
++  index->groups[2]->materials[9]->data = glass9_iv;
++  index->groups[2]->materials[10]->name = builtin_material_names[83];
++  index->groups[2]->materials[10]->data = glass10_iv;
++  index->groups[2]->materials[11]->name = builtin_material_names[84];
++  index->groups[2]->materials[11]->data = glass11_iv;
++  index->groups[2]->materials[12]->name = builtin_material_names[85];
++  index->groups[2]->materials[12]->data = glass12_iv;
++  index->groups[2]->materials[13]->name = builtin_material_names[86];
++  index->groups[2]->materials[13]->data = glass13_iv;
++  index->groups[2]->materials[14]->name = builtin_material_names[87];
++  index->groups[2]->materials[14]->data = glass14_iv;
++  index->groups[2]->materials[15]->name = builtin_material_names[88];
++  index->groups[2]->materials[15]->data = glass15_iv;
++  index->groups[2]->materials[16]->name = builtin_material_names[89];
++  index->groups[2]->materials[16]->data = glass16_iv;
++  index->groups[2]->materials[17]->name = builtin_material_names[90];
++  index->groups[2]->materials[17]->data = glass17_iv;
++  index->groups[2]->materials[18]->name = builtin_material_names[91];
++  index->groups[2]->materials[18]->data = glass18_iv;
++  index->groups[2]->materials[19]->name = builtin_material_names[92];
++  index->groups[2]->materials[19]->data = glass19_iv;
++  index->groups[2]->materials[20]->name = builtin_material_names[93];
++  index->groups[2]->materials[20]->data = glass20_iv;
++  index->groups[2]->materials[21]->name = builtin_material_names[94];
++  index->groups[2]->materials[21]->data = glass21_iv;
++  index->groups[2]->materials[22]->name = builtin_material_names[95];
++  index->groups[2]->materials[22]->data = glass22_iv;
++  index->groups[2]->materials[23]->name = builtin_material_names[96];
++  index->groups[2]->materials[23]->data = glass23_iv;
++  index->groups[2]->materials[24]->name = builtin_material_names[97];
++  index->groups[2]->materials[24]->data = glass24_iv;
++  index->groups[2]->materials[25]->name = builtin_material_names[98];
++  index->groups[2]->materials[25]->data = glass25_iv;
++  index->groups[2]->materials[26]->name = builtin_material_names[99];
++  index->groups[2]->materials[26]->data = glass26_iv;
++  index->groups[2]->materials[27]->name = builtin_material_names[100];
++  index->groups[2]->materials[27]->data = glass27_iv;
++  index->groups[2]->materials[28]->name = builtin_material_names[101];
++  index->groups[2]->materials[28]->data = glass28_iv;
++  index->groups[2]->materials[29]->name = builtin_material_names[102];
++  index->groups[2]->materials[29]->data = glass29_iv;
++  index->groups[2]->materials[30]->name = builtin_material_names[103];
++  index->groups[2]->materials[30]->data = glass30_iv;
++  index->groups[2]->materials[31]->name = builtin_material_names[104];
++  index->groups[2]->materials[31]->data = glass31_iv;
++  index->groups[2]->materials[32]->name = builtin_material_names[105];
++  index->groups[2]->materials[32]->data = glass32_iv;
++  index->groups[2]->materials[33]->name = builtin_material_names[106];
++  index->groups[2]->materials[33]->data = glass33_iv;
++  index->groups[2]->materials[34]->name = builtin_material_names[107];
++  index->groups[2]->materials[34]->data = glass34_iv;
++  index->groups[3]->name = builtin_material_names[108];
++  index->groups[3]->materials[0]->name = builtin_material_names[109];
++  index->groups[3]->materials[0]->data = metal0_iv;
++  index->groups[3]->materials[1]->name = builtin_material_names[110];
++  index->groups[3]->materials[1]->data = metal1_iv;
++  index->groups[3]->materials[2]->name = builtin_material_names[111];
++  index->groups[3]->materials[2]->data = metal2_iv;
++  index->groups[3]->materials[3]->name = builtin_material_names[112];
++  index->groups[3]->materials[3]->data = metal3_iv;
++  index->groups[3]->materials[4]->name = builtin_material_names[113];
++  index->groups[3]->materials[4]->data = metal4_iv;
++  index->groups[3]->materials[5]->name = builtin_material_names[114];
++  index->groups[3]->materials[5]->data = metal5_iv;
++  index->groups[3]->materials[6]->name = builtin_material_names[115];
++  index->groups[3]->materials[6]->data = metal6_iv;
++  index->groups[3]->materials[7]->name = builtin_material_names[116];
++  index->groups[3]->materials[7]->data = metal7_iv;
++  index->groups[3]->materials[8]->name = builtin_material_names[117];
++  index->groups[3]->materials[8]->data = metal8_iv;
++  index->groups[3]->materials[9]->name = builtin_material_names[118];
++  index->groups[3]->materials[9]->data = metal9_iv;
++  index->groups[3]->materials[10]->name = builtin_material_names[119];
++  index->groups[3]->materials[10]->data = metal10_iv;
++  index->groups[3]->materials[11]->name = builtin_material_names[120];
++  index->groups[3]->materials[11]->data = metal11_iv;
++  index->groups[3]->materials[12]->name = builtin_material_names[121];
++  index->groups[3]->materials[12]->data = metal12_iv;
++  index->groups[3]->materials[13]->name = builtin_material_names[122];
++  index->groups[3]->materials[13]->data = metal13_iv;
++  index->groups[3]->materials[14]->name = builtin_material_names[123];
++  index->groups[3]->materials[14]->data = metal14_iv;
++  index->groups[3]->materials[15]->name = builtin_material_names[124];
++  index->groups[3]->materials[15]->data = metal15_iv;
++  index->groups[3]->materials[16]->name = builtin_material_names[125];
++  index->groups[3]->materials[16]->data = metal16_iv;
++  index->groups[3]->materials[17]->name = builtin_material_names[126];
++  index->groups[3]->materials[17]->data = metal17_iv;
++  index->groups[3]->materials[18]->name = builtin_material_names[127];
++  index->groups[3]->materials[18]->data = metal18_iv;
++  index->groups[3]->materials[19]->name = builtin_material_names[128];
++  index->groups[3]->materials[19]->data = metal19_iv;
++  index->groups[3]->materials[20]->name = builtin_material_names[129];
++  index->groups[3]->materials[20]->data = metal20_iv;
++  index->groups[3]->materials[21]->name = builtin_material_names[130];
++  index->groups[3]->materials[21]->data = metal21_iv;
++  index->groups[3]->materials[22]->name = builtin_material_names[131];
++  index->groups[3]->materials[22]->data = metal22_iv;
++  index->groups[3]->materials[23]->name = builtin_material_names[132];
++  index->groups[3]->materials[23]->data = metal23_iv;
++  index->groups[3]->materials[24]->name = builtin_material_names[133];
++  index->groups[3]->materials[24]->data = metal24_iv;
++  index->groups[3]->materials[25]->name = builtin_material_names[134];
++  index->groups[3]->materials[25]->data = metal25_iv;
++  index->groups[3]->materials[26]->name = builtin_material_names[135];
++  index->groups[3]->materials[26]->data = metal26_iv;
++  index->groups[3]->materials[27]->name = builtin_material_names[136];
++  index->groups[3]->materials[27]->data = metal27_iv;
++  index->groups[3]->materials[28]->name = builtin_material_names[137];
++  index->groups[3]->materials[28]->data = metal28_iv;
++  index->groups[3]->materials[29]->name = builtin_material_names[138];
++  index->groups[3]->materials[29]->data = metal29_iv;
++  index->groups[3]->materials[30]->name = builtin_material_names[139];
++  index->groups[3]->materials[30]->data = metal30_iv;
++  index->groups[3]->materials[31]->name = builtin_material_names[140];
++  index->groups[3]->materials[31]->data = metal31_iv;
++  index->groups[3]->materials[32]->name = builtin_material_names[141];
++  index->groups[3]->materials[32]->data = metal32_iv;
++  index->groups[3]->materials[33]->name = builtin_material_names[142];
++  index->groups[3]->materials[33]->data = metal33_iv;
++  index->groups[3]->materials[34]->name = builtin_material_names[143];
++  index->groups[3]->materials[34]->data = metal34_iv;
++  index->groups[4]->name = builtin_material_names[144];
++  index->groups[4]->materials[0]->name = builtin_material_names[145];
++  index->groups[4]->materials[0]->data = neon0_iv;
++  index->groups[4]->materials[1]->name = builtin_material_names[146];
++  index->groups[4]->materials[1]->data = neon1_iv;
++  index->groups[4]->materials[2]->name = builtin_material_names[147];
++  index->groups[4]->materials[2]->data = neon2_iv;
++  index->groups[4]->materials[3]->name = builtin_material_names[148];
++  index->groups[4]->materials[3]->data = neon3_iv;
++  index->groups[4]->materials[4]->name = builtin_material_names[149];
++  index->groups[4]->materials[4]->data = neon4_iv;
++  index->groups[4]->materials[5]->name = builtin_material_names[150];
++  index->groups[4]->materials[5]->data = neon5_iv;
++  index->groups[4]->materials[6]->name = builtin_material_names[151];
++  index->groups[4]->materials[6]->data = neon6_iv;
++  index->groups[4]->materials[7]->name = builtin_material_names[152];
++  index->groups[4]->materials[7]->data = neon7_iv;
++  index->groups[4]->materials[8]->name = builtin_material_names[153];
++  index->groups[4]->materials[8]->data = neon8_iv;
++  index->groups[4]->materials[9]->name = builtin_material_names[154];
++  index->groups[4]->materials[9]->data = neon9_iv;
++  index->groups[4]->materials[10]->name = builtin_material_names[155];
++  index->groups[4]->materials[10]->data = neon10_iv;
++  index->groups[4]->materials[11]->name = builtin_material_names[156];
++  index->groups[4]->materials[11]->data = neon11_iv;
++  index->groups[4]->materials[12]->name = builtin_material_names[157];
++  index->groups[4]->materials[12]->data = neon12_iv;
++  index->groups[4]->materials[13]->name = builtin_material_names[158];
++  index->groups[4]->materials[13]->data = neon13_iv;
++  index->groups[4]->materials[14]->name = builtin_material_names[159];
++  index->groups[4]->materials[14]->data = neon14_iv;
++  index->groups[4]->materials[15]->name = builtin_material_names[160];
++  index->groups[4]->materials[15]->data = neon15_iv;
++  index->groups[4]->materials[16]->name = builtin_material_names[161];
++  index->groups[4]->materials[16]->data = neon16_iv;
++  index->groups[4]->materials[17]->name = builtin_material_names[162];
++  index->groups[4]->materials[17]->data = neon17_iv;
++  index->groups[4]->materials[18]->name = builtin_material_names[163];
++  index->groups[4]->materials[18]->data = neon18_iv;
++  index->groups[4]->materials[19]->name = builtin_material_names[164];
++  index->groups[4]->materials[19]->data = neon19_iv;
++  index->groups[4]->materials[20]->name = builtin_material_names[165];
++  index->groups[4]->materials[20]->data = neon20_iv;
++  index->groups[4]->materials[21]->name = builtin_material_names[166];
++  index->groups[4]->materials[21]->data = neon21_iv;
++  index->groups[4]->materials[22]->name = builtin_material_names[167];
++  index->groups[4]->materials[22]->data = neon22_iv;
++  index->groups[4]->materials[23]->name = builtin_material_names[168];
++  index->groups[4]->materials[23]->data = neon23_iv;
++  index->groups[4]->materials[24]->name = builtin_material_names[169];
++  index->groups[4]->materials[24]->data = neon24_iv;
++  index->groups[4]->materials[25]->name = builtin_material_names[170];
++  index->groups[4]->materials[25]->data = neon25_iv;
++  index->groups[4]->materials[26]->name = builtin_material_names[171];
++  index->groups[4]->materials[26]->data = neon26_iv;
++  index->groups[4]->materials[27]->name = builtin_material_names[172];
++  index->groups[4]->materials[27]->data = neon27_iv;
++  index->groups[4]->materials[28]->name = builtin_material_names[173];
++  index->groups[4]->materials[28]->data = neon28_iv;
++  index->groups[4]->materials[29]->name = builtin_material_names[174];
++  index->groups[4]->materials[29]->data = neon29_iv;
++  index->groups[4]->materials[30]->name = builtin_material_names[175];
++  index->groups[4]->materials[30]->data = neon30_iv;
++  index->groups[4]->materials[31]->name = builtin_material_names[176];
++  index->groups[4]->materials[31]->data = neon31_iv;
++  index->groups[4]->materials[32]->name = builtin_material_names[177];
++  index->groups[4]->materials[32]->data = neon32_iv;
++  index->groups[4]->materials[33]->name = builtin_material_names[178];
++  index->groups[4]->materials[33]->data = neon33_iv;
++  index->groups[4]->materials[34]->name = builtin_material_names[179];
++  index->groups[4]->materials[34]->data = neon34_iv;
++  index->groups[5]->name = builtin_material_names[180];
++  index->groups[5]->materials[0]->name = builtin_material_names[181];
++  index->groups[5]->materials[0]->data = rococo0_iv;
++  index->groups[5]->materials[1]->name = builtin_material_names[182];
++  index->groups[5]->materials[1]->data = rococo1_iv;
++  index->groups[5]->materials[2]->name = builtin_material_names[183];
++  index->groups[5]->materials[2]->data = rococo2_iv;
++  index->groups[5]->materials[3]->name = builtin_material_names[184];
++  index->groups[5]->materials[3]->data = rococo3_iv;
++  index->groups[5]->materials[4]->name = builtin_material_names[185];
++  index->groups[5]->materials[4]->data = rococo4_iv;
++  index->groups[5]->materials[5]->name = builtin_material_names[186];
++  index->groups[5]->materials[5]->data = rococo5_iv;
++  index->groups[5]->materials[6]->name = builtin_material_names[187];
++  index->groups[5]->materials[6]->data = rococo6_iv;
++  index->groups[5]->materials[7]->name = builtin_material_names[188];
++  index->groups[5]->materials[7]->data = rococo7_iv;
++  index->groups[5]->materials[8]->name = builtin_material_names[189];
++  index->groups[5]->materials[8]->data = rococo8_iv;
++  index->groups[5]->materials[9]->name = builtin_material_names[190];
++  index->groups[5]->materials[9]->data = rococo9_iv;
++  index->groups[5]->materials[10]->name = builtin_material_names[191];
++  index->groups[5]->materials[10]->data = rococo10_iv;
++  index->groups[5]->materials[11]->name = builtin_material_names[192];
++  index->groups[5]->materials[11]->data = rococo11_iv;
++  index->groups[5]->materials[12]->name = builtin_material_names[193];
++  index->groups[5]->materials[12]->data = rococo12_iv;
++  index->groups[5]->materials[13]->name = builtin_material_names[194];
++  index->groups[5]->materials[13]->data = rococo13_iv;
++  index->groups[5]->materials[14]->name = builtin_material_names[195];
++  index->groups[5]->materials[14]->data = rococo14_iv;
++  index->groups[5]->materials[15]->name = builtin_material_names[196];
++  index->groups[5]->materials[15]->data = rococo15_iv;
++  index->groups[5]->materials[16]->name = builtin_material_names[197];
++  index->groups[5]->materials[16]->data = rococo16_iv;
++  index->groups[5]->materials[17]->name = builtin_material_names[198];
++  index->groups[5]->materials[17]->data = rococo17_iv;
++  index->groups[5]->materials[18]->name = builtin_material_names[199];
++  index->groups[5]->materials[18]->data = rococo18_iv;
++  index->groups[5]->materials[19]->name = builtin_material_names[200];
++  index->groups[5]->materials[19]->data = rococo19_iv;
++  index->groups[5]->materials[20]->name = builtin_material_names[201];
++  index->groups[5]->materials[20]->data = rococo20_iv;
++  index->groups[5]->materials[21]->name = builtin_material_names[202];
++  index->groups[5]->materials[21]->data = rococo21_iv;
++  index->groups[5]->materials[22]->name = builtin_material_names[203];
++  index->groups[5]->materials[22]->data = rococo22_iv;
++  index->groups[5]->materials[23]->name = builtin_material_names[204];
++  index->groups[5]->materials[23]->data = rococo23_iv;
++  index->groups[5]->materials[24]->name = builtin_material_names[205];
++  index->groups[5]->materials[24]->data = rococo24_iv;
++  index->groups[5]->materials[25]->name = builtin_material_names[206];
++  index->groups[5]->materials[25]->data = rococo25_iv;
++  index->groups[5]->materials[26]->name = builtin_material_names[207];
++  index->groups[5]->materials[26]->data = rococo26_iv;
++  index->groups[5]->materials[27]->name = builtin_material_names[208];
++  index->groups[5]->materials[27]->data = rococo27_iv;
++  index->groups[5]->materials[28]->name = builtin_material_names[209];
++  index->groups[5]->materials[28]->data = rococo28_iv;
++  index->groups[5]->materials[29]->name = builtin_material_names[210];
++  index->groups[5]->materials[29]->data = rococo29_iv;
++  index->groups[5]->materials[30]->name = builtin_material_names[211];
++  index->groups[5]->materials[30]->data = rococo30_iv;
++  index->groups[5]->materials[31]->name = builtin_material_names[212];
++  index->groups[5]->materials[31]->data = rococo31_iv;
++  index->groups[5]->materials[32]->name = builtin_material_names[213];
++  index->groups[5]->materials[32]->data = rococo32_iv;
++  index->groups[5]->materials[33]->name = builtin_material_names[214];
++  index->groups[5]->materials[33]->data = rococo33_iv;
++  index->groups[5]->materials[34]->name = builtin_material_names[215];
++  index->groups[5]->materials[34]->data = rococo34_iv;
++  index->groups[6]->name = builtin_material_names[216];
++  index->groups[6]->materials[0]->name = builtin_material_names[217];
++  index->groups[6]->materials[0]->data = santafe0_iv;
++  index->groups[6]->materials[1]->name = builtin_material_names[218];
++  index->groups[6]->materials[1]->data = santafe1_iv;
++  index->groups[6]->materials[2]->name = builtin_material_names[219];
++  index->groups[6]->materials[2]->data = santafe2_iv;
++  index->groups[6]->materials[3]->name = builtin_material_names[220];
++  index->groups[6]->materials[3]->data = santafe3_iv;
++  index->groups[6]->materials[4]->name = builtin_material_names[221];
++  index->groups[6]->materials[4]->data = santafe4_iv;
++  index->groups[6]->materials[5]->name = builtin_material_names[222];
++  index->groups[6]->materials[5]->data = santafe5_iv;
++  index->groups[6]->materials[6]->name = builtin_material_names[223];
++  index->groups[6]->materials[6]->data = santafe6_iv;
++  index->groups[6]->materials[7]->name = builtin_material_names[224];
++  index->groups[6]->materials[7]->data = santafe7_iv;
++  index->groups[6]->materials[8]->name = builtin_material_names[225];
++  index->groups[6]->materials[8]->data = santafe8_iv;
++  index->groups[6]->materials[9]->name = builtin_material_names[226];
++  index->groups[6]->materials[9]->data = santafe9_iv;
++  index->groups[6]->materials[10]->name = builtin_material_names[227];
++  index->groups[6]->materials[10]->data = santafe10_iv;
++  index->groups[6]->materials[11]->name = builtin_material_names[228];
++  index->groups[6]->materials[11]->data = santafe11_iv;
++  index->groups[6]->materials[12]->name = builtin_material_names[229];
++  index->groups[6]->materials[12]->data = santafe12_iv;
++  index->groups[6]->materials[13]->name = builtin_material_names[230];
++  index->groups[6]->materials[13]->data = santafe13_iv;
++  index->groups[6]->materials[14]->name = builtin_material_names[231];
++  index->groups[6]->materials[14]->data = santafe14_iv;
++  index->groups[6]->materials[15]->name = builtin_material_names[232];
++  index->groups[6]->materials[15]->data = santafe15_iv;
++  index->groups[6]->materials[16]->name = builtin_material_names[233];
++  index->groups[6]->materials[16]->data = santafe16_iv;
++  index->groups[6]->materials[17]->name = builtin_material_names[234];
++  index->groups[6]->materials[17]->data = santafe17_iv;
++  index->groups[6]->materials[18]->name = builtin_material_names[235];
++  index->groups[6]->materials[18]->data = santafe18_iv;
++  index->groups[6]->materials[19]->name = builtin_material_names[236];
++  index->groups[6]->materials[19]->data = santafe19_iv;
++  index->groups[6]->materials[20]->name = builtin_material_names[237];
++  index->groups[6]->materials[20]->data = santafe20_iv;
++  index->groups[6]->materials[21]->name = builtin_material_names[238];
++  index->groups[6]->materials[21]->data = santafe21_iv;
++  index->groups[6]->materials[22]->name = builtin_material_names[239];
++  index->groups[6]->materials[22]->data = santafe22_iv;
++  index->groups[6]->materials[23]->name = builtin_material_names[240];
++  index->groups[6]->materials[23]->data = santafe23_iv;
++  index->groups[6]->materials[24]->name = builtin_material_names[241];
++  index->groups[6]->materials[24]->data = santafe24_iv;
++  index->groups[6]->materials[25]->name = builtin_material_names[242];
++  index->groups[6]->materials[25]->data = santafe25_iv;
++  index->groups[6]->materials[26]->name = builtin_material_names[243];
++  index->groups[6]->materials[26]->data = santafe26_iv;
++  index->groups[6]->materials[27]->name = builtin_material_names[244];
++  index->groups[6]->materials[27]->data = santafe27_iv;
++  index->groups[6]->materials[28]->name = builtin_material_names[245];
++  index->groups[6]->materials[28]->data = santafe28_iv;
++  index->groups[6]->materials[29]->name = builtin_material_names[246];
++  index->groups[6]->materials[29]->data = santafe29_iv;
++  index->groups[6]->materials[30]->name = builtin_material_names[247];
++  index->groups[6]->materials[30]->data = santafe30_iv;
++  index->groups[6]->materials[31]->name = builtin_material_names[248];
++  index->groups[6]->materials[31]->data = santafe31_iv;
++  index->groups[6]->materials[32]->name = builtin_material_names[249];
++  index->groups[6]->materials[32]->data = santafe32_iv;
++  index->groups[6]->materials[33]->name = builtin_material_names[250];
++  index->groups[6]->materials[33]->data = santafe33_iv;
++  index->groups[6]->materials[34]->name = builtin_material_names[251];
++  index->groups[6]->materials[34]->data = santafe34_iv;
++  index->groups[7]->name = builtin_material_names[252];
++  index->groups[7]->materials[0]->name = builtin_material_names[253];
++  index->groups[7]->materials[0]->data = sheen0_iv;
++  index->groups[7]->materials[1]->name = builtin_material_names[254];
++  index->groups[7]->materials[1]->data = sheen1_iv;
++  index->groups[7]->materials[2]->name = builtin_material_names[255];
++  index->groups[7]->materials[2]->data = sheen2_iv;
++  index->groups[7]->materials[3]->name = builtin_material_names[256];
++  index->groups[7]->materials[3]->data = sheen3_iv;
++  index->groups[7]->materials[4]->name = builtin_material_names[257];
++  index->groups[7]->materials[4]->data = sheen4_iv;
++  index->groups[7]->materials[5]->name = builtin_material_names[258];
++  index->groups[7]->materials[5]->data = sheen5_iv;
++  index->groups[7]->materials[6]->name = builtin_material_names[259];
++  index->groups[7]->materials[6]->data = sheen6_iv;
++  index->groups[7]->materials[7]->name = builtin_material_names[260];
++  index->groups[7]->materials[7]->data = sheen7_iv;
++  index->groups[7]->materials[8]->name = builtin_material_names[261];
++  index->groups[7]->materials[8]->data = sheen8_iv;
++  index->groups[7]->materials[9]->name = builtin_material_names[262];
++  index->groups[7]->materials[9]->data = sheen9_iv;
++  index->groups[7]->materials[10]->name = builtin_material_names[263];
++  index->groups[7]->materials[10]->data = sheen10_iv;
++  index->groups[7]->materials[11]->name = builtin_material_names[264];
++  index->groups[7]->materials[11]->data = sheen11_iv;
++  index->groups[7]->materials[12]->name = builtin_material_names[265];
++  index->groups[7]->materials[12]->data = sheen12_iv;
++  index->groups[7]->materials[13]->name = builtin_material_names[266];
++  index->groups[7]->materials[13]->data = sheen13_iv;
++  index->groups[7]->materials[14]->name = builtin_material_names[267];
++  index->groups[7]->materials[14]->data = sheen14_iv;
++  index->groups[7]->materials[15]->name = builtin_material_names[268];
++  index->groups[7]->materials[15]->data = sheen15_iv;
++  index->groups[7]->materials[16]->name = builtin_material_names[269];
++  index->groups[7]->materials[16]->data = sheen16_iv;
++  index->groups[7]->materials[17]->name = builtin_material_names[270];
++  index->groups[7]->materials[17]->data = sheen17_iv;
++  index->groups[7]->materials[18]->name = builtin_material_names[271];
++  index->groups[7]->materials[18]->data = sheen18_iv;
++  index->groups[7]->materials[19]->name = builtin_material_names[272];
++  index->groups[7]->materials[19]->data = sheen19_iv;
++  index->groups[7]->materials[20]->name = builtin_material_names[273];
++  index->groups[7]->materials[20]->data = sheen20_iv;
++  index->groups[7]->materials[21]->name = builtin_material_names[274];
++  index->groups[7]->materials[21]->data = sheen21_iv;
++  index->groups[7]->materials[22]->name = builtin_material_names[275];
++  index->groups[7]->materials[22]->data = sheen22_iv;
++  index->groups[7]->materials[23]->name = builtin_material_names[276];
++  index->groups[7]->materials[23]->data = sheen23_iv;
++  index->groups[7]->materials[24]->name = builtin_material_names[277];
++  index->groups[7]->materials[24]->data = sheen24_iv;
++  index->groups[7]->materials[25]->name = builtin_material_names[278];
++  index->groups[7]->materials[25]->data = sheen25_iv;
++  index->groups[7]->materials[26]->name = builtin_material_names[279];
++  index->groups[7]->materials[26]->data = sheen26_iv;
++  index->groups[7]->materials[27]->name = builtin_material_names[280];
++  index->groups[7]->materials[27]->data = sheen27_iv;
++  index->groups[7]->materials[28]->name = builtin_material_names[281];
++  index->groups[7]->materials[28]->data = sheen28_iv;
++  index->groups[7]->materials[29]->name = builtin_material_names[282];
++  index->groups[7]->materials[29]->data = sheen29_iv;
++  index->groups[7]->materials[30]->name = builtin_material_names[283];
++  index->groups[7]->materials[30]->data = sheen30_iv;
++  index->groups[7]->materials[31]->name = builtin_material_names[284];
++  index->groups[7]->materials[31]->data = sheen31_iv;
++  index->groups[7]->materials[32]->name = builtin_material_names[285];
++  index->groups[7]->materials[32]->data = sheen32_iv;
++  index->groups[7]->materials[33]->name = builtin_material_names[286];
++  index->groups[7]->materials[33]->data = sheen33_iv;
++  index->groups[7]->materials[34]->name = builtin_material_names[287];
++  index->groups[7]->materials[34]->data = sheen34_iv;
++  index->groups[8]->name = builtin_material_names[288];
++  index->groups[8]->materials[0]->name = builtin_material_names[289];
++  index->groups[8]->materials[0]->data = silky0_iv;
++  index->groups[8]->materials[1]->name = builtin_material_names[290];
++  index->groups[8]->materials[1]->data = silky1_iv;
++  index->groups[8]->materials[2]->name = builtin_material_names[291];
++  index->groups[8]->materials[2]->data = silky2_iv;
++  index->groups[8]->materials[3]->name = builtin_material_names[292];
++  index->groups[8]->materials[3]->data = silky3_iv;
++  index->groups[8]->materials[4]->name = builtin_material_names[293];
++  index->groups[8]->materials[4]->data = silky4_iv;
++  index->groups[8]->materials[5]->name = builtin_material_names[294];
++  index->groups[8]->materials[5]->data = silky5_iv;
++  index->groups[8]->materials[6]->name = builtin_material_names[295];
++  index->groups[8]->materials[6]->data = silky6_iv;
++  index->groups[8]->materials[7]->name = builtin_material_names[296];
++  index->groups[8]->materials[7]->data = silky7_iv;
++  index->groups[8]->materials[8]->name = builtin_material_names[297];
++  index->groups[8]->materials[8]->data = silky8_iv;
++  index->groups[8]->materials[9]->name = builtin_material_names[298];
++  index->groups[8]->materials[9]->data = silky9_iv;
++  index->groups[8]->materials[10]->name = builtin_material_names[299];
++  index->groups[8]->materials[10]->data = silky10_iv;
++  index->groups[8]->materials[11]->name = builtin_material_names[300];
++  index->groups[8]->materials[11]->data = silky11_iv;
++  index->groups[8]->materials[12]->name = builtin_material_names[301];
++  index->groups[8]->materials[12]->data = silky12_iv;
++  index->groups[8]->materials[13]->name = builtin_material_names[302];
++  index->groups[8]->materials[13]->data = silky13_iv;
++  index->groups[8]->materials[14]->name = builtin_material_names[303];
++  index->groups[8]->materials[14]->data = silky14_iv;
++  index->groups[8]->materials[15]->name = builtin_material_names[304];
++  index->groups[8]->materials[15]->data = silky15_iv;
++  index->groups[8]->materials[16]->name = builtin_material_names[305];
++  index->groups[8]->materials[16]->data = silky16_iv;
++  index->groups[8]->materials[17]->name = builtin_material_names[306];
++  index->groups[8]->materials[17]->data = silky17_iv;
++  index->groups[8]->materials[18]->name = builtin_material_names[307];
++  index->groups[8]->materials[18]->data = silky18_iv;
++  index->groups[8]->materials[19]->name = builtin_material_names[308];
++  index->groups[8]->materials[19]->data = silky19_iv;
++  index->groups[8]->materials[20]->name = builtin_material_names[309];
++  index->groups[8]->materials[20]->data = silky20_iv;
++  index->groups[8]->materials[21]->name = builtin_material_names[310];
++  index->groups[8]->materials[21]->data = silky21_iv;
++  index->groups[8]->materials[22]->name = builtin_material_names[311];
++  index->groups[8]->materials[22]->data = silky22_iv;
++  index->groups[8]->materials[23]->name = builtin_material_names[312];
++  index->groups[8]->materials[23]->data = silky23_iv;
++  index->groups[8]->materials[24]->name = builtin_material_names[313];
++  index->groups[8]->materials[24]->data = silky24_iv;
++  index->groups[8]->materials[25]->name = builtin_material_names[314];
++  index->groups[8]->materials[25]->data = silky25_iv;
++  index->groups[8]->materials[26]->name = builtin_material_names[315];
++  index->groups[8]->materials[26]->data = silky26_iv;
++  index->groups[8]->materials[27]->name = builtin_material_names[316];
++  index->groups[8]->materials[27]->data = silky27_iv;
++  index->groups[8]->materials[28]->name = builtin_material_names[317];
++  index->groups[8]->materials[28]->data = silky28_iv;
++  index->groups[8]->materials[29]->name = builtin_material_names[318];
++  index->groups[8]->materials[29]->data = silky29_iv;
++  index->groups[8]->materials[30]->name = builtin_material_names[319];
++  index->groups[8]->materials[30]->data = silky30_iv;
++  index->groups[8]->materials[31]->name = builtin_material_names[320];
++  index->groups[8]->materials[31]->data = silky31_iv;
++  index->groups[8]->materials[32]->name = builtin_material_names[321];
++  index->groups[8]->materials[32]->data = silky32_iv;
++  index->groups[8]->materials[33]->name = builtin_material_names[322];
++  index->groups[8]->materials[33]->data = silky33_iv;
++  index->groups[8]->materials[34]->name = builtin_material_names[323];
++  index->groups[8]->materials[34]->data = silky34_iv;
++  index->groups[9]->name = builtin_material_names[324];
++  index->groups[9]->materials[0]->name = builtin_material_names[325];
++  index->groups[9]->materials[0]->data = spring0_iv;
++  index->groups[9]->materials[1]->name = builtin_material_names[326];
++  index->groups[9]->materials[1]->data = spring1_iv;
++  index->groups[9]->materials[2]->name = builtin_material_names[327];
++  index->groups[9]->materials[2]->data = spring2_iv;
++  index->groups[9]->materials[3]->name = builtin_material_names[328];
++  index->groups[9]->materials[3]->data = spring3_iv;
++  index->groups[9]->materials[4]->name = builtin_material_names[329];
++  index->groups[9]->materials[4]->data = spring4_iv;
++  index->groups[9]->materials[5]->name = builtin_material_names[330];
++  index->groups[9]->materials[5]->data = spring5_iv;
++  index->groups[9]->materials[6]->name = builtin_material_names[331];
++  index->groups[9]->materials[6]->data = spring6_iv;
++  index->groups[9]->materials[7]->name = builtin_material_names[332];
++  index->groups[9]->materials[7]->data = spring7_iv;
++  index->groups[9]->materials[8]->name = builtin_material_names[333];
++  index->groups[9]->materials[8]->data = spring8_iv;
++  index->groups[9]->materials[9]->name = builtin_material_names[334];
++  index->groups[9]->materials[9]->data = spring9_iv;
++  index->groups[9]->materials[10]->name = builtin_material_names[335];
++  index->groups[9]->materials[10]->data = spring10_iv;
++  index->groups[9]->materials[11]->name = builtin_material_names[336];
++  index->groups[9]->materials[11]->data = spring11_iv;
++  index->groups[9]->materials[12]->name = builtin_material_names[337];
++  index->groups[9]->materials[12]->data = spring12_iv;
++  index->groups[9]->materials[13]->name = builtin_material_names[338];
++  index->groups[9]->materials[13]->data = spring13_iv;
++  index->groups[9]->materials[14]->name = builtin_material_names[339];
++  index->groups[9]->materials[14]->data = spring14_iv;
++  index->groups[9]->materials[15]->name = builtin_material_names[340];
++  index->groups[9]->materials[15]->data = spring15_iv;
++  index->groups[9]->materials[16]->name = builtin_material_names[341];
++  index->groups[9]->materials[16]->data = spring16_iv;
++  index->groups[9]->materials[17]->name = builtin_material_names[342];
++  index->groups[9]->materials[17]->data = spring17_iv;
++  index->groups[9]->materials[18]->name = builtin_material_names[343];
++  index->groups[9]->materials[18]->data = spring18_iv;
++  index->groups[9]->materials[19]->name = builtin_material_names[344];
++  index->groups[9]->materials[19]->data = spring19_iv;
++  index->groups[9]->materials[20]->name = builtin_material_names[345];
++  index->groups[9]->materials[20]->data = spring20_iv;
++  index->groups[9]->materials[21]->name = builtin_material_names[346];
++  index->groups[9]->materials[21]->data = spring21_iv;
++  index->groups[9]->materials[22]->name = builtin_material_names[347];
++  index->groups[9]->materials[22]->data = spring22_iv;
++  index->groups[9]->materials[23]->name = builtin_material_names[348];
++  index->groups[9]->materials[23]->data = spring23_iv;
++  index->groups[9]->materials[24]->name = builtin_material_names[349];
++  index->groups[9]->materials[24]->data = spring24_iv;
++  index->groups[9]->materials[25]->name = builtin_material_names[350];
++  index->groups[9]->materials[25]->data = spring25_iv;
++  index->groups[9]->materials[26]->name = builtin_material_names[351];
++  index->groups[9]->materials[26]->data = spring26_iv;
++  index->groups[9]->materials[27]->name = builtin_material_names[352];
++  index->groups[9]->materials[27]->data = spring27_iv;
++  index->groups[9]->materials[28]->name = builtin_material_names[353];
++  index->groups[9]->materials[28]->data = spring28_iv;
++  index->groups[9]->materials[29]->name = builtin_material_names[354];
++  index->groups[9]->materials[29]->data = spring29_iv;
++  index->groups[9]->materials[30]->name = builtin_material_names[355];
++  index->groups[9]->materials[30]->data = spring30_iv;
++  index->groups[9]->materials[31]->name = builtin_material_names[356];
++  index->groups[9]->materials[31]->data = spring31_iv;
++  index->groups[9]->materials[32]->name = builtin_material_names[357];
++  index->groups[9]->materials[32]->data = spring32_iv;
++  index->groups[9]->materials[33]->name = builtin_material_names[358];
++  index->groups[9]->materials[33]->data = spring33_iv;
++  index->groups[9]->materials[34]->name = builtin_material_names[359];
++  index->groups[9]->materials[34]->data = spring34_iv;
++  index->groups[10]->name = builtin_material_names[360];
++  index->groups[10]->materials[0]->name = builtin_material_names[361];
++  index->groups[10]->materials[0]->data = summer0_iv;
++  index->groups[10]->materials[1]->name = builtin_material_names[362];
++  index->groups[10]->materials[1]->data = summer1_iv;
++  index->groups[10]->materials[2]->name = builtin_material_names[363];
++  index->groups[10]->materials[2]->data = summer2_iv;
++  index->groups[10]->materials[3]->name = builtin_material_names[364];
++  index->groups[10]->materials[3]->data = summer3_iv;
++  index->groups[10]->materials[4]->name = builtin_material_names[365];
++  index->groups[10]->materials[4]->data = summer4_iv;
++  index->groups[10]->materials[5]->name = builtin_material_names[366];
++  index->groups[10]->materials[5]->data = summer5_iv;
++  index->groups[10]->materials[6]->name = builtin_material_names[367];
++  index->groups[10]->materials[6]->data = summer6_iv;
++  index->groups[10]->materials[7]->name = builtin_material_names[368];
++  index->groups[10]->materials[7]->data = summer7_iv;
++  index->groups[10]->materials[8]->name = builtin_material_names[369];
++  index->groups[10]->materials[8]->data = summer8_iv;
++  index->groups[10]->materials[9]->name = builtin_material_names[370];
++  index->groups[10]->materials[9]->data = summer9_iv;
++  index->groups[10]->materials[10]->name = builtin_material_names[371];
++  index->groups[10]->materials[10]->data = summer10_iv;
++  index->groups[10]->materials[11]->name = builtin_material_names[372];
++  index->groups[10]->materials[11]->data = summer11_iv;
++  index->groups[10]->materials[12]->name = builtin_material_names[373];
++  index->groups[10]->materials[12]->data = summer12_iv;
++  index->groups[10]->materials[13]->name = builtin_material_names[374];
++  index->groups[10]->materials[13]->data = summer13_iv;
++  index->groups[10]->materials[14]->name = builtin_material_names[375];
++  index->groups[10]->materials[14]->data = summer14_iv;
++  index->groups[10]->materials[15]->name = builtin_material_names[376];
++  index->groups[10]->materials[15]->data = summer15_iv;
++  index->groups[10]->materials[16]->name = builtin_material_names[377];
++  index->groups[10]->materials[16]->data = summer16_iv;
++  index->groups[10]->materials[17]->name = builtin_material_names[378];
++  index->groups[10]->materials[17]->data = summer17_iv;
++  index->groups[10]->materials[18]->name = builtin_material_names[379];
++  index->groups[10]->materials[18]->data = summer18_iv;
++  index->groups[10]->materials[19]->name = builtin_material_names[380];
++  index->groups[10]->materials[19]->data = summer19_iv;
++  index->groups[10]->materials[20]->name = builtin_material_names[381];
++  index->groups[10]->materials[20]->data = summer20_iv;
++  index->groups[10]->materials[21]->name = builtin_material_names[382];
++  index->groups[10]->materials[21]->data = summer21_iv;
++  index->groups[10]->materials[22]->name = builtin_material_names[383];
++  index->groups[10]->materials[22]->data = summer22_iv;
++  index->groups[10]->materials[23]->name = builtin_material_names[384];
++  index->groups[10]->materials[23]->data = summer23_iv;
++  index->groups[10]->materials[24]->name = builtin_material_names[385];
++  index->groups[10]->materials[24]->data = summer24_iv;
++  index->groups[10]->materials[25]->name = builtin_material_names[386];
++  index->groups[10]->materials[25]->data = summer25_iv;
++  index->groups[10]->materials[26]->name = builtin_material_names[387];
++  index->groups[10]->materials[26]->data = summer26_iv;
++  index->groups[10]->materials[27]->name = builtin_material_names[388];
++  index->groups[10]->materials[27]->data = summer27_iv;
++  index->groups[10]->materials[28]->name = builtin_material_names[389];
++  index->groups[10]->materials[28]->data = summer28_iv;
++  index->groups[10]->materials[29]->name = builtin_material_names[390];
++  index->groups[10]->materials[29]->data = summer29_iv;
++  index->groups[10]->materials[30]->name = builtin_material_names[391];
++  index->groups[10]->materials[30]->data = summer30_iv;
++  index->groups[10]->materials[31]->name = builtin_material_names[392];
++  index->groups[10]->materials[31]->data = summer31_iv;
++  index->groups[10]->materials[32]->name = builtin_material_names[393];
++  index->groups[10]->materials[32]->data = summer32_iv;
++  index->groups[10]->materials[33]->name = builtin_material_names[394];
++  index->groups[10]->materials[33]->data = summer33_iv;
++  index->groups[10]->materials[34]->name = builtin_material_names[395];
++  index->groups[10]->materials[34]->data = summer34_iv;
++  index->groups[11]->name = builtin_material_names[396];
++  index->groups[11]->materials[0]->name = builtin_material_names[397];
++  index->groups[11]->materials[0]->data = tropical0_iv;
++  index->groups[11]->materials[1]->name = builtin_material_names[398];
++  index->groups[11]->materials[1]->data = tropical1_iv;
++  index->groups[11]->materials[2]->name = builtin_material_names[399];
++  index->groups[11]->materials[2]->data = tropical2_iv;
++  index->groups[11]->materials[3]->name = builtin_material_names[400];
++  index->groups[11]->materials[3]->data = tropical3_iv;
++  index->groups[11]->materials[4]->name = builtin_material_names[401];
++  index->groups[11]->materials[4]->data = tropical4_iv;
++  index->groups[11]->materials[5]->name = builtin_material_names[402];
++  index->groups[11]->materials[5]->data = tropical5_iv;
++  index->groups[11]->materials[6]->name = builtin_material_names[403];
++  index->groups[11]->materials[6]->data = tropical6_iv;
++  index->groups[11]->materials[7]->name = builtin_material_names[404];
++  index->groups[11]->materials[7]->data = tropical7_iv;
++  index->groups[11]->materials[8]->name = builtin_material_names[405];
++  index->groups[11]->materials[8]->data = tropical8_iv;
++  index->groups[11]->materials[9]->name = builtin_material_names[406];
++  index->groups[11]->materials[9]->data = tropical9_iv;
++  index->groups[11]->materials[10]->name = builtin_material_names[407];
++  index->groups[11]->materials[10]->data = tropical10_iv;
++  index->groups[11]->materials[11]->name = builtin_material_names[408];
++  index->groups[11]->materials[11]->data = tropical11_iv;
++  index->groups[11]->materials[12]->name = builtin_material_names[409];
++  index->groups[11]->materials[12]->data = tropical12_iv;
++  index->groups[11]->materials[13]->name = builtin_material_names[410];
++  index->groups[11]->materials[13]->data = tropical13_iv;
++  index->groups[11]->materials[14]->name = builtin_material_names[411];
++  index->groups[11]->materials[14]->data = tropical14_iv;
++  index->groups[11]->materials[15]->name = builtin_material_names[412];
++  index->groups[11]->materials[15]->data = tropical15_iv;
++  index->groups[11]->materials[16]->name = builtin_material_names[413];
++  index->groups[11]->materials[16]->data = tropical16_iv;
++  index->groups[11]->materials[17]->name = builtin_material_names[414];
++  index->groups[11]->materials[17]->data = tropical17_iv;
++  index->groups[11]->materials[18]->name = builtin_material_names[415];
++  index->groups[11]->materials[18]->data = tropical18_iv;
++  index->groups[11]->materials[19]->name = builtin_material_names[416];
++  index->groups[11]->materials[19]->data = tropical19_iv;
++  index->groups[11]->materials[20]->name = builtin_material_names[417];
++  index->groups[11]->materials[20]->data = tropical20_iv;
++  index->groups[11]->materials[21]->name = builtin_material_names[418];
++  index->groups[11]->materials[21]->data = tropical21_iv;
++  index->groups[11]->materials[22]->name = builtin_material_names[419];
++  index->groups[11]->materials[22]->data = tropical22_iv;
++  index->groups[11]->materials[23]->name = builtin_material_names[420];
++  index->groups[11]->materials[23]->data = tropical23_iv;
++  index->groups[11]->materials[24]->name = builtin_material_names[421];
++  index->groups[11]->materials[24]->data = tropical24_iv;
++  index->groups[11]->materials[25]->name = builtin_material_names[422];
++  index->groups[11]->materials[25]->data = tropical25_iv;
++  index->groups[11]->materials[26]->name = builtin_material_names[423];
++  index->groups[11]->materials[26]->data = tropical26_iv;
++  index->groups[11]->materials[27]->name = builtin_material_names[424];
++  index->groups[11]->materials[27]->data = tropical27_iv;
++  index->groups[11]->materials[28]->name = builtin_material_names[425];
++  index->groups[11]->materials[28]->data = tropical28_iv;
++  index->groups[11]->materials[29]->name = builtin_material_names[426];
++  index->groups[11]->materials[29]->data = tropical29_iv;
++  index->groups[11]->materials[30]->name = builtin_material_names[427];
++  index->groups[11]->materials[30]->data = tropical30_iv;
++  index->groups[11]->materials[31]->name = builtin_material_names[428];
++  index->groups[11]->materials[31]->data = tropical31_iv;
++  index->groups[11]->materials[32]->name = builtin_material_names[429];
++  index->groups[11]->materials[32]->data = tropical32_iv;
++  index->groups[11]->materials[33]->name = builtin_material_names[430];
++  index->groups[11]->materials[33]->data = tropical33_iv;
++  index->groups[11]->materials[34]->name = builtin_material_names[431];
++  index->groups[11]->materials[34]->data = tropical34_iv;
++  index->groups[12]->name = builtin_material_names[432];
++  index->groups[12]->materials[0]->name = builtin_material_names[433];
++  index->groups[12]->materials[0]->data = winter0_iv;
++  index->groups[12]->materials[1]->name = builtin_material_names[434];
++  index->groups[12]->materials[1]->data = winter1_iv;
++  index->groups[12]->materials[2]->name = builtin_material_names[435];
++  index->groups[12]->materials[2]->data = winter2_iv;
++  index->groups[12]->materials[3]->name = builtin_material_names[436];
++  index->groups[12]->materials[3]->data = winter3_iv;
++  index->groups[12]->materials[4]->name = builtin_material_names[437];
++  index->groups[12]->materials[4]->data = winter4_iv;
++  index->groups[12]->materials[5]->name = builtin_material_names[438];
++  index->groups[12]->materials[5]->data = winter5_iv;
++  index->groups[12]->materials[6]->name = builtin_material_names[439];
++  index->groups[12]->materials[6]->data = winter6_iv;
++  index->groups[12]->materials[7]->name = builtin_material_names[440];
++  index->groups[12]->materials[7]->data = winter7_iv;
++  index->groups[12]->materials[8]->name = builtin_material_names[441];
++  index->groups[12]->materials[8]->data = winter8_iv;
++  index->groups[12]->materials[9]->name = builtin_material_names[442];
++  index->groups[12]->materials[9]->data = winter9_iv;
++  index->groups[12]->materials[10]->name = builtin_material_names[443];
++  index->groups[12]->materials[10]->data = winter10_iv;
++  index->groups[12]->materials[11]->name = builtin_material_names[444];
++  index->groups[12]->materials[11]->data = winter11_iv;
++  index->groups[12]->materials[12]->name = builtin_material_names[445];
++  index->groups[12]->materials[12]->data = winter12_iv;
++  index->groups[12]->materials[13]->name = builtin_material_names[446];
++  index->groups[12]->materials[13]->data = winter13_iv;
++  index->groups[12]->materials[14]->name = builtin_material_names[447];
++  index->groups[12]->materials[14]->data = winter14_iv;
++  index->groups[12]->materials[15]->name = builtin_material_names[448];
++  index->groups[12]->materials[15]->data = winter15_iv;
++  index->groups[12]->materials[16]->name = builtin_material_names[449];
++  index->groups[12]->materials[16]->data = winter16_iv;
++  index->groups[12]->materials[17]->name = builtin_material_names[450];
++  index->groups[12]->materials[17]->data = winter17_iv;
++  index->groups[12]->materials[18]->name = builtin_material_names[451];
++  index->groups[12]->materials[18]->data = winter18_iv;
++  index->groups[12]->materials[19]->name = builtin_material_names[452];
++  index->groups[12]->materials[19]->data = winter19_iv;
++  index->groups[12]->materials[20]->name = builtin_material_names[453];
++  index->groups[12]->materials[20]->data = winter20_iv;
++  index->groups[12]->materials[21]->name = builtin_material_names[454];
++  index->groups[12]->materials[21]->data = winter21_iv;
++  index->groups[12]->materials[22]->name = builtin_material_names[455];
++  index->groups[12]->materials[22]->data = winter22_iv;
++  index->groups[12]->materials[23]->name = builtin_material_names[456];
++  index->groups[12]->materials[23]->data = winter23_iv;
++  index->groups[12]->materials[24]->name = builtin_material_names[457];
++  index->groups[12]->materials[24]->data = winter24_iv;
++  index->groups[12]->materials[25]->name = builtin_material_names[458];
++  index->groups[12]->materials[25]->data = winter25_iv;
++  index->groups[12]->materials[26]->name = builtin_material_names[459];
++  index->groups[12]->materials[26]->data = winter26_iv;
++  index->groups[12]->materials[27]->name = builtin_material_names[460];
++  index->groups[12]->materials[27]->data = winter27_iv;
++  index->groups[12]->materials[28]->name = builtin_material_names[461];
++  index->groups[12]->materials[28]->data = winter28_iv;
++  index->groups[12]->materials[29]->name = builtin_material_names[462];
++  index->groups[12]->materials[29]->data = winter29_iv;
++  index->groups[12]->materials[30]->name = builtin_material_names[463];
++  index->groups[12]->materials[30]->data = winter30_iv;
++  index->groups[12]->materials[31]->name = builtin_material_names[464];
++  index->groups[12]->materials[31]->data = winter31_iv;
++  index->groups[12]->materials[32]->name = builtin_material_names[465];
++  index->groups[12]->materials[32]->data = winter32_iv;
++  index->groups[12]->materials[33]->name = builtin_material_names[466];
++  index->groups[12]->materials[33]->data = winter33_iv;
++  index->groups[12]->materials[34]->name = builtin_material_names[467];
++  index->groups[12]->materials[34]->data = winter34_iv;
++#endif // ! WITH_STATIC_DEFAULTS
++} // setupBuiltinMaterials()
++
++// *************************************************************************
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoAnyMaterialListBuiltins.cpp.in.m4
+@@ -0,0 +1,141 @@
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// @configure_input@
++
++#if SO at GUI@_DEBUG
++static const char rcsid[] =
++  "$Id$";
++#endif // SO at GUI@_DEBUG
++
++/**************************************************************************
++ * IMPORTANT NOTICE
++ * Be aware that the file So at Gui@MaterialListBuiltins.cpp is generated from
++ * the file So at Gui@MaterialListBuiltins.cpp.m4, so changes has to be done in
++ * the source file with the m4 macros.  The generation is done manually,
++ * since it is no point in making this project depend on the user having
++ * m4 installed.
++ **************************************************************************/
++
++#include <assert.h>
++#include <string.h>
++
++#include <Inventor/@Gui@/SoAnyMaterialList.h>
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#ifdef WITH_STATIC_DEFAULTS
++#include <materials/materials.h>
++#endif // WITH_STATIC_DEFAULTS
++
++include(libm4.m4)
++divert(0)dnl
++// *************************************************************************
++define([SOANY_BUILTIN_MATERIAL_GROUPS], [13])dnl
++define([SOANY_BUILTIN_MATERIAL_GROUP_SIZE], [35])dnl
++
++#ifdef WITH_STATIC_DEFAULTS
++static
++const char *
++changequote(,)dnl
++builtin_material_names[] = {
++changequote([,])dnl
++define([matnum], 0)dnl
++m4_foreach([material], [artdeco, autumn, glass, metal, neon, rococo, santafe,
++                        sheen, silky, spring, summer, tropical, winter], [dnl
++  "material",
++m4_for([num], 0, m4_eval(SOANY_BUILTIN_MATERIAL_GROUP_SIZE-1),,
++[dnl
++    "material.num",
++])dnl
++define([matnum], m4_eval(matnum+1))dnl
++])dnl
++  NULL
++}; // builtin_material_names
++#endif // WITH_STATIC_DEFAULTS
++
++// *************************************************************************
++
++/*!
++  \internal
++
++  This method fills in the So at Gui@MaterialDirectory structure with the builtin
++  material data.
++*/
++
++void
++SoAnyMaterialList::setupBuiltinMaterials( // private
++  So at Gui@MaterialDirectory * const index ) const
++{
++  assert( index != NULL );
++  index->numGroups = 0;
++  index->groups = NULL;
++#ifdef WITH_STATIC_DEFAULTS
++changequote(,)dnl
++  index->flags |= SO at GUI@_BUILTIN_MATERIALS;
++  index->numGroups = SOANY_BUILTIN_MATERIAL_GROUPS;
++  index->groups = new So at Gui@MaterialGroup * [ SOANY_BUILTIN_MATERIAL_GROUPS ];
++  for ( int i = 0; i < index->numGroups; i++ ) {
++    index->groups[i] = new So at Gui@MaterialGroup;
++    index->groups[i]->numMaterials = SOANY_BUILTIN_MATERIAL_GROUP_SIZE;
++    index->groups[i]->materials = new So at Gui@Material * [ SOANY_BUILTIN_MATERIAL_GROUP_SIZE ];
++    for ( int j = 0; j < SOANY_BUILTIN_MATERIAL_GROUP_SIZE; j++ ) {
++      index->groups[i]->materials[j] = new So at Gui@Material;
++    }
++  }
++
++changequote([,])dnl
++define([matnum], 0)dnl
++m4_foreach([material], [artdeco, autumn, glass, metal, neon, rococo, santafe,
++                        sheen, silky, spring, summer, tropical, winter], [dnl
++changequote(<,>)dnl
++  index->groups[matnum]->name = builtin_material_names[m4_eval(matnum*(SOANY_BUILTIN_MATERIAL_GROUP_SIZE+1))];
++changequote([,])dnl
++m4_for([num], 0, m4_eval(SOANY_BUILTIN_MATERIAL_GROUP_SIZE-1),,
++[changequote(<,>)dnl
++  index->groups[matnum]->materials[num]->name = builtin_material_names[m4_eval(matnum*(SOANY_BUILTIN_MATERIAL_GROUP_SIZE+1)+num+1)];
++  index->groups[matnum]->materials[num]->data = material<>num<>_iv;
++changequote([,])dnl
++])dnl
++define([matnum], m4_eval(matnum+1))dnl
++])dnl
++#endif // ! WITH_STATIC_DEFAULTS
++} // setupBuiltinMaterials()
++
++// *************************************************************************
++
++#if SO at GUI@_DEBUG
++static const char * getSoAnyMaterialListBuiltinsRCSId(void) { return rcsid; }
++#endif // SO at GUI@_DEBUG
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGui.h.in
+@@ -0,0 +1,216 @@
++#ifndef SO at GUI@_H
++#define SO at GUI@_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/So at Gui@Basic.h>
++
++// FIXME: use configure defines for the header files.
++// 20020613 mortene.
++
++#ifdef __COIN_SOQT__
++
++#if QT_VERSION >= 0x040000
++#include <QtCore/QObject>
++#else
++#include <qobject.h>
++#endif
++
++#endif // __COIN_SOQT__
++#ifdef __COIN_SOXT__
++#include <X11/Intrinsic.h>
++#include <Xm/Xm.h>
++#endif // __COIN_SOXT__
++#ifdef __COIN_SOGTK__
++// Fetch stdlib.h, so NULL is defined before glib.h is (indirectly)
++// included. Otherwise we get a compile error with KCC on some
++// systems.
++#include <stdlib.h>
++#include <gtk/gtk.h>
++class SoGtkComponent;
++class SbPList;
++#endif // __COIN_SOGTK__
++#ifdef __COIN_SOWIN__
++#include <windows.h>
++#endif // __COIN_SOWIN__
++
++#include <Inventor/SbBasic.h>
++#include <Inventor/SbLinear.h>
++#include <Inventor/SbString.h>
++#include <Inventor/SoDB.h>
++#include <Inventor/errors/SoDebugError.h>
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@
++{
++
++public:
++  static @WIDGET@ init(const char * appname, const char * classname = "So at Gui@");
++  static @WIDGET@ init(int & argc, char ** argv,
++                       const char * appname, const char * classname = "So at Gui@");
++  static void init(@WIDGET@ toplevelwidget);
++
++  static void mainLoop(void);
++  static void exitMainLoop(void);
++  static void done(void);
++
++  static @WIDGET@ getTopLevelWidget(void);
++  static @WIDGET@ getShellWidget(const @WIDGET@ w);
++
++  static void show(@WIDGET@ const widget);
++  static void hide(@WIDGET@ const widget);
++
++  static void setWidgetSize(@WIDGET@ const widget, const SbVec2s size);
++  static SbVec2s getWidgetSize(const @WIDGET@ widget);
++
++  static void createSimpleErrorDialog(@WIDGET@ widget,
++                                      const char * title,
++                                      const char * string1,
++                                      const char * string2 = NULL);
++
++  static void getVersionInfo(int * major = NULL,
++                             int * minor = NULL,
++                             int * micro = NULL);
++  static const char * getVersionString(void);
++  static const char * getVersionToolkitString(void);
++
++  enum FatalErrors {
++    UNSPECIFIED_ERROR = 0,
++    NO_OPENGL_CANVAS,
++    INTERNAL_ASSERT
++  };
++  typedef void FatalErrorCB(const SbString errmsg, So at Gui@::FatalErrors errcode,
++                            void * userdata);
++  static FatalErrorCB * setFatalErrorHandler(So at Gui@::FatalErrorCB * cb,
++                                             void * userdata);
++
++  static SbBool isDebugLibrary(void);
++  static SbBool isCompatible(unsigned int major, unsigned int minor);
++
++  enum ABIType { DLL, LIB, UNKNOWN };
++  static ABIType getABIType(void);
++
++  static void lockGL(void);
++  static void unlockGL(void);
++
++private:
++  // Since the class consists solely of static functions, hide the
++  // default constructor and the destructor so nobody can instantiate
++  // it.
++  So at Gui@(void);
++  virtual ~So at Gui@();
++
++  friend class SoGuiP;
++  friend class So at Gui@P;
++
++
++  // FIXME!: audit and remove as much as possible of the remaining
++  // toolkit specific parts below. 20020117 mortene.
++
++#ifdef __COIN_SOWIN__
++public:
++  static void doIdleTasks(void);
++#endif // __COIN_SOWIN__
++
++#ifdef __COIN_SOXT__
++public:
++  static void nextEvent(XtAppContext, XEvent *);
++  static Boolean dispatchEvent(XEvent * event);
++  static XtAppContext getAppContext(void);
++  static Display * getDisplay(void);
++  static XmString encodeString(const char * const str);
++  static char * decodeString(XmString xstring);
++  static void getPopupArgs(Display * display, int screen,
++                           ArgList args, int * n);
++
++  static void registerColormapLoad(Widget widget, Widget shell);
++  static void addColormapToShell(Widget widget, Widget shell);
++  static void removeColormapFromShell(Widget widget, Widget shell);
++
++  static void addExtensionEventHandler(Widget widget,
++                                       int eventType, XtEventHandler proc,
++                                       XtPointer clientData);
++  static void removeExtensionEventHandler(Widget widget,
++                                          int eventType, XtEventHandler proc,
++                                          XtPointer clientData);
++
++protected:
++  static void getExtensionEventHandler(XEvent * event, Widget & widget,
++                                       XtEventHandler & proc,
++                                       XtPointer & clientData);
++#endif // __COIN_SOXT__
++
++#ifdef __COIN_SOGTK__
++public:
++  friend class SoGtkComponent;
++  enum SoGtkComponentAction { CREATION, DESTRUCTION, CHANGE };
++  typedef void SoGtkComponentActionCallback(SoGtkComponent *, SoGtk::SoGtkComponentAction, void *);
++
++  static void addComponentActionCallback(SoGtkComponentActionCallback *, void *);
++  static void removeComponentActionCallback(SoGtkComponentActionCallback *, void *);
++
++  static int getComponents(SbPList & components);
++
++protected:
++  static void invokeComponentActionCallbacks(SoGtkComponent * component,
++                                             SoGtkComponentAction action);
++
++  static gint componentCreation(SoGtkComponent * component);
++  static gint componentDestruction(SoGtkComponent * component);
++  static gint componentChange(SoGtkComponent * component);
++
++private:
++  static gint timerSensorCB(gpointer data);
++  static gint idleSensorCB(gpointer data);
++  static gint delaySensorCB(gpointer data);
++
++  static GtkWidget * mainWidget;
++  static SbPList * components;
++  static SbPList * component_callbacks;
++#endif // __COIN_SOGTK__
++};
++
++// *************************************************************************
++// Here's something InventorWin provides for convenience. Belongs more
++// in the application code domain, imo, but we provide these macros
++// for better compile time compatibility with InventorWin.  -mortene
++
++#define SO at GUI@_ENTER_GL_SECTION() do { So at Gui@::lockGL(); } while(FALSE)
++#define SO at GUI@_LEAVE_GL_SECTION() do { So at Gui@::unlockGL(); } while(FALSE)
++
++// *************************************************************************
++
++#endif // ! SO at GUI@_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiBasic.h.in
+@@ -0,0 +1,153 @@
++#ifndef SO at GUI@_BASIC_H
++#define SO at GUI@_BASIC_H
++
++// NB: this is not a pure configure-input file, it's also a config header...
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// *************************************************************************
++
++/* Some useful inline template functions:
++ *   So at Gui@Min(Val1, Val2)       - returns minimum value
++ *   So at Gui@Max(Val1, Val2)       - returns maximum value
++ *   So at Gui@Clamp(Val, Min, Max)  - returns clamped value
++ *   So at Gui@Swap(Val1, Val2)      - swaps the two values (no return value)
++ */
++
++template <class Type>
++inline Type So at Gui@Abs(Type Val) {
++  return (Val < 0) ? -Val : Val;
++}
++
++template <class Type>
++inline Type So at Gui@Min(Type a, Type b) {
++  return (b < a) ? b : a;
++}
++
++template <class Type>
++inline Type So at Gui@Max(Type a, Type b) {
++  return (b > a) ? b : a;
++}
++
++template <class Type>
++inline Type So at Gui@Clamp(Type val, Type min, Type max) {
++  return So at Gui@Max(min, So at Gui@Min(max, val));
++}
++
++template <class Type>
++inline void So at Gui@Swap(Type & a, Type & b) {
++  Type t = a; a = b; b = t;
++}
++
++// *************************************************************************
++
++#define __COIN_SO at GUI@__
++
++#if ! defined(SO at GUI@_MAJOR_VERSION)
++#undef SO at GUI@_MAJOR_VERSION
++#endif /* ! SO at GUI@_MAJOR_VERSION */
++#if ! defined(SO at GUI@_MINOR_VERSION)
++#undef SO at GUI@_MINOR_VERSION
++#endif /* ! SO at GUI@_MINOR_VERSION */
++#if ! defined(SO at GUI@_MICRO_VERSION)
++#undef SO at GUI@_MICRO_VERSION
++#endif /* ! SO at GUI@_MICRO_VERSION */
++#if ! defined(SO at GUI@_BETA_VERSION)
++#undef SO at GUI@_BETA_VERSION
++#endif /* ! SO at GUI@_BETA_VERSION */
++#if ! defined(SO at GUI@_VERSION)
++#undef SO at GUI@_VERSION
++#endif /* ! SO at GUI@_VERSION */
++
++// *************************************************************************
++
++/* Precaution to avoid an error easily made by the application programmer. */
++#ifdef SO at GUI@_DLL_API
++# error Leave the internal SO at GUI@_DLL_API define alone.
++#endif /* SO at GUI@_DLL_API */
++
++/*
++  On MSWindows platforms, one of these defines must always be set when
++  building application programs:
++
++   - "SO at GUI@_DLL", when the application programmer is using the
++     library in the form of a dynamic link library (DLL)
++
++   - "SO at GUI@_NOT_DLL", when the application programmer is using the
++     library in the form of a static object library (LIB)
++
++  Note that either SO at GUI@_DLL or SO at GUI@_NOT_DLL _must_ be defined by
++  the application programmer on MSWindows platforms, or else the
++  #error statement will hit. Set up one or the other of these two
++  defines in your compiler environment according to how the library
++  was built -- as a DLL (use "SO at GUI@_DLL") or as a LIB (use
++  "SO at GUI@_NOT_DLL").
++
++  (Setting up defines for the compiler is typically done by either
++  adding something like "/DSO at GUI@_DLL" to the compiler's argument
++  line (for command-line build processes), or by adding the define to
++  the list of preprocessor symbols in your IDE GUI (in the MSVC IDE,
++  this is done from the "Project"->"Settings" menu, choose the "C/C++"
++  tab, then "Preprocessor" from the dropdown box and add the
++  appropriate define)).
++
++  It is extremely important that the application programmer uses the
++  correct define, as using "SO at GUI@_NOT_DLL" when "SO at GUI@_DLL" is
++  correct is likely to cause mysterious crashes.
++ */
++#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
++# ifdef SO at GUI@_INTERNAL
++#  ifdef SO at GUI@_MAKE_DLL
++#   define SO at GUI@_DLL_API __declspec(dllexport)
++#  endif /* SO at GUI@_MAKE_DLL */
++# else /* !SO at GUI@_INTERNAL */
++#  ifdef SO at GUI@_DLL
++#   define SO at GUI@_DLL_API __declspec(dllimport)
++#  else /* !SO at GUI@_DLL */
++#   ifndef SO at GUI@_NOT_DLL
++#    error Define either SO at GUI@_DLL or SO at GUI@_NOT_DLL as appropriate for your linkage! See Inventor/@Gui@/So at Gui@Basic.h for further instructions.
++#   endif /* SO at GUI@_NOT_DLL */
++#  endif /* !SO at GUI@_DLL */
++# endif /* !SO at GUI@_MAKE_DLL */
++#endif /* Microsoft Windows */
++
++/* Empty define to avoid errors when _not_ compiling an MSWindows DLL. */
++#ifndef SO at GUI@_DLL_API
++# define SO at GUI@_DLL_API
++#endif /* !SO at GUI@_DLL_API */
++
++#ifndef GUI_TOOLKIT_VERSION
++#define GUI_TOOLKIT_VERSION ""
++#endif /* GUI_TOOLKIT_VERSION */
++
++#endif // ! SO at GUI@_BASIC_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiColorEditor.h.in
+@@ -0,0 +1,39 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// This include file just forwards to the one under the editors/
++// directory. Done to be compatible with old SGI InventorXt code and
++// TGS SoWin and SoQt code.
++
++#include <Inventor/@Gui@/editors/So at Gui@ColorEditor.h>
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiCommon.cpp.in
+@@ -0,0 +1,682 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/* For the Doxygen tool. */
++
++/*! \defgroup misc Miscellaneous Classes */
++/*! \defgroup devices @Gui@ Device Classes */
++/*! \defgroup components @Gui@ Components */
++/*! \defgroup viewers @Gui@ Viewer Components */
++
++
++// FIXME: the code example shouldn't be duplicated here -- it's
++// already part of the SoQt mainpage-doc. 20020806 mortene.
++
++/*!
++  \class So at Gui@ So at Gui@.h Inventor/@Gui@/So at Gui@.h
++  \brief The So at Gui@ class takes care of @Gui@ initialization and event dispatching.
++  \ingroup misc
++
++  This is the "application-wide" class with solely static methods
++  handling initialization and event processing tasks. You must use
++  this class in any application built on top of the So at Gui@
++  library.
++
++  Typical usage is as follows (complete application code):
++
++  \code
++  #include <Inventor/@Gui@/So at Gui@.h>
++  #include <Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.h>
++  #include <Inventor/nodes/SoBaseColor.h>
++  #include <Inventor/nodes/SoCone.h>
++  #include <Inventor/nodes/SoSeparator.h>
++  
++  int
++  main(int argc, char ** argv)
++  {
++    // Initialize So at Gui@ and Inventor API libraries. This returns a main
++    // window to use.
++    @WIDGET@ mainwin = So at Gui@::init(argc, argv, argv[0]);
++  
++    // Make a dead simple scene graph, only containing a single
++    // yellow cone under the scenegraph root.
++    SoSeparator * root = new SoSeparator;
++    root->ref();
++
++    SoBaseColor * col = new SoBaseColor;
++    col->rgb = SbColor(1, 1, 0);
++    root->addChild(col);
++
++    root->addChild(new SoCone);
++  
++    // Use one of the convenient viewer classes.
++    So at Gui@ExaminerViewer * eviewer = new So at Gui@ExaminerViewer(mainwin);
++    eviewer->setSceneGraph(root);
++    eviewer->show();
++  
++    // Pop up the main window.
++    So at Gui@::show(mainwin);
++    // Loop until exit.
++    So at Gui@::mainLoop();
++
++    // Clean up resources.
++    delete eviewer;
++    root->unref();
++    So at Gui@::done();
++
++    return 0;
++  }
++  \endcode
++
++  And voila:
++
++  <center>
++  <img src="http://doc.coin3d.org/images/SoLibs/general/sogui-class-example.png">
++  </center>
++
++  \sa So at Gui@Component
++*/
++
++// *************************************************************************
++
++#include <stdlib.h>
++#include <string.h>
++
++#include <Inventor/@Gui@/So at Gui@.h>
++#include <Inventor/@Gui@/SoGuiP.h>
++#include <Inventor/@Gui@/SoAny.h>
++
++#include <Inventor/SoDB.h>
++#include <Inventor/SoInteraction.h>
++#include <Inventor/nodekits/SoNodeKit.h>
++
++#include <string>
++
++// *************************************************************************
++
++// Default constructor and the destructor is private (So at Gui@ class
++// consists solely of static functions).
++So at Gui@::So at Gui@(void) { }
++So at Gui@::~So at Gui@() { }
++
++// *************************************************************************
++
++cc_mutex * SoGuiP::gllockmutex = NULL;
++
++// *************************************************************************
++
++void
++SoGuiP::commonInit(void)
++{
++  SoDB::init();
++  SoNodeKit::init();
++  SoInteraction::init();
++
++  SoAny::init();
++
++  SoGuiP::gllockmutex = cc_mutex_construct();
++}
++
++void
++SoGuiP::commonCleanup(void)
++{
++  cc_mutex_destruct(SoGuiP::gllockmutex);
++}
++
++// *************************************************************************
++
++/*!
++  This function initializes the So at Gui@ library, as well as the
++  Inventor API. The latter is done by calling \a SoDB::init(), \a
++  SoNodeKit::init() and \a SoInteraction::init().
++
++  The returned @WIDGET@ is a toplevel shell widget for the
++  application, which can be used as a shell for the main component.
++
++  This method is provided for easier porting / compatibility with the
++  original SGI Inventor InventorXt library. It just adds dummy \a argc
++  and \a argv arguments and calls the So at Gui@::init() method below.
++*/
++ at WIDGET@
++So at Gui@::init(const char * appname, const char * classname)
++{
++  // If this is SoQt, Qt will keep a reference to the appname string
++  // -- so make it guaranteed permanent.
++  char * buf = NULL;
++  if (appname != NULL) {
++    size_t appname_len = strlen(appname);
++    buf = (char *)new char[appname_len+1]; // FIXME: minor memleak, free on app-exit. 20020117 mortene.
++    (void)strncpy(buf, appname, appname_len);
++    buf[appname_len] = '\0';
++  }
++
++  // FIXME: Both SoGui_init_argc/argv need to be static to workaround
++  // a compiler optimization memory corruption bug (observed with gcc
++  // 4.1.1 using -O2 in combination with qt-4.2.x), which would lead
++  // to a segfault. 20070528 tamer.
++
++  // Fake argc and argv setup, forward to real init routine.
++  static int SoGui_init_argc = (buf != NULL) ? 1 : 0;
++  static char * SoGui_init_argv[2]; // use static array to avoid memory corruption in Qt
++  SoGui_init_argv[0] = buf;
++  SoGui_init_argv[1] = NULL;
++
++  return So at Gui@::init(SoGui_init_argc, SoGui_init_argv, appname, classname);
++}
++
++/*!
++  \fn @WIDGET@ So at Gui@::init(int & argc, char ** argv, const char * appname, const char * classname)
++
++  This function initializes the So at Gui@ library, as well as the
++  Inventor API. The latter is done by calling \a SoDB::init(), \a
++  SoNodeKit::init() and \a SoInteraction::init().
++
++  Creates an application framework and constructs and returns a main
++  widget for you.
++
++  The returned @WIDGET@ is a toplevel shell widget for the
++  application, which can be used as a shell for the main component.
++*/
++
++/*!
++  \fn void So at Gui@::init(@WIDGET@ toplevelwidget)
++
++  This function initializes the So at Gui@ library, as well as the
++  Inventor API. The latter is done by calling \a SoDB::init(), \a
++  SoNodeKit::init() and \a SoInteraction::init().
++
++  Assumes you are creating your own application framework and main
++  widget.  \a toplevelwidget should be your application's main widget.
++*/
++
++/*!
++  \fn void So at Gui@::done(void)
++
++  Cleans up all static data allocated by the So at Gui@ library on
++  initialization.
++
++  This functions calls SoDB::finish() which means that no Coin classes
++  should be used after it has been called.
++
++  <!-- (Disabled: see FIXME in SoQt.cpp:855)
++  Is called implicitly from the end of So at Gui@::mainLoop(), so the
++  application programmer should not call it explicitly unless she
++  has taken control over the native event loop herself, and is
++  therefore not using So at Gui@::mainLoop().
++
++  (Even then it is usually not necessary to call this method, as the
++  operating system should take care of cleaning up resource use when
++  an application exits. This method is mainly provided as a manner to
++  be able to clean up in "unusual" run-time environments, for instance
++  if So at Gui@ is used as a component in a browser plug-in.)
++  -->
++
++  It should never be invoked more than \e once, and that
++  is just before application exit, as it deallocates \e static data
++  allocated as "one-off" operations in So at Gui@::init().
++  
++  NOTE: done() is not present in the original API for SGI's InventorXt
++  library.
++*/
++
++/*!
++  \fn void So at Gui@::mainLoop(void)
++
++  This is the event dispatch loop.
++
++  It doesn't return until application exit is somehow forced, either
++  programmatically from the relevant API-call of the native toolkit,
++  or when the user closes the application's main widget.
++  
++  After the main loop has finished execution, call So at Gui@::done() to clean 
++  up static data.
++
++  <!-- (Disabled: see FIXME in SoQt.cpp:855)
++  An important note: be careful about how you handle
++  So at Gui@Component-derived objects after the application control returns
++  from mainLoop(), as So at Gui@ will then have been "cleaned up" with
++  regards to various internal resources. So doing for instance
++  something like this:
++
++  \code
++  So at Gui@::mainLoop();
++  viewer->hide();
++  \endcode
++
++  ..spells "undefined behavior, expect a crash".
++
++  \e Deleting a component after mainLoop() returns is allowed, though,
++  and also necessary to avoid getting reports of possible memory leaks
++  from memleak checkers.
++  -->
++*/
++
++/*!
++  \fn void So at Gui@::exitMainLoop(void)
++
++  This function will make the main event loop finish looping.
++
++  NOTE: exitMainLoop() is not present in the original API for SGI's
++  InventorXt library.
++*/
++
++/*!
++  \fn @WIDGET@ So at Gui@::getTopLevelWidget(void)
++
++  Returns the @WIDGET@ which is the main widget for the
++  application. When this widget gets closed, So at Gui@::mainLoop() will
++  return (unless the close event is caught by the user).
++
++  \sa getShellWidget()
++*/
++
++// *************************************************************************
++
++/*!
++  This method will fill in the integers pointed to by the arguments
++  with the corresponding part of the version release number of the
++  So at Gui@ library.
++
++  A \c NULL pointer will make that part of the version number be ignored.
++
++  This method is not part of the original InventorXt API from SGI.
++*/
++void
++So at Gui@::getVersionInfo(int * major, int * minor, int * micro)
++{
++  if (major) { *major = SO at GUI@_MAJOR_VERSION; }
++  if (minor) { *minor = SO at GUI@_MINOR_VERSION; }
++  if (micro) { *micro = SO at GUI@_MICRO_VERSION; }
++}
++
++/*!
++  This method returns a string containing the version id of the
++  library.
++
++  This method is not part of the original InventorXt API from SGI.
++*/
++const char *
++So at Gui@::getVersionString(void)
++{
++  static const char version[] = SO at GUI@_VERSION;
++  return version;
++}
++
++/*!
++  This method returns a string containing the version id of the
++  @Gui@ toolkit the So at Gui@ library is linked against.
++
++  This method is not part of the original InventorXt API from SGI.
++*/
++#ifdef SOWIN_INTERNAL
++namespace Win32 {
++  std::string GetOSDisplayString();
++};
++#endif
++
++const char *
++So at Gui@::getVersionToolkitString(void)
++{
++#ifdef SOWIN_INTERNAL
++  static std::string toolkit_version = Win32::GetOSDisplayString();
++#else
++  static std::string toolkit_version = GUI_TOOLKIT_VERSION;
++#endif
++  return toolkit_version.c_str();
++}
++
++// *************************************************************************
++
++/*!
++  This method locks other threads out from a code section until the
++  caller thread invokes So at Gui@::unlockGL().
++
++  It is meant to protect several threads invoking OpenGL calls in
++  parallell, in case the underlying OpenGL implementation is not
++  multi-thread safe.
++
++  For convenience, the function can be invoked through the
++  SO at GUI@_ENTER_GL_SECTION().
++
++  This method is not part of the original InventorXt API from SGI.
++*/
++void
++So at Gui@::lockGL(void)
++{
++  assert(SoGuiP::gllockmutex);
++
++  cc_mutex_lock(SoGuiP::gllockmutex);
++}
++
++/*!
++  See documentation for So at Gui@::lockGL().
++
++  For convenience, the function can be invoked through the
++  SO at GUI@_LEAVE_GL_SECTION().
++
++  This method is not part of the original InventorXt API from SGI.
++*/
++void
++So at Gui@::unlockGL(void)
++{
++  cc_mutex_unlock(SoGuiP::gllockmutex);
++}
++
++// *************************************************************************
++
++/*!
++  \typedef void So at Gui@::FatalErrorCB(const SbString errmsg, So at Gui@::FatalErrors errcode, void * userdata)
++
++  An application function callback for handling fatal errors should be
++  of this type.
++
++  The first argument is an error message in English describing the
++  details of the error. The second argument is an error code used so
++  the application can identify specific conditions. The third argument
++  is the userdata pointer passed in to So at Gui@::setFatalErrorHandler().
++*/
++
++/*!
++  \enum So at Gui@::FatalErrors
++  Numerical identifiers for classifying the different kinds of possible
++  fatal errors.
++*/
++
++/*!
++  \var So at Gui@::FatalErrors So at Gui@::NO_OPENGL_CANVAS
++
++  Could not construct \e any valid OpenGL canvas. Something is very
++  wrong on the client system.
++*/
++/*!
++  \var So at Gui@::FatalErrors So at Gui@::INTERNAL_ASSERT
++
++  An internal error condition that should never happen was
++  detected. The most likely cause of this is programmering errors
++  within the So at Gui@ library itself.
++*/
++/*!
++  \var So at Gui@::FatalErrors So at Gui@::UNSPECIFIED_ERROR
++
++  Signifies that we were not able to specify in any greater detail the
++  error condition that came up.
++*/
++
++/*!
++  Set up a callback to invoke in the case of unexpected fatal error
++  conditions within the So at Gui@ library.
++
++  Almost any error condition within the library is handled in a robust
++  way through return values indicating errors for the offending calls,
++  but there are a few cases that are impossible to handle without
++  seriously crippling the functionality.
++
++  (One example is if we fail to find \e any way of making a valid
++  OpenGL canvas. This is an indication that something is seriously
++  wrong on the end-user's system, and the So at Gui@ library will not work
++  properly.)
++
++  In the case of a fatal error, it is expected that the given
++  application callback function communicates the problem to the
++  end-user and then either exits the application or at least refrains
++  from using any part of the So at Gui@ library.
++
++  If no callback is explicitly set up by the application, the So at Gui@
++  library will display an error message to the end-user and then exit
++  the application.
++
++  When setting a callback, this method returns a pointer to the
++  previous callback function, or \c NULL if none.
++
++  (This is an extension versus the original SGI InventorXt library
++  API.)
++
++
++  On a related note, be aware that the end-user will still be notified
++  about non-fatal errors and warning messages through a dialog box. If
++  you want to handle these yourself, or if you don't want your
++  end-user to see any of these non-critical messages, you will also
++  need to install an error handler callback function on the Coin
++  library itself:
++
++  \code
++    SoDebugError::setHandlerCallback(myErrorHandlerCB, myCBUserData);
++  \endcode
++
++  (Please also see the documentation of
++  SoDebugError::setHandlerCallback().)
++
++ */
++So at Gui@::FatalErrorCB *
++So at Gui@::setFatalErrorHandler(So at Gui@::FatalErrorCB * cb, void * userdata)
++{
++  return SoAny::si()->setFatalErrorHandler(cb, userdata);
++}
++
++// *************************************************************************
++
++/*!
++  Returns \c TRUE if this binary version of the So at Gui@ library was
++  compiled with debug settings on.
++
++  This method was not part of the original SGI InventorXt library, but
++  is an extension specific to the Coin project.
++*/
++SbBool
++So at Gui@::isDebugLibrary(void)
++{
++  return SO at GUI@_DEBUG != 0 ? TRUE : FALSE;
++}
++
++/*!
++  Returns \c TRUE if this version of the So at Gui@ library has an
++  Application Binary Interface compatible with the given version.
++
++  This method was not part of the original SGI InventorXt library, but
++  is an extension specific to the Coin project.
++*/
++SbBool
++So at Gui@::isCompatible(unsigned int major, unsigned int minor)
++{
++  if (major != SO at GUI@_MAJOR_VERSION) { return FALSE; }
++  if (minor > SO at GUI@_MINOR_VERSION) { return FALSE; }
++  return TRUE;
++}
++
++/*!
++  \enum So at Gui@::ABIType
++  Numerical identifiers to identify how the library was built.
++*/
++/*!
++  \var So at Gui@::ABIType So at Gui@::DLL
++  The So at Gui@ library was built as a dynamic link library (aka "shared
++  library").
++*/
++/*!
++  \var So at Gui@::ABIType So at Gui@::LIB
++  The So at Gui@ library was built as a static library.
++*/
++/*!
++  \var So at Gui@::ABIType So at Gui@::UNKNOWN
++  The So at Gui@ introspection mechanisms can not decide how the library
++  was built.
++*/
++
++
++/*!
++  Returns an indication on how the library was compiled: as a dynamic
++  library, or as a static library.
++
++  This method was not part of the original SGI InventorXt library, but
++  is an extension specific to the Coin project.
++*/
++So at Gui@::ABIType
++So at Gui@::getABIType(void)
++{
++  // FIXME: replace this ugly shit with a configure-check to test if
++  // we're on a DLL-capable platform. 20020118 mortene.
++#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
++#ifdef SO at GUI@_MAKE_DLL
++  return So at Gui@::DLL;
++#else
++  return So at Gui@::LIB;
++#endif
++#endif
++  // FIXME: this is rather lame, we have enough information in the
++  // configure / build process to always know whether we're building
++  // static or dynamic. 20020618 mortene.
++  return So at Gui@::UNKNOWN;
++}
++
++#if 0 // FIXME: not in use, see larsa's FIXME below. 20020617 mortene.
++
++// *************************************************************************
++// These sanity checks are designed to detect common pitfall errors for
++// Microsoft Windows linkage with So at Gui@ and Coin.
++
++// FIXME: use an "is-this-a-DLL-capable-platform" configure check
++// and remove the system "#if defined" tests below. 20011203 mortene.
++// FIXME: I disabled this because it wasn't inlined in the client app
++// but compiled into the library by MSVC++ and with SOWIN_DLL undefined,
++// the ABI test always tried the LIB_ABI path.  20020126 larsa
++#if 0 && (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__))
++#define SO at GUI@_SANITY_CHECK(forward_call)                  \
++  if (So at Gui@::isDebugLibrary() &&                       \
++       SoDB::isInitialized())                          \
++    SoDebugError::postWarning("So at Gui@::init",            \
++      "unable to verify application linkage sanity "    \
++      "because Open Inventor has already been "         \
++      "initialized before So at Gui@::init call");           \
++  SO at GUI@_RUNTIME_SANITY_CHECK();                         \
++  SO at GUI@_LINKSTYLE_SANITY_CHECK();                       \
++  forward_call;                                         \
++  SO at GUI@_LINKTIME_SANITY_CHECK()
++
++#define SO at GUI@_RUNTIME_SANITY_CHECK()                    \
++  do {                                                  \
++    if (!So at Gui@::isCompatible(SO at GUI@_MAJOR_VERSION,      \
++                            SO at GUI@_MINOR_VERSION))      \
++      So at Gui@::abort(SO at GUI@_RUNTIME_MISMATCH);             \
++  } while (FALSE)
++
++#ifdef SO at GUI@_DLL
++#define SO at GUI@_LINKSTYLE_SANITY_CHECK()                  \
++  do {                                                  \
++    if (So at Gui@::getABIType() != SO at GUI@_DLL_ABI)         \
++      So at Gui@::abort(SO at GUI@_LINKSTYLE_MISMATCH);           \
++  } while (FALSE)
++#else
++#define SO at GUI@_LINKSTYLE_SANITY_CHECK()                  \
++  do {                                                  \
++    if (So at Gui@::getABIType() != SO at GUI@_LIB_ABI)         \
++      So at Gui@::abort(SO at GUI@_LINKSTYLE_MISMATCH);           \
++  } while (FALSE)
++#endif
++
++#define SO at GUI@_LINKTIME_SANITY_CHECK()                   \
++  do {                                                  \
++    if (!SoDB::isInitialized())                       \
++      So at Gui@::abort(SO at GUI@_LINKTIME_MISMATCH);            \
++  } while (FALSE)
++#else /* ! MS Windows */
++#define SO at GUI@_SANITY_CHECK(forward_call)                \
++  forward_call
++#endif /* ! MS Windows */
++
++#endif // OBSOLETED
++
++#ifndef DOXYGEN_SKIP_THIS
++
++// Abort the application due to some kind of mismatch in the ABI
++// settings / configuration. This should hopefully help application
++// programmers avoid shooting themselves in the foot by controlling
++// certain run-time parameters in the client application versus what
++// is expected by the So at Gui@ library.
++//
++// If you're an application programmer, it is very likely that you
++// only need to consider this an internal library method.
++//
++// This method was not part of the original SGI InventorXt library,
++// but is an extension specific to the Coin project.
++void
++SoGuiP::abort(SoGuiP::ABIError error)
++{
++  switch (error) {
++  case SoGuiP::LINKTIME_MISMATCH:
++    So at Gui@::createSimpleErrorDialog(NULL, "Fatal Error",
++                                     "Detected linktime mismatch error.");
++    break;
++
++  case SoGuiP::LINKSTYLE_MISMATCH:
++    So at Gui@::createSimpleErrorDialog(NULL, "Fatal Error",
++                                     "Detected linkstyle mismatch error (DLL vs. LIB).");
++    break;
++
++  case SoGuiP::RUNTIME_MISMATCH:
++    So at Gui@::createSimpleErrorDialog(NULL, "Fatal Error",
++                                     "Detected runtime mismatch error (versioning and ABI compatibility).");
++    break;
++
++  default:
++    // FIXME: shouldn't this rather be an assert? 20020118 mortene.
++    So at Gui@::createSimpleErrorDialog(NULL, "Fatal Error",
++                                     "Unknown error in So at Gui@ :(");
++    break;
++  }
++
++  // FIXME: call fatal error handler in SoAny. 20020118 mortene.
++  exit(-1);
++}
++
++#endif // DOXYGEN_SKIP_THIS
++
++// *************************************************************************
++
++/*!
++  \fn void So at Gui@::createSimpleErrorDialog(@WIDGET@ widget, const char * title, const char * string1, const char * string2)
++
++
++  This is a convenient way for the application programmer to throw up
++  an obtrusive application-global error dialog.
++
++  If \a widget is \c NULL, the dialog will be modal for the whole
++  application (all windows will be blocked for input). If not,
++  only the window for the given \a widget will be blocked.
++
++  \a title is the title of the dialog box. \a string1 and \a string2
++  contains the text which will be shown in the dialog box.
++
++  There will only be a single "Ok" button for the user to press and
++  continue with the application.
++*/
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiComponent.h.in
+@@ -0,0 +1,174 @@
++#ifndef SO at GUI@_COMPONENT_H
++#define SO at GUI@_COMPONENT_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/SbLinear.h>
++#include <Inventor/@Gui@/So at Gui@Object.h>
++
++#ifdef __COIN_SOQT__
++class QWidget;
++#endif // __COIN_SOQT__
++#ifdef __COIN_SOXT__
++#include <X11/Intrinsic.h>
++#endif // __COIN_SOXT__
++#ifdef __COIN_SOGTK__
++#include <gtk/gtk.h>
++#endif // __COIN_SOGTK__
++#ifdef __COIN_SOWIN__
++#include <windows.h>
++#endif // __COIN_SOWIN__
++
++
++class So at Gui@Component;
++class So at Gui@Cursor;
++
++typedef void So at Gui@ComponentCB(void * user, So at Gui@Component * component);
++typedef void So at Gui@ComponentVisibilityCB(void * user, SbBool visible);
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@Component : public So at Gui@Object {
++  SO at GUI@_OBJECT_ABSTRACT_HEADER(So at Gui@Component, So at Gui@Object);
++
++public:
++  virtual ~So at Gui@Component();
++
++  virtual void show(void);
++  virtual void hide(void);
++
++  virtual void setComponentCursor(const So at Gui@Cursor & cursor);
++  static void setWidgetCursor(@WIDGET@ w, const So at Gui@Cursor & cursor);
++
++  SbBool isFullScreen(void) const;
++  SbBool setFullScreen(const SbBool onoff);
++
++  SbBool isVisible(void);
++  SbBool isTopLevelShell(void) const;
++
++  @WIDGET@ getWidget(void) const;
++  @WIDGET@ getBaseWidget(void) const;
++  @WIDGET@ getShellWidget(void) const;
++  @WIDGET@ getParentWidget(void) const;
++
++  void setSize(const SbVec2s size);
++  SbVec2s getSize(void) const;
++
++  void setTitle(const char * const title);
++  const char * getTitle(void) const;
++  void setIconTitle(const char * const title);
++  const char * getIconTitle(void) const;
++
++  const char * getWidgetName(void) const;
++  const char * getClassName(void) const;
++
++  void setWindowCloseCallback(So at Gui@ComponentCB * const func,
++                              void * const user = NULL);
++  static So at Gui@Component * getComponent(@WIDGET@ widget);
++
++  static void initClasses(void);
++
++protected:
++  So at Gui@Component(@WIDGET@ const parent = NULL,
++                   const char * const name = NULL,
++                   const SbBool embed = TRUE);
++
++  virtual void afterRealizeHook(void);
++
++  // About the wrapping below: this variable was added after SoQt 1.0,
++  // and before SoXt 1.1. To be able to release SoQt 1.1 from this
++  // same branch, sizeof(SoQtComponent) needs to be the same as for
++  // SoQt 1.0, which means we can't add this variable for SoQt.
++#ifndef __COIN_SOQT__
++  SbBool firstRealize;
++#endif // __COIN_SOQT__
++
++  void setClassName(const char * const name);
++  void setBaseWidget(@WIDGET@ widget);
++
++  void registerWidget(@WIDGET@ widget);
++  void unregisterWidget(@WIDGET@ widget);
++
++  virtual const char * getDefaultWidgetName(void) const;
++  virtual const char * getDefaultTitle(void) const;
++  virtual const char * getDefaultIconTitle(void) const;
++
++  virtual void sizeChanged(const SbVec2s & size);
++
++  void addVisibilityChangeCallback(So at Gui@ComponentVisibilityCB * const func,
++                                   void * const user = NULL);
++  void removeVisibilityChangeCallback(So at Gui@ComponentVisibilityCB * const func,
++                                      void * const user = NULL);
++
++private:
++  class So at Gui@ComponentP * pimpl;
++  friend class SoGuiComponentP;
++  friend class So at Gui@ComponentP;
++
++  // FIXME!: audit and remove as much as possible of the remaining
++  // toolkit specific parts below. 20020117 mortene.
++
++#ifdef __COIN_SOXT__
++public:
++  Display * getDisplay(void);
++  void fitSize(const SbVec2s size);
++  // FIXME: I guess these should really be part of the common
++  // API. 20011012 mortene.
++  void addWindowCloseCallback(SoXtComponentCB * callback, void * closure = NULL);
++  void removeWindowCloseCallback(SoXtComponentCB * callback, void * closure = NULL);
++
++protected:
++  // FIXME: I guess this should perhaps be part of the common API?
++  // 20011012 mortene.
++  void invokeVisibilityChangeCallbacks(const SbBool enable) const;
++  void invokeWindowCloseCallbacks(void) const;
++  virtual void windowCloseAction(void);
++
++private:
++  // FIXME: get rid of this? 20011012 mortene.
++  static void event_handler(Widget, XtPointer, XEvent *, Boolean *);
++#endif // __COIN_SOXT__
++
++#ifdef __COIN_SOGTK__
++protected:
++  virtual SbBool eventFilter(GtkWidget * object, GdkEvent * event);
++private:
++  static gint eventHandler(GtkWidget * object, GdkEvent * event, gpointer closure);
++#endif // __COIN_SOGTK__
++};
++
++// *************************************************************************
++
++#endif // ! SO at GUI@_COMPONENT_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiComponentCommon.cpp.in
+@@ -0,0 +1,549 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/*!
++  \class So at Gui@Component So at Gui@Component.h Inventor/@Gui@/So at Gui@Component.h
++  \brief The So at Gui@Component class is the base class for all GUI components.
++
++  Components in the So at Gui@ component library all inherit this
++  abstract base class. It provides basic methods for setting and
++  querying about the relationship between the component object and its
++  underlying @Gui@ object(s).
++
++  Application programmers should not need to interface any code
++  against this class, unless they want to extend the So at Gui@ library
++  in entirely new directions. For making new viewer components, for
++  instance, other classes further down the inheritance hierarchy would
++  be better suited for subclassing.
++
++  Note that the relationship between all So at Gui@Component derived
++  classes and @Gui@ widgets is one of "has-A", \e not "is-A" --
++  i.e. So at Gui@Component \e contains a @WIDGET@, it doesn't derive from
++  or subclass it.
++*/
++
++#include <Inventor/@Gui@/So at Gui@.h>
++#include <Inventor/@Gui@/So at Gui@Component.h>
++#include <Inventor/@Gui@/So at Gui@ComponentP.h>
++
++#include <Inventor/SbPList.h>
++
++/*!
++  \fn void So at Gui@Component::initClasses(void)
++
++  This function initializes the type system for all the component
++  classes.  It is called indirectly for you when you call
++  So at Gui@::init().
++
++  \sa So at Gui@::init(), So at Gui@Device::initClasses()
++*/
++
++/*!
++  \fn So at Gui@Component::So at Gui@Component(@WIDGET@ const parent, const char * const name, const SbBool embed)
++
++  This is a protected constructor, used only by derived classes.
++
++  The \a parent argument is the parent widget of the component.  If
++  you don't supply a parent, the main window (the one given to or
++  returned from So at Gui@::init()) is used (and the \a embed argument is
++  considered to be \c FALSE).
++
++  The \a name argument is the name of the component. If you don't
++  supply one, the name will default to something, depending on the
++  inheritance hierarchy.
++
++  The \a embed argument tells wether the component should be embedded
++  in the \a parent widget or should create its own shell. This flag is
++  only checked if the \a parent widget argument is specified (not
++  \c NULL).
++
++  If you create a non-embedded component, the component will create
++  its own shell, which will be a toplevelshell type. If you embed the
++  component, the component will create a formwidget type widget inside
++  the \a parent widget, which you can get the handle of by calling
++  So at Gui@Component::getBaseWidget().
++*/
++
++/*!
++  \fn So at Gui@Component::~So at Gui@Component()
++
++  Destructor.
++*/
++
++/*!
++  \fn void So at Gui@Component::addVisibilityChangeCallback(So at Gui@ComponentVisibilityCB * const func, void * const user)
++
++  Add a callback which will be called whenever the widget component
++  changes visibility status (because of iconification or
++  deiconification, for instance).
++
++  \sa removeVisibilityChangeCallback(), isVisible()
++*/
++
++/*!
++  \fn void So at Gui@Component::removeVisibilityChangeCallback(So at Gui@ComponentVisibilityCB * const func, void * const data)
++
++  Remove one of the callbacks from the list of visibility notification
++  callbacks.
++
++  \sa addVisibilityChangeCallback(), isVisible()
++*/
++
++/*!
++  \fn void So at Gui@Component::setClassName(const char * const name)
++
++  Set class name of component.
++
++  \sa getClassName(), componentClassName()
++*/
++
++/*!
++  \fn void So at Gui@Component::setBaseWidget(@WIDGET@ widget)
++
++  Set the core widget for this So at Gui@ component. It is important that
++  subclasses get this correct, as the widget set here will be the
++  widget returned from query methods.
++
++  \sa baseWidget()
++*/
++
++/*!
++  \fn void So at Gui@Component::show(void)
++
++  This will show the widget, de-iconifiying and raising it if
++  necessary.
++
++  \sa hide(), isVisible()
++*/
++
++/*!
++  \fn void So at Gui@Component::hide(void)
++
++  This will hide the widget.
++
++  \sa show(), isVisible()
++*/
++
++/*!
++  \fn SbBool So at Gui@Component::isVisible(void)
++
++  Returns visibility status on the widget. If any parents of this
++  widget or this widget itself is hidden, returns \c FALSE.
++
++  Note that a widget which is just obscured by other windows on the
++  desktop is not hidden in this sense, and \c TRUE will be returned.
++
++  \sa show(), hide()
++*/
++
++/*!
++  \fn @WIDGET@ So at Gui@Component::getWidget(void) const
++
++  Returns a pointer to the component's window system widget.
++
++  \sa getShellWidget(), getParentWidget()
++*/
++
++/*!
++  \fn @WIDGET@ So at Gui@Component::getBaseWidget(void) const
++
++  An So at Gui@Component may be composed of any number of widgets in
++  parent-children relationships in a tree structure with any depth.
++  This method will return the root widget in that tree.
++
++  \sa setBaseWidget()
++*/
++
++/*!
++  \fn SbBool So at Gui@Component::isTopLevelShell(void) const
++
++  Returns \c TRUE if this component is a toplevel shell, i.e. it has a
++  window representation on the desktop.
++
++  \sa getShellWidget()
++*/
++
++/*!
++  This method returns the shell widget of the component, but only if
++  it was created as a toplevel shell.  \c NULL will be returned for
++  embedded components.
++
++  (The toplevel shell is the desktop window which contains the
++  component.)
++
++  To get the toplevel shell of embedded components, you can use the
++  So at Gui@::getShellWidget() method.
++
++  \sa isTopLevelShell(), getWidget()
++*/
++ at WIDGET@
++So at Gui@Component::getShellWidget(void) const
++{
++  @WIDGET@ w = this->getWidget();
++  // the below assert disables SoXt, so I've removed it for now
++  // 20031001 larsa
++  // assert(w == NULL && "widget not built yet!");
++  return (this->isTopLevelShell() && w) ? So at Gui@::getShellWidget(w) : NULL;
++}
++
++/*!
++  \fn @WIDGET@ So at Gui@Component::getParentWidget(void) const
++
++  Returns the widget which is the parent (i.e. contains) this
++  component's base widget.
++
++  \sa getWidget(), baseWidget(), isTopLevelShell()
++*/
++
++/*!
++  \fn void So at Gui@Component::setTitle(const char * const title)
++
++  Set the window title of this component. The title will appear on the
++  window title bar, if the component manages its own window.
++
++  \if SOQT_DOC
++
++  Note that there is one peculiarity to be aware of if you are using
++  the non-commercial version of Qt: only window titles with the
++  substring "Qt" in them are allowed (!), and attempts to set a window
++  title without this substring will simply be ignored.
++
++  \endif
++
++  \sa getTitle(), setIconTitle(), isTopLevelShell()
++*/
++
++/*!
++  \fn const char * So at Gui@Component::getTitle(void) const
++
++  Returns the window title.
++
++  If a title has been set, that title will be returned.
++  If no title has been set, the default title is returned.
++
++  \sa setTitle(), isTopLevelShell()
++*/
++
++/*!
++  \fn void So at Gui@Component::setIconTitle(const char * const title)
++
++  This method sets the title of the icon representation of the window.
++
++  The title will appear on the window icon, if the component manages
++  its own window.
++
++  \sa getIconTitle(), setTitle(), isTopLevelShell()
++*/
++
++/*!
++  \fn const char * So at Gui@Component::getIconTitle(void) const
++
++  Returns the title the window has when iconfied.
++
++  If an icon title has been set, that icon title is returned.  If no
++  icon title has been set, the default icon title is returned.
++
++  \sa setIconTitle(), isTopLevelShell()
++*/
++
++/*!
++  \fn const char * So at Gui@Component::getWidgetName(void) const
++
++  Returns name of the widget.
++*/
++
++/*!
++  \fn const char * So at Gui@Component::getClassName(void) const
++
++  Returns class name of widget.
++*/
++
++/*!
++  This method returns the default name of a component widget class.
++
++  It should be overridden by derived non-abstract classes for the
++  topmost widget in the component to have a proper name.
++*/
++const char *
++So at Gui@Component::getDefaultWidgetName(void) const
++{
++  return "So at Gui@Component";
++}
++
++/*!
++  This method returns the default window caption string of the
++  component.
++
++  It should be overridden by derived non-abstract classes so the
++  window and popup menu will get a proper title.
++*/
++const char *
++So at Gui@Component::getDefaultTitle(void) const
++{
++  return "@Gui@ Component";
++}
++
++/*!
++  This method returns the default icon title of the component.
++
++  It should be overridden by derived non-abstract classes so icons
++  will get proper titles.
++*/
++const char *
++So at Gui@Component::getDefaultIconTitle(void) const
++{
++  return "@Gui@ Component";
++}
++
++/*!
++  \fn void So at Gui@Component::setSize(const SbVec2s size)
++
++  Resize the component widget.
++
++  The method assumes the caller knows what he is doing.
++
++  \sa getSize()
++*/
++
++/*!
++  \fn SbVec2s So at Gui@Component::getSize(void) const
++
++  Returns the component widget size.
++
++  The size that is returned is a cached size value, not a value
++  fetched from the GUI system.
++
++  \sa setSize()
++*/
++
++/*!
++  \fn void So at Gui@Component::sizeChanged(const SbVec2s & size)
++
++  Called internally from within the So at Gui@ library when the widget
++  embedded in a component changes it size, which is usually triggered
++  by end-user interaction.
++
++  This method is then invoked to notify the component that the size
++  has changed.  It is called from the top and all the way down to the
++  bottom, the size being adjusted to take into account extra
++  decorations having been added at each level in the component class
++  hierarchy.
++*/
++
++/*!
++  \fn void So at Gui@Component::setWindowCloseCallback(So at Gui@ComponentCB * const func, void * const data)
++
++  Set up a callback function to use when the component gets closed. A
++  component must be a toplevel shell for this to have any effect.
++
++  For toplevel shells with no close callback set, the window will
++  simply be hidden. The typical action to take in the callback would
++  be to delete the component.
++
++  \sa isTopLevelShell()
++*/
++
++/*!
++  \fn SbBool So at Gui@Component::setFullScreen(const SbBool onoff)
++
++  Toggle full screen mode for this component, if possible.
++
++  Returns \c FALSE if operation failed.  This might happen if the
++  toolkit doesn't support attempts at making the component cover the
++  complete screen or if the component is not a toplevel window.
++*/
++
++/*!
++  \fn SbBool So at Gui@Component::isFullScreen(void) const
++
++  Returns if this widget/component is in full screen mode.
++*/
++
++/*!
++  \fn void So at Gui@Component::setComponentCursor(const So at Gui@Cursor & cursor)
++
++  Sets the cursor for this component.
++
++  Note: not part of the original SGI InventorXt API.
++*/
++
++/*!
++  \fn void So at Gui@Component::setWidgetCursor(@WIDGET@ w, const So at Gui@Cursor & cursor)
++
++  Set cursor for a native widget in the underlying toolkit.
++
++  Note: not part of the original SGI InventorXt API.
++*/
++
++/*!
++  \fn void So at Gui@Component::afterRealizeHook(void)
++
++  A function "hook" / callback invoked just after the window for the
++  component has been realized.
++
++  Override this if you need specific initialization for your own
++  component or viewer class to happen right after it has been made
++  visible, but remember to call upwards in the inheritance hierarchy:
++
++  \code
++  void
++  MyLittleViewer::afterRealizeHook(void)
++  {
++    <superclass>::afterRealizeHook();
++    // [own initialization here]
++  }
++  \endcode
++*/
++
++
++
++// *************************************************************************
++
++/*!
++  This method should be used by subclasses to register the widgets
++  they set up from the underlying native toolkit, so they can be
++  "reverse" mapped to the owner component.
++
++  Subclasses failing to register the widgets they use will cause the
++  So at Gui@Component::getComponent() method to fail with those widgets.
++
++  \sa unregisterWidget(), getComponent()
++*/
++void
++So at Gui@Component::registerWidget(@WIDGET@ widget)
++{
++#if SO at GUI@_DEBUG && 0 // debug
++  SoDebugError::postInfo("So at Gui@Component::registerWidget",
++                         "registering widget %p", widget);
++#endif // debug
++
++  // In case widget was already present.
++  void * comp;
++  if (SoGuiComponentP::widget2compdict->find((unsigned long)widget, comp)) {
++    if (((So at Gui@Component *)comp) != this) {
++#if SO at GUI@_DEBUG
++      SoDebugError::postWarning("So at Gui@Component::registerWidget",
++                                "widget %p already registered on a different "
++                                "component", widget);
++#endif // SO at GUI@_DEBUG
++      SoGuiComponentP::widget2compdict->remove((unsigned long)widget);
++    }
++    else {
++      return;
++    }
++  }
++
++  SoGuiComponentP::widget2compdict->enter((unsigned long)widget, (void *)this);
++}
++
++/*!
++  Remove a previously registered native toolkit widget from the
++  widget-to-component mappings used by
++  So at Gui@Component::getComponent().
++
++  \sa registerWidget()
++*/
++void
++So at Gui@Component::unregisterWidget(@WIDGET@ widget)
++{
++#if SO at GUI@_DEBUG && 0 // debug
++  SoDebugError::postInfo("So at Gui@Component::unregisterWidget",
++                         "unregistering widget %p", widget);
++#endif // debug
++
++  // Ignore return value to allow a widget to be unregistered several
++  // times (it doesn't matter, just as it doesn't matter if a widget
++  // is registered multiple times).
++  (void)SoGuiComponentP::widget2compdict->remove((unsigned long)widget);
++}
++
++/*!
++  Finds and returns the So at Gui@Component corresponding to the given
++  @WIDGET@, if any. If the widget does not seem to belong to any
++  So at Gui@Component, \c NULL will be returned.
++*/
++So at Gui@Component *
++So at Gui@Component::getComponent(@WIDGET@ widget)
++{
++  void * comp;
++  if (!SoGuiComponentP::widget2compdict->find((unsigned long)widget, comp)) {
++    return NULL;
++  }
++  return (So at Gui@Component *)comp;
++}
++
++// *************************************************************************
++
++#ifndef DOXYGEN_SKIP_THIS
++
++// Remaining code is for the SoGuiComponentP "private implementation"
++// class.
++
++SbDict * SoGuiComponentP::widget2compdict = NULL;
++int SoGuiComponentP::nrofcomponents = 0;
++
++SoGuiComponentP::SoGuiComponentP(So at Gui@Component * publ)
++{
++  this->pub = publ;
++
++  if (SoGuiComponentP::widget2compdict == NULL) {
++    SoGuiComponentP::widget2compdict = new SbDict;
++  }
++  SoGuiComponentP::nrofcomponents++;
++}
++
++SoGuiComponentP::~SoGuiComponentP()
++{
++  SoGuiComponentP::nrofcomponents--;
++  if (SoGuiComponentP::nrofcomponents == 0) {
++#if SO at GUI@_DEBUG
++    // Check to see if widgets were forgotten (ie missing
++    // unregisterWidget() calls).
++    SbPList keys, values;
++    SoGuiComponentP::widget2compdict->makePList(keys, values);
++    for (int i=0; i < keys.getLength(); i++) {
++      SoDebugError::postWarning("SoGuiComponentP::~SoGuiComponentP",
++                                "widget %p not unregistered for component %p",
++                                keys[i], values[i]);
++    }
++#endif // SO at GUI@_DEBUG
++
++    delete SoGuiComponentP::widget2compdict;
++    SoGuiComponentP::widget2compdict = NULL;
++  }
++}
++
++#endif // DOXYGEN_SKIP_THIS
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiComponentP.h.in
+@@ -0,0 +1,67 @@
++#ifndef SOGUICOMPONENTP_H
++#define SOGUICOMPONENTP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/SbDict.h>
++
++class So at Gui@Component;
++
++// ************************************************************************
++
++// This class contains private data and methods used within the
++// SoGuiComponent class.
++
++class SoGuiComponentP
++{
++public:
++  ~SoGuiComponentP();
++
++  static SbDict * widget2compdict;
++
++  static int nrofcomponents;
++
++protected:
++  SoGuiComponentP(So at Gui@Component * publ);
++  So at Gui@Component * pub;
++};
++
++// ************************************************************************
++
++#endif // !SOGUICOMPONENTP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiCursor.cpp.in
+@@ -0,0 +1,414 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/*!
++  \class So at Gui@Cursor
++  \brief The So at Gui@Cursor class is used to set cursors for GUI components.
++  \ingroup misc
++
++  The class provides both a set of pre-defined cursor shapes, aswell
++  as the option to use custom bitmap graphics.
++
++  Instances of this class is usually made for passing in to the
++  So at Gui@Component::setComponentCursor() and
++  So at Gui@Component::setWidgetCursor() methods.
++*/
++
++#include <Inventor/@Gui@/So at Gui@Cursor.h>
++#include <Inventor/@Gui@/SoAny.h>
++#include <assert.h>
++
++/*!
++  \enum So at Gui@Cursor::Shape
++
++  For enumerating built-in shape types, that can be used without
++  having to specify cursor graphics. These are mapped to pre-defined
++  cursor shapes from the underlying toolkit.
++*/
++
++
++/*!
++  \var So at Gui@Cursor::Shape So at Gui@Cursor::CUSTOM_BITMAP
++
++  Cursor is specified with our own bitmap graphics. The bitmap data
++  must be passed into the constructor.
++*/
++
++/*!
++  \var So at Gui@Cursor::Shape So at Gui@Cursor::DEFAULT
++
++  Using the native Window system's default cursor.
++*/
++
++/*!
++  \var So at Gui@Cursor::Shape So at Gui@Cursor::BUSY
++
++  A busy cursor.
++*/
++
++/*!
++  \var So at Gui@Cursor::Shape So at Gui@Cursor::CROSSHAIR
++
++  Two thin lines in a cross.
++*/
++
++/*!
++  \var So at Gui@Cursor::Shape So at Gui@Cursor::UPARROW
++
++  Thick, upward-pointing arrow.
++*/
++
++/*** Graphic data for the mouse pointer bitmaps. ***********************/
++
++/*!
++  \class So at Gui@Cursor::CustomCursor
++  \brief The So at Gui@Cursor::CustomCursor class is used to specify bitmap data for So at Gui@Cursor custom cursors.
++*/
++
++/*!
++  \var SbVec2s So at Gui@Cursor::CustomCursor::dim
++
++  Size of cursor data. Can be anything from 1 pixel wide and high, up
++  to maximum 32 pixels in each dimension.
++*/
++/*!
++  \var SbVec2s So at Gui@Cursor::CustomCursor::hotspot
++
++  Position of cursor hotspot, ie the pixel of the cursor which is
++  considered to be the "pick point" when interacting with the canvas
++  or widgets.
++
++  The hotspot position should be specified relative to the uppermost,
++  leftmost corner (which is position <0, 0>).
++*/
++/*!
++  \var unsigned char * So at Gui@Cursor::CustomCursor::bitmap
++
++  The size of the array of bitmap data should be equal to
++  (width+7)/8*height, as each cursor pixel is specified with just two
++  bits, one in the bitmap array, one in the mask array.
++
++  The bitmap and mask bits should be laid out as follows:
++  \verbatim
++  B=1 and M=1 == black
++  B=0 and M=1 == white
++  B=0 and M=0 == transparency
++  B=1 and M=0 will give undefined results for some platforms, so avoid.
++  \endverbatim
++*/  
++/*!
++  \var unsigned char * So at Gui@Cursor::CustomCursor::mask
++
++  See doc of So at Gui@Cursor::CustomCursor::bitmap.
++*/
++
++/*** zoom-style cursor ******/
++
++#define ZOOM_WIDTH 16
++#define ZOOM_HEIGHT 16
++#define ZOOM_BYTES ((ZOOM_WIDTH + 7) / 8) * ZOOM_HEIGHT
++#define ZOOM_HOT_X 5
++#define ZOOM_HOT_Y 7
++
++static unsigned char zoom_bitmap[ZOOM_BYTES] =
++{
++  0x00, 0x0f, 0x80, 0x1c, 0x40, 0x38, 0x20, 0x70,
++  0x90, 0xe4, 0xc0, 0xcc, 0xf0, 0xfc, 0x00, 0x0c,
++  0x00, 0x0c, 0xf0, 0xfc, 0xc0, 0xcc, 0x90, 0xe4,
++  0x20, 0x70, 0x40, 0x38, 0x80, 0x1c, 0x00, 0x0f
++};
++
++static unsigned char zoom_mask_bitmap[ZOOM_BYTES] =
++{
++ 0x00,0x0f,0x80,0x1f,0xc0,0x3f,0xe0,0x7f,0xf0,0xff,0xf0,0xff,0xf0,0xff,0x00,
++ 0x0f,0x00,0x0f,0xf0,0xff,0xf0,0xff,0xf0,0xff,0xe0,0x7f,0xc0,0x3f,0x80,0x1f,
++ 0x00,0x0f
++};
++
++/*** pan-style cursor *******/
++
++#define PAN_WIDTH 16
++#define PAN_HEIGHT 16
++#define PAN_BYTES ((PAN_WIDTH + 7) / 8) * PAN_HEIGHT
++#define PAN_HOT_X 7
++#define PAN_HOT_Y 7
++
++static unsigned char pan_bitmap[PAN_BYTES] =
++{
++  0xc0, 0x03, 0x60, 0x02, 0x20, 0x04, 0x10, 0x08,
++  0x68, 0x16, 0x54, 0x2a, 0x73, 0xce, 0x01, 0x80,
++  0x01, 0x80, 0x73, 0xce, 0x54, 0x2a, 0x68, 0x16,
++  0x10, 0x08, 0x20, 0x04, 0x40, 0x02, 0xc0, 0x03
++};
++
++static unsigned char pan_mask_bitmap[PAN_BYTES] =
++{
++ 0xc0,0x03,0xe0,0x03,0xe0,0x07,0xf0,0x0f,0xe8,0x17,0xdc,0x3b,0xff,0xff,0xff,
++ 0xff,0xff,0xff,0xff,0xff,0xdc,0x3b,0xe8,0x17,0xf0,0x0f,0xe0,0x07,0xc0,0x03,
++ 0xc0,0x03
++};
++
++/*** rotate-style cursor ****/
++
++#define ROTATE_WIDTH 16
++#define ROTATE_HEIGHT 16
++#define ROTATE_BYTES ((ROTATE_WIDTH + 7) / 8) * ROTATE_HEIGHT
++#define ROTATE_HOT_X 6
++#define ROTATE_HOT_Y 8
++
++static unsigned char rotate_bitmap[ROTATE_BYTES] = {
++  0xf0, 0xef, 0x18, 0xb8, 0x0c, 0x90, 0xe4, 0x83,
++  0x34, 0x86, 0x1c, 0x83, 0x00, 0x81, 0x00, 0xff,
++  0xff, 0x00, 0x81, 0x00, 0xc1, 0x38, 0x61, 0x2c,
++  0xc1, 0x27, 0x09, 0x30, 0x1d, 0x18, 0xf7, 0x0f
++};
++
++static unsigned char rotate_mask_bitmap[ROTATE_BYTES] = {
++ 0xf0,0xef,0xf8,0xff,0xfc,0xff,0xfc,0xff,0x3c,0xfe,0x1c,0xff,0x00,0xff,0x00,
++ 0xff,0xff,0x00,0xff,0x00,0xff,0x38,0x7f,0x3c,0xff,0x3f,0xff,0x3f,0xff,0x1f,
++ 0xf7,0x0f
++};
++
++/*** just a blank cursor ****/
++
++#define BLANK_WIDTH 1
++#define BLANK_HEIGHT 1
++#define BLANK_BYTES ((BLANK_WIDTH + 7) / 8) * BLANK_HEIGHT
++#define BLANK_HOT_X 0
++#define BLANK_HOT_Y 0
++
++static unsigned char blank_bitmap[BLANK_BYTES] = { 0x00 };
++static unsigned char blank_mask_bitmap[BLANK_BYTES] = { 0x00 };
++
++/***********************************************************************/
++
++static So at Gui@Cursor::CustomCursor zoom;
++static So at Gui@Cursor::CustomCursor pan;
++static So at Gui@Cursor::CustomCursor rotate;
++static So at Gui@Cursor::CustomCursor blank;
++
++static So at Gui@Cursor * soguicursor_zoomcursor = NULL;
++static So at Gui@Cursor * soguicursor_pancursor = NULL;
++static So at Gui@Cursor * soguicursor_rotatecursor = NULL;
++static So at Gui@Cursor * soguicursor_blankcursor = NULL;
++
++static void soguicursor_atexit_cleanup(void)
++{
++  delete soguicursor_zoomcursor;
++  delete soguicursor_pancursor;
++  delete soguicursor_rotatecursor;
++  delete soguicursor_blankcursor;
++  soguicursor_zoomcursor = NULL;
++  soguicursor_pancursor = NULL;
++  soguicursor_rotatecursor = NULL;
++  soguicursor_blankcursor = NULL;
++}
++
++void
++So at Gui@Cursor::initClass(void)
++{
++  zoom.dim = SbVec2s(ZOOM_WIDTH, ZOOM_HEIGHT);
++  zoom.hotspot = SbVec2s(ZOOM_HOT_X, ZOOM_HOT_Y);
++  zoom.bitmap = zoom_bitmap;
++  zoom.mask = zoom_mask_bitmap;
++  
++  pan.dim = SbVec2s(PAN_WIDTH, PAN_HEIGHT);
++  pan.hotspot = SbVec2s(PAN_HOT_X, PAN_HOT_Y);
++  pan.bitmap = pan_bitmap;
++  pan.mask = pan_mask_bitmap;
++  
++  rotate.dim = SbVec2s(ROTATE_WIDTH, ROTATE_HEIGHT);
++  rotate.hotspot = SbVec2s(ROTATE_HOT_X, ROTATE_HOT_Y);
++  rotate.bitmap = rotate_bitmap;
++  rotate.mask = rotate_mask_bitmap;
++  
++  blank.dim = SbVec2s(BLANK_WIDTH, BLANK_HEIGHT);
++  blank.hotspot = SbVec2s(BLANK_HOT_X, BLANK_HOT_Y);
++  blank.bitmap = blank_bitmap;
++  blank.mask = blank_mask_bitmap;
++
++  soguicursor_zoomcursor = new So at Gui@Cursor(&zoom);
++  soguicursor_pancursor = new So at Gui@Cursor(&pan);
++  soguicursor_rotatecursor = new So at Gui@Cursor(&rotate);
++  soguicursor_blankcursor = new So at Gui@Cursor(&blank);
++  SoAny::atexit((SoAny::atexit_f*)soguicursor_atexit_cleanup, 0);
++}
++
++/*!
++  Default constructor. Creates a default cursor.
++*/
++So at Gui@Cursor::So at Gui@Cursor(void)
++{
++  this->commonConstructor(So at Gui@Cursor::DEFAULT, NULL);
++}
++
++/*!
++  Constructor with Shape argument, for setting up the cursor with a
++  pre-defined shape from the underlying native toolkit.
++*/
++So at Gui@Cursor::So at Gui@Cursor(const Shape shape)
++{ 
++  assert(shape != CUSTOM_BITMAP && "don't use this constructor for making CUSTOM_BITMAP cursors");
++  this->commonConstructor(shape, NULL);
++}
++
++/*!
++  Constructs a new custom bitmap cursor from \a cc.
++
++  Note that only a \e shallow copy will be made of the CustomCursor
++  bitmap and mask references, so don't deallocate the memory they use
++  until the So at Gui@Cursor has been destructed.
++
++  As for the format of the cursor bitmap data, see documentation of
++  So at Gui@Cursor::CustomCursor.
++*/
++So at Gui@Cursor::So at Gui@Cursor(const CustomCursor * ccarg)
++{ 
++  this->commonConstructor(CUSTOM_BITMAP, ccarg);
++}
++
++// Private common constructor.
++void
++So at Gui@Cursor::commonConstructor(const Shape shapearg, const CustomCursor * ccarg)
++{ 
++  this->shape = shapearg;
++  this->cc = NULL;
++
++  if (ccarg) {
++    assert(shape == CUSTOM_BITMAP);
++    this->cc = new CustomCursor;
++    *(this->cc) = *ccarg;
++  }
++}
++
++/*!
++  Constructor.
++*/
++So at Gui@Cursor::So at Gui@Cursor(const So at Gui@Cursor & cursor)
++{
++  this->commonConstructor(cursor.shape, cursor.cc);
++}
++
++/*!
++  Destructor
++*/
++So at Gui@Cursor::~So at Gui@Cursor()
++{
++  delete this->cc;
++}
++
++/*!
++  Equal operator.
++*/
++So at Gui@Cursor & 
++So at Gui@Cursor::operator=(const So at Gui@Cursor & c)
++{
++  delete this->cc;
++  this->cc = NULL;
++  this->commonConstructor(c.shape, c.cc);
++  return *this;
++}
++
++/*!
++  Returns the shape type.
++
++  If the cursor has been set by the application programmer to a bitmap
++  cursor, So at Gui@Cursor::CUSTOM_BITMAP is returned.
++*/
++So at Gui@Cursor::Shape 
++So at Gui@Cursor::getShape(void) const
++{
++  return this->shape;
++}
++
++/*!
++  Sets the cursor to a predefined shape.
++*/
++void 
++So at Gui@Cursor::setShape(const Shape shapearg)
++{
++  this->shape = shapearg;
++}
++
++/*!
++  Returns a reference to the current custom bitmap cursor.
++
++  Do not call this method unless So at Gui@Cursor::getShape() returns
++  So at Gui@Cursor::CUSTOM_BITMAP.
++*/
++const So at Gui@Cursor::CustomCursor &
++So at Gui@Cursor::getCustomCursor(void) const
++{
++  assert(cc!=NULL && "not a custom bitmap cursor");
++  return *(this->cc);
++}
++
++/*!
++  Returns a "zoom" indicator cursor.
++*/
++const So at Gui@Cursor &
++So at Gui@Cursor::getZoomCursor(void)
++{
++  return *soguicursor_zoomcursor;
++}
++
++/*!
++  Returns a cursor with "pan" graphics (ie for translation in the
++  camera normal plane).
++*/
++const So at Gui@Cursor &
++So at Gui@Cursor::getPanCursor(void)
++{
++  return *soguicursor_pancursor;
++}
++
++/*!
++  Returns a "rotate" indicator cursor.
++*/
++const So at Gui@Cursor &
++So at Gui@Cursor::getRotateCursor(void)
++{
++  return *soguicursor_rotatecursor;
++}
++
++/*!
++  Because all toolkits don't easily support setting up a blank cursor
++  from pre-defined shapes or API functions, we also provide a simple
++  completely transparent cursor.
++*/
++const So at Gui@Cursor &
++So at Gui@Cursor::getBlankCursor(void)
++{
++  return *soguicursor_blankcursor;
++}
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiCursor.h.in
+@@ -0,0 +1,87 @@
++#ifndef SO at GUI@_CURSOR_H
++#define SO at GUI@_CURSOR_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/SbLinear.h>
++#include <Inventor/@Gui@/So at Gui@Basic.h>
++
++class SO at GUI@_DLL_API So at Gui@Cursor {
++public:
++  static void initClass(void);
++
++  struct CustomCursor {
++    SbVec2s dim;
++    SbVec2s hotspot;
++    unsigned char * bitmap;
++    unsigned char * mask;
++  };
++
++
++  // FIXME: add more default shapes. 20011119 pederb.
++  enum Shape {
++    CUSTOM_BITMAP = -1,
++    DEFAULT = 0,
++    BUSY,
++    CROSSHAIR,
++    UPARROW
++  };
++  
++  So at Gui@Cursor(void);
++  So at Gui@Cursor(const Shape shape);
++  So at Gui@Cursor(const CustomCursor * cc);
++  So at Gui@Cursor(const So at Gui@Cursor & cursor);
++  ~So at Gui@Cursor();
++
++  So at Gui@Cursor & operator=(const So at Gui@Cursor & c);
++
++  Shape getShape(void) const;
++  void setShape(const Shape shape);
++
++  const CustomCursor & getCustomCursor(void) const;
++
++  static const So at Gui@Cursor & getZoomCursor(void);
++  static const So at Gui@Cursor & getPanCursor(void);
++  static const So at Gui@Cursor & getRotateCursor(void);
++  static const So at Gui@Cursor & getBlankCursor(void);
++  
++private:
++  void commonConstructor(const Shape shape, const CustomCursor * cc);
++
++  Shape shape;
++  CustomCursor * cc;
++};
++
++#endif // ! SO at GUI@_CURSOR_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiGLWidget.h.in
+@@ -0,0 +1,229 @@
++#ifndef SO at GUI@_GLWIDGET_H
++#define SO at GUI@_GLWIDGET_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/SbBasic.h>
++#include <Inventor/@Gui@/So at Gui@Basic.h>
++#include <Inventor/@Gui@/So at Gui@Component.h>
++
++#ifdef __COIN_SOQT__
++class QEvent;
++#endif // __COIN_SOQT__
++#ifdef __COIN_SOXT__
++/*
++ * GL/glx.h includes X11/Xmd.h which contains typedefs for BOOL and
++ * INT32 that conflict with the definitions in windef.h (which is
++ * included from windows.h, which may be included from
++ * Inventor/system/gl.h).  To avoid this conflict, we rename the
++ * typedefs done in X11/Xmd.h to use other names (tempbool and
++ * tempint32), and try to clean up the hack after the header has been
++ * parsed.  2003-06-25 larsa
++ */
++#ifndef BOOL
++#define BOOL tempbool
++#define COIN_DEFINED_BOOL
++#endif /* !BOOL */
++#ifndef INT32
++#define INT32 tempint32
++#define COIN_DEFINED_INT32
++#endif /* !INT32 */
++#include <GL/glx.h>
++/*
++ * This is the cleanup part of the X11/Xmd.h conflict fix hack set up
++ * above.  2003-06-25 larsa
++ */
++#ifdef COIN_DEFINED_BOOL
++#undef BOOL
++#undef COIN_DEFINED_BOOL
++#endif /* COIN_DEFINED_BOOL */
++#ifdef COIN_DEFINED_INT32
++#undef INT32
++#undef COIN_DEFINED_INT32
++#endif /* COIN_DEFINED_INT32 */
++#endif // __COIN_SOXT__
++#ifdef __COIN_SOGTK__
++#include <gtk/gtk.h>
++#endif // __COIN_SOGTK__
++
++// *************************************************************************
++
++enum GLModes {
++  SO_GL_RGB      = 0x01, SO_GLX_RGB      = SO_GL_RGB,
++  SO_GL_DOUBLE   = 0x02, SO_GLX_DOUBLE   = SO_GL_DOUBLE,
++  SO_GL_ZBUFFER  = 0x04, SO_GLX_ZBUFFER  = SO_GL_ZBUFFER,
++  SO_GL_OVERLAY  = 0x08, SO_GLX_OVERLAY  = SO_GL_OVERLAY,
++  SO_GL_STEREO   = 0x10, SO_GLX_STEREO   = SO_GL_STEREO
++};
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@GLWidget : public So at Gui@Component {
++  SO at GUI@_OBJECT_ABSTRACT_HEADER(So at Gui@GLWidget, So at Gui@Component);
++
++public:
++
++  void setBorder(const SbBool enable);
++  SbBool isBorder(void) const;
++
++  virtual void setDoubleBuffer(const SbBool enable);
++  SbBool isDoubleBuffer(void) const;
++
++  void setDrawToFrontBufferEnable(const SbBool enable);
++  SbBool isDrawToFrontBufferEnable(void) const;
++  
++  void setQuadBufferStereo(const SbBool enable);
++  SbBool isQuadBufferStereo(void) const;
++
++  void setAccumulationBuffer(const SbBool enable);
++  SbBool getAccumulationBuffer(void) const;
++
++  void setStencilBuffer(const SbBool enable);
++  SbBool getStencilBuffer(void) const;
++
++  void setAlphaChannel(const SbBool enable);
++  SbBool getAlphaChannel(void) const;
++
++  void setOverlayRender(const SbBool onoff);
++  SbBool isOverlayRender(void) const;
++
++  void setSampleBuffers(const int numsamples);
++  int getSampleBuffers(void) const;
++
++  void setStealFocus(SbBool enable);
++  SbBool isStealFocus(void) const;
++
++  @WIDGET@ getGLWidget(void) const;
++  @WIDGET@ getNormalWidget(void) const;
++  @WIDGET@ getOverlayWidget(void) const;
++
++  SbBool hasOverlayGLArea(void) const;
++  SbBool hasNormalGLArea(void) const;
++
++  unsigned long getOverlayTransparentPixel(void);
++
++  // OpenGL query functions.
++  void getPointSizeLimits(SbVec2f & range, float & granularity);
++  void getLineWidthLimits(SbVec2f & range, float & granularity);
++
++protected:
++  So at Gui@GLWidget(@WIDGET@ const parent = NULL,
++                  const char * const name = NULL,
++                  const SbBool embed = TRUE,
++                  const int glmodes = SO_GL_RGB,
++                  const SbBool build = TRUE);
++  ~So at Gui@GLWidget();
++
++  virtual void processEvent(@EVENT@ event);
++
++  @WIDGET@ buildWidget(@WIDGET@ parent);
++
++  virtual void redraw(void) = 0;
++  virtual void redrawOverlay(void);
++
++  virtual void initGraphic(void);
++  virtual void initOverlayGraphic(void);
++
++  virtual void sizeChanged(const SbVec2s & size);
++  virtual void widgetChanged(@WIDGET@ w);
++
++  void setGLSize(const SbVec2s size);
++  SbVec2s getGLSize(void) const;
++  float getGLAspectRatio(void) const;
++
++  // old aliases
++  void setGlxSize(const SbVec2s size) { this->setGLSize(size); }
++  SbVec2s getGlxSize(void) const { return this->getGLSize(); }
++  float getGlxAspectRatio(void) const { return this->getGLAspectRatio(); }
++
++  void setStereoBuffer(SbBool flag);
++  SbBool isStereoBuffer(void) const;
++
++  SbBool isRGBMode(void);
++
++  SbBool waitForExpose;
++  SbBool drawToFrontBuffer;
++
++  void glLockNormal(void);
++  void glUnlockNormal(void);
++
++  void glLockOverlay(void);
++  void glUnlockOverlay(void);
++
++  void glSwapBuffers(void);
++  void glFlushBuffer(void);
++
++  virtual SbBool glScheduleRedraw(void);
++
++private:
++  class So at Gui@GLWidgetP * pimpl;
++  friend class SoGuiGLWidgetP;
++  friend class So at Gui@GLWidgetP;
++
++  // FIXME: get rid of toolkit-specific stuff below. 20020613 mortene.
++
++#ifdef __COIN_SOXT__
++public:
++  GLXContext getNormalContext(void);
++  GLXContext getOverlayContext(void);
++
++  Window getNormalWindow(void);
++  Window getOverlayWindow(void);
++
++  int getOverlayColorMapSize(void);
++  int getColorMapSize(void);
++
++  virtual void setNormalVisual(XVisualInfo * visual);
++  XVisualInfo * getNormalVisual(void);
++  virtual void setOverlayVisual(XVisualInfo * visual);
++  XVisualInfo * getOverlayVisual(void);
++
++protected:
++  static void eventHandler(Widget, SoXtGLWidget *, XAnyEvent *, Boolean *);
++
++  int getDisplayListShareGroup(GLXContext context);
++  Widget getGlxMgrWidget(void);
++#endif // __COIN_SOXT__
++
++#ifdef __COIN_SOGTK__
++protected:
++  virtual SbBool eventFilter(GtkWidget * object, GdkEvent * event);
++#endif // __COIN_SOGTK__
++
++};
++
++// *************************************************************************
++
++#endif // ! SO at GUI@_GLWIDGET_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiGLWidgetCommon.cpp.in
+@@ -0,0 +1,691 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#define PRIVATE(obj) ((SoGuiGLWidgetP *)(obj->pimpl))
++
++// *************************************************************************
++
++/*!
++  \class So at Gui@GLWidget So at Gui@GLWidget.h Inventor/@Gui@/So at Gui@GLWidget.h
++  \brief The So at Gui@GLWidget class manages OpenGL contexts.
++  \ingroup components
++
++  This is the basic, abstract component class which sets up an OpenGL
++  canvas for its subclasses.
++
++  Application programmers will normally not use this class directly,
++  but rather through the interface of either its direct descendent;
++  So at Gui@RenderArea, or through one of the "rapid application
++  development"-style viewer subclasses.
++
++  \if SOQT_DOC
++
++  An important thing to know about embedding So at Gui@GLWidget derived
++  components into other @Gui@ widgets is that you need to set up
++  "focus proxying" to have events still be sent to the OpenGL canvas
++  widget. This is true for both the So at Gui@RenderArea aswell as all
++  the viewer components (like So at Gui@ExaminerViewer,
++  So at Gui@PlaneViewer etc).
++
++  As an example, if you embed an So at Gui@ExaminerViewer inside a QFrame
++  like this:
++
++  \code
++  QMainWindow * toplevel = new QMainWindow;
++  QFrame * frame = new QFrame(toplevel);
++  So at Gui@ExaminerViewer * viewer = new So at Gui@ExaminerViewer(toplevel);
++  \endcode
++
++  ...events from the keyboard will not always automatically be
++  forwarded to the viewer OpenGL canvas. This is the code you need to
++  add in this case:
++
++  \code
++  toplevel->setFocusProxy(viewer->getWidget());
++  \endcode
++
++  \endif
++
++  \if SOWIN_DOC
++
++  For debugging purposes, SoWinGLWidget provides the
++  OIV_FORCE_PIXEL_FORMAT environment variable to make it possible to
++  override the pixel format chosen by the internal attribute match
++  algorithm.
++
++  \endif
++*/
++
++// *************************************************************************
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/@Gui@/common/gl.h>
++#include <Inventor/@Gui@/So at Gui@GLWidget.h>
++#include <Inventor/@Gui@/So at Gui@GLWidgetP.h>
++
++// *************************************************************************
++
++// All shared documentation for functions with specific
++// implementations in the individual toolkits.
++
++/*!
++  \fn So at Gui@GLWidget::So at Gui@GLWidget(@WIDGET@ const parent, const char * const name, const SbBool embed, const int glmodes, const SbBool build)
++
++  The constructor is protected, as this is an abstract class to only
++  be used by it's subclasses.
++*/
++
++/*!
++  \fn So at Gui@GLWidget::~So at Gui@GLWidget()
++
++  Clean up all use of internal resources.
++
++  The destructor is protected, as this is an abstract class to only be
++  used by it's subclasses.
++*/
++
++/*!
++  \fn void So at Gui@GLWidget::setBorder(const SbBool enable)
++
++  Specify whether or not there should be a border framing the OpenGL
++  canvas. The border will be 2 pixels wide.
++
++  The default is to display the OpenGL canvas with no border.
++
++  \sa isBorder()
++*/
++
++/*!
++  \fn SbBool So at Gui@GLWidget::isBorder(void) const
++
++  Returns whether or not there's a border framing the OpenGL canvas.
++
++  \sa setBorder()
++*/
++
++/*!
++  \fn void So at Gui@GLWidget::setOverlayRender(const SbBool onoff)
++
++  Turn on or off the use of overlay planes.
++
++  \sa isOverlayRender()
++*/
++
++/*!
++  \fn SbBool So at Gui@GLWidget::isOverlayRender(void) const
++
++  Returns a flag indicating whether or not overplay planes are
++  currently used.
++
++  \sa setOverlayRender()
++*/
++
++/*!
++  \fn void So at Gui@GLWidget::setDoubleBuffer(const SbBool enable)
++
++  Switch between single and double buffer mode for the OpenGL canvas.
++  The default is to use a single buffer canvas.
++
++  \sa isDoubleBuffer()
++*/
++
++/*!
++  \fn SbBool So at Gui@GLWidget::isDoubleBuffer(void) const
++
++  Returns the status of the buffer mode.
++
++  \sa setDoubleBuffer()
++*/
++
++/*!
++  \fn void So at Gui@GLWidget::setQuadBufferStereo(const SbBool enable)
++
++  Enables or disables OpenGL quad buffer stereo.
++*/
++
++/*!
++  \fn SbBool So at Gui@GLWidget::isQuadBufferStereo(void) const
++
++  Returns \c TRUE if quad buffer stereo is enabled for this widget.
++*/
++
++/*!
++  \fn void So at Gui@GLWidget::setAccumulationBuffer(const SbBool enable)
++
++  Enables/disables the OpenGL accumulation buffer.
++
++  For general information about accumulation buffers, confer with your
++  OpenGL reference documentation.
++
++  By default, the accumulation buffer will be attempted disabled.
++  Whether or not it will \e actually be disabled depends on what
++  OpenGL contexts are available on the system. It is perfectly
++  possible that the only usable contexts with regard to the other
++  settings (like double buffering and RGBA mode versus color index
++  mode) causes the context selection to choose an OpenGL format that
++  contains an accumulation buffer, even though it was not
++  requested.
++
++  Vice versa, one is not guaranteed to get accumulation buffers even
++  when requested through this function, either because they are not
++  available, or because they are only available in combination with
++  other OpenGL context settings that are not wanted (like single
++  buffers, non-accellerated rendering, etc).
++
++  If you try to enable accumulation buffers by using this function,
++  you should therefore in succession use the
++  So at Gui@GLWidget::getAccumulationBuffer() to query whether or not an
++  accumulation buffer could actually be set up.
++
++  \sa So at Gui@RenderArea::setAntiAliasing()
++*/
++
++/*!
++  \fn SbBool So at Gui@GLWidget::getAccumulationBuffer(void) const
++
++  Returns whether the OpenGL accumulation buffer is enabled.
++
++  The returned flag will indicate whether or not accumulation buffers
++  are \e actually present, and not just parrot the input value to
++  So at Gui@GLWidget::setAccumulationBuffer(). See documentation of that
++  function for more information.
++*/
++
++/*!
++  \fn void So at Gui@GLWidget::setStencilBuffer(const SbBool enable)
++
++  Enables/disables the OpenGL stencil buffer.
++
++  For general information about stencil buffers, confer with your
++  OpenGL reference documentation.
++
++  By default, the stencil buffer will be attempted disabled, but the
++  same notes apply for stencil buffers as for accumulation
++  buffers. For an explanation on the issue of stencil and accumulation
++  buffer availability, see the function documentation of
++  So at Gui@GLWidget::setAccumulationBuffer().
++*/
++
++/*!
++  \fn SbBool So at Gui@GLWidget::getStencilBuffer(void) const
++
++  Returns whether the OpenGL stencil buffer is enabled.
++
++  The returned flag will indicate whether or not stencil buffers are
++  \e actually present, in the same manner as for
++  So at Gui@GLWidget::getAccumulationBuffer(). See documentation of
++  So at Gui@GLWidget::setStencilBuffer().
++*/
++
++/*!
++  \fn void So at Gui@GLWidget::setAlphaChannel(const SbBool enable)
++
++  Enables/disables the alpha channel for the OpenGL context.
++*/
++
++/*!
++  \fn SbBool So at Gui@GLWidget::getAlphaChannel(void) const
++
++  Returns whether the alpha channel is enabled for the OpenGL context.
++*/
++
++/*!
++  \fn void So at Gui@GLWidget::setDrawToFrontBufferEnable(const SbBool enable)
++
++  If this is set to \c TRUE, rendering will happen in the front buffer
++  even if the current rendering mode is double buffered.
++*/
++
++/*!
++  \fn SbBool So at Gui@GLWidget::isDrawToFrontBufferEnable(void) const
++  \sa setDrawToFrontBufferEnable()
++*/
++
++/*!
++  \fn @WIDGET@ So at Gui@GLWidget::buildWidget(@WIDGET@ parent)
++
++  This method builds the component contents in the given \a parent
++  widget. For subclasses adding new user interface items, this method
++  is typically overridden in the following manner:
++
++  \code
++  @WIDGET@ MyOwnViewer::buildWidget(@WIDGET@ parent)
++  {
++     @WIDGET@ superw = <superclass>::buildWidget(parent);
++     // [then move superw within MyOwnViewer framework and add own
++     // user interface components]
++  }
++  \endcode
++*/
++
++/*!
++  \fn virtual void So at Gui@GLWidget::redraw(void)
++
++  This method is invoked when the GL buffer needs to be redrawn.
++ */
++
++/*!
++  \var SbBool So at Gui@GLWidget::waitForExpose
++
++  If this is \c TRUE, rendering should not be done yet. Upon the first
++  expose event of a newly created OpenGL widget, this variable will
++  be set to \c FALSE.
++*/
++
++/*!
++  \var SbBool So at Gui@GLWidget::drawToFrontBuffer
++
++  If this is \c TRUE, rendering will happen in the front buffer even
++  if the current rendering mode is double buffered.
++*/
++
++/*!
++  \fn @WIDGET@ So at Gui@GLWidget::getNormalWidget(void) const
++
++  \if SOQT_DOC
++  For SoQt, this returns the same widget pointer as that of
++  SoQtGLWidget::getGLWidget().
++  \endif
++*/
++
++/*!
++  \fn @WIDGET@ So at Gui@GLWidget::getOverlayWidget(void) const
++
++  Returns widget associated with overlay planes, or \c NULL if no
++  overlay planes are available.
++
++  \if SOQT_DOC
++  For the Qt toolkit, overlay planes is a feature of the QGLWidget,
++  and not seen at a separate widget entity. So this call will just
++  return the same widget reference as the SoQt::getGLWidget() call (if
++  overlay planes are supported).
++  \endif
++*/
++
++/*!
++  \fn void So at Gui@GLWidget::setGLSize(const SbVec2s size)
++  Sets the size of the GL canvas.
++*/
++
++/*!
++  \fn SbVec2s So at Gui@GLWidget::getGLSize(void) const
++
++  Return the dimensions of the OpenGL canvas.
++*/
++
++/*!
++  \fn float So at Gui@GLWidget::getGLAspectRatio(void) const
++
++  Return the aspect ratio of the OpenGL canvas.
++*/
++
++/*!
++  \fn void So at Gui@GLWidget::setGlxSize(const SbVec2s size)
++  This function has been renamed to the more appropriate setGLSize.
++  \sa setGLSize
++*/
++
++/*!
++  \fn SbVec2s So at Gui@GLWidget::getGlxSize(void) const
++  This function has been renamed to the more appropriate getGLSize.
++  \sa getGLSize
++*/
++
++/*!
++  \fn float So at Gui@GLWidget::getGlxAspectRatio(void) const
++  This function has been renamed to the more appropriate getGLAspectRatio.
++  \sa getGLAspectRatio
++*/
++
++/*!
++  \fn @WIDGET@ So at Gui@GLWidget::getGLWidget(void) const
++
++  Returns a pointer to the toolkit-native GL widget.
++*/
++
++/*!
++  \fn void So at Gui@GLWidget::widgetChanged(@WIDGET@ w)
++
++  This is the method which gets called whenever we change which OpenGL
++  widget is used.
++
++  Should be overridden in subclasses which directly or indirectly
++  store the return value from the So at Gui@GLWidget::getGLWidget()
++  method.
++
++  \sa sizeChanged()
++*/
++
++/*!
++  \fn void So at Gui@GLWidget::processEvent(@EVENT@ anyevent)
++
++  Any events from the native window system that goes to the OpenGL
++  canvas gets piped through this method.
++
++  It is overridden in the subclasses to catch user interaction with
++  the render canvas in the viewers, aswell as forwarding relevant
++  events to the scenegraph.
++*/
++
++/*!
++  \fn void So at Gui@GLWidget::glLockNormal(void)
++
++  This method calls make-current on the correct context and ups the
++  lock level.
++*/
++
++/*!
++  \fn void So at Gui@GLWidget::glUnlockNormal(void)
++
++  This method drops the lock level.
++*/
++
++/*!
++  \fn void So at Gui@GLWidget::glSwapBuffers(void)
++  Swap back buffer to front and vice versa.
++*/
++
++/*!
++  \fn void So at Gui@GLWidget::glFlushBuffer(void)
++
++  Flush the current GL buffer. Simply calls glFlush().
++*/
++
++/*!
++  \fn void So at Gui@GLWidget::glLockOverlay(void)
++
++  This method calls make-current on the correct context and ups the
++  lock level.
++*/
++
++/*!
++  \fn void So at Gui@GLWidget::glUnlockOverlay(void)
++
++  This method drops the lock level.
++*/
++
++/*!
++  \fn unsigned long So at Gui@GLWidget::getOverlayTransparentPixel(void)
++  Returns the overlay transparent pixel.
++*/
++
++/*!
++  \fn SbBool So at Gui@GLWidget::isRGBMode(void)
++
++  Returns \c TRUE if the normal GL context is in RGBA mode.
++  Return \c FALSE if color index mode is used.
++*/
++
++/*!
++  \fn void So at Gui@GLWidget::redrawOverlay(void)
++
++  Renders the overlay scene graph. Default method is empty. Subclasses
++  should override this method.
++*/
++
++/*!
++  \fn SbBool So at Gui@GLWidget::hasNormalGLArea(void) const 
++
++  Will return \c TRUE if a normal GL drawing area exists.
++*/
++
++/*!
++  \fn SbBool So at Gui@GLWidget::hasOverlayGLArea(void) const 
++
++  Will return \c TRUE if an overlay GL drawing area exists.
++*/
++
++/*!
++  \fn void So at Gui@GLWidget::initGraphic(void)
++
++  Will be called when GL widget should initialize graphic, after
++  the widget has been created. Default method enabled GL_DEPTH_TEST.
++*/
++
++/*!
++  \fn void So at Gui@GLWidget::initOverlayGraphic(void)
++
++  Will be called after the overlay widget has been created, and subclasses
++  should override this to initialize overlay stuff.
++
++  Default method does nothing.
++*/
++
++/*!
++  \fn SbBool So at Gui@GLWidget::glScheduleRedraw(void)
++
++  Will be called whenever scene graph needs to be redrawn.  If this
++  method return \c FALSE, redraw() will be called immediately.
++
++  Default method simply returns \c FALSE. Override this method to
++  schedule a redraw and return \c TRUE if you're trying to do The
++  Right Thing.
++*/
++
++/*!
++  \fn void So at Gui@GLWidget::setStealFocus(SbBool enable)
++
++  Sets whether the GL widget should steal keyboard focus when the
++  mouse is over the GL view.
++
++  Default is \c TRUE.
++
++  \sa isStealFocus
++  \since So at Gui@ 1.3.0
++*/
++
++/*!
++  \fn SbBool So at Gui@GLWidget::isStealFocus(void) const
++
++  Returns whether focus stealing policy is on (\c TRUE) or off (\c
++  FALSE).
++
++  Default is \c TRUE.
++
++  \sa setStealFocus
++  \since So at Gui@ 1.3.0
++*/
++
++
++/*! 
++  \fn void So at Gui@GLWidget::setSampleBuffers(const int numsamples)
++  
++  Set the number of samples use when enabling multisample buffer contexts.
++  Multisampling will be enabled when numsamples > 1.
++  
++*/
++
++/*! 
++  \fn int So at Gui@GLWidget::getSampleBuffers(void) const
++  
++  Returns the number of samples used for multisampling. Returns 1 if
++  multisampling is disabled.
++*/
++
++// Documented in common/SoGuiGLWidgetCommon.cpp.in.
++void
++So at Gui@GLWidget::setStealFocus(SbBool enable)
++{
++  PRIVATE(this)->stealFocus = enable;
++}
++
++// Documented in common/SoGuiGLWidgetCommon.cpp.in.
++SbBool
++So at Gui@GLWidget::isStealFocus(void) const
++{
++  return PRIVATE(this)->stealFocus;
++}
++
++// *************************************************************************
++
++/*!
++  This function is provided as a convenience for the application
++  programmer to help with acquiring the OpenGL implementation limits
++  for rendering points.
++
++  For robust application code, one needs to consider the range limits
++  when setting the SoDrawStyle::pointSize field.
++*/
++void
++So at Gui@GLWidget::getPointSizeLimits(SbVec2f & range, float & granularity)
++{
++  this->glLockNormal();
++
++  GLfloat vals[2];
++  glGetFloatv(GL_POINT_SIZE_RANGE, vals);
++
++  // Matthias Koenig reported on coin-discuss that the OpenGL
++  // implementation on SGI Onyx 2 InfiniteReality returns 0 for the
++  // lowest pointsize, but it will still set the return value of
++  // glGetError() to GL_INVALID_VALUE if this size is attempted
++  // used. So the boundary range fix in the next line of code is a
++  // workaround for that OpenGL implementation bug.
++  //
++  // 0.0f and lower values are explicitly disallowed, according to
++  // the OpenGL 1.3 specification, Chapter 3.3.
++
++  if (vals[0] <= 0.0f) { vals[0] = So at Gui@Min(1.0f, vals[1]); }
++
++  range.setValue(vals[0], vals[1]);
++
++  GLfloat gran[1];
++  glGetFloatv(GL_POINT_SIZE_GRANULARITY, gran);
++  granularity = gran[0];
++
++  this->glUnlockNormal();
++}
++
++/*!
++  This function is provided as a convenience for the application
++  programmer to help with acquiring the OpenGL implementation limits
++  for rendering lines.
++
++  For robust application code, one needs to consider the range limits
++  when setting the SoDrawStyle::lineWidth field.
++*/
++void
++So at Gui@GLWidget::getLineWidthLimits(SbVec2f & range, float & granularity)
++{
++  this->glLockNormal();
++
++  GLfloat vals[2];
++  glGetFloatv(GL_LINE_WIDTH_RANGE, vals);
++
++  // Matthias Koenig reported on coin-discuss that the OpenGL
++  // implementation on SGI Onyx 2 InfiniteReality returns 0 for the
++  // lowest linewidth, but it will still set the return value of
++  // glGetError() to GL_INVALID_VALUE if this size is attempted
++  // used. This is a workaround for what looks like an OpenGL bug.
++
++  if (vals[0] <= 0.0f) { vals[0] = So at Gui@Min(1.0f, vals[1]); }
++
++  range.setValue(vals[0], vals[1]);
++
++  GLfloat gran[1];
++  glGetFloatv(GL_LINE_WIDTH_GRANULARITY, gran);
++  granularity = gran[0];
++
++  this->glUnlockNormal();
++}
++
++// FIXME: other implementation specifics to check are
++//
++//  * maximum stack depths (attribute, modelview matrix, name,
++//    projection matrix, texture matrix)
++//
++//  * max display list nesting
++//
++//  * max nr of clipplanes
++//
++//  * max nr of light sources
++//
++//  * max 3D texture size (needs specific extension?)
++//
++// 20020802 mortene.
++
++/*!
++  Sets whether OpenGL stereo buffers (quad buffer stereo) should be
++  used.
++*/
++void
++So at Gui@GLWidget::setStereoBuffer(SbBool flag)
++{
++  // FIXME: is this really correct? 20011012 mortene.
++  this->setQuadBufferStereo(flag);
++}
++
++/*!
++  Returns whether OpenGL stereo buffers are being used.
++*/
++SbBool
++So at Gui@GLWidget::isStereoBuffer(void) const
++{
++  // FIXME: is this really correct? 20011012 mortene.
++  return this->isQuadBufferStereo();
++}
++
++// *************************************************************************
++
++#ifndef DOXYGEN_SKIP_THIS
++
++// Remaining code is for the SoGuiGLWidgetP "private implementation"
++// class.
++
++
++SoGuiGLWidgetP::SoGuiGLWidgetP(So at Gui@GLWidget * publ)
++{
++  this->pub = publ;
++  this->stealFocus = TRUE;
++}
++
++SoGuiGLWidgetP::~SoGuiGLWidgetP()
++{
++}
++
++// Just forward from a static function, so we can find out from
++// anywhere within the library -- without exposing the API for the app
++// programmer.
++SbBool
++SoGuiGLWidgetP::isDirectRendering(So at Gui@GLWidget * w)
++{
++  return ((SoGuiGLWidgetP *)(w->pimpl))->isDirectRendering();
++}
++
++#undef PRIVATE
++#endif // DOXYGEN_SKIP_THIS
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiGLWidgetP.h.in
+@@ -0,0 +1,68 @@
++#ifndef SOGUIGLWIDGETP_H
++#define SOGUIGLWIDGETP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/SbBasic.h>
++
++class So at Gui@GLWidget;
++
++// ************************************************************************
++
++// This class contains private data and methods used within the
++// SoGuiGLWidget class.
++
++class SoGuiGLWidgetP
++{
++public:
++  virtual ~SoGuiGLWidgetP();
++
++  static SbBool isDirectRendering(class So at Gui@GLWidget * w);
++  SbBool stealFocus;
++
++protected:
++  SoGuiGLWidgetP(So at Gui@GLWidget * publ);
++  So at Gui@GLWidget * pub;
++
++  virtual SbBool isDirectRendering(void) = 0;
++};
++
++// ************************************************************************
++
++#endif // !SOGUIGLWIDGETP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiMaterialEditor.h.in
+@@ -0,0 +1,39 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// This include file just forwards to the one under the editors/
++// directory. Done to be compatible with old SGI InventorXt code and
++// TGS SoWin and SoQt code.
++
++#include <Inventor/@Gui@/editors/So at Gui@MaterialEditor.h>
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiMaterialList.h.in
+@@ -0,0 +1,110 @@
++#ifndef SO at GUI@_MATERIALLIST_H
++#define SO at GUI@_MATERIALLIST_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/So at Gui@Component.h>
++
++class SoMaterial;
++class SoAnyMaterialList;
++
++typedef void So at Gui@MaterialListCB(void * closure, const SoMaterial * material);
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@MaterialList : public So at Gui@Component {
++  SO at GUI@_OBJECT_HEADER(So at Gui@MaterialList, So at Gui@Component);
++
++public:
++  So at Gui@MaterialList(
++    @WIDGET@ parent = NULL,
++    const char * const name = NULL,
++    SbBool embed = TRUE,
++    const char * const dir = NULL);
++  ~So at Gui@MaterialList(void);
++
++  void addCallback(
++    So at Gui@MaterialListCB * const callback,
++    void * const closure = NULL);
++  void removeCallback(
++    So at Gui@MaterialListCB * const callback,
++    void * const closure = NULL);
++
++protected:
++  So at Gui@MaterialList(
++    @WIDGET@ parent,
++    const char * const name,
++    SbBool embed,
++    const char * const dir,
++    SbBool build);
++
++  virtual const char * getDefaultWidgetName(void) const;
++  virtual const char * getDefaultTitle(void) const;
++  virtual const char * getDefaultIconTitle(void) const;
++
++  @WIDGET@ buildWidget(@WIDGET@ parent);
++  @WIDGET@ buildPulldownMenu(@WIDGET@ parent);
++
++private:
++  void constructor(const char * const dir, const SbBool build);
++
++  // FIXME: remove all this and set it up for use with a
++  // SoGuiMaterialListP class. 2001???? larsa.
++
++  void selectionCallback(int i);
++  static void selection_cb(@WIDGET@, void *, void *);
++
++  void paletteMenuCallback(@WIDGET@);
++  static void palette_menu_cb(@WIDGET@, void *, void *);
++
++
++#ifdef __COIN_SOGTK__
++  void menuactivation(GtkWidget * menuitem);
++  static void menuactivationCB(GtkObject * obj, gpointer closure);
++
++  void itemactivation(int item);
++  static void itemactivationCB(GtkObject * obj, gint row, gint column,
++                               GdkEvent * event, gpointer closure);
++#endif // __COIN_SOGTK__
++
++  @WIDGET@ listwidget;
++
++  SoAnyMaterialList * common;
++
++}; // public So at Gui@MaterialList
++
++// *************************************************************************
++
++#endif // ! SO at GUI@_MATERIALLIST_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiObject.cpp.in
+@@ -0,0 +1,166 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// Pulls in __COIN_SO at GUI@__ define used below.
++#include <Inventor/@Gui@/So at Gui@Basic.h>
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <so at gui@defs.h>
++#include <Inventor/@Gui@/So at Gui@Object.h>
++#include <Inventor/@Gui@/devices/So at Gui@Device.h>
++#include <Inventor/@Gui@/So at Gui@Component.h>
++
++/*!
++  \class So at Gui@Object Inventor/@Gui@/So at Gui@Object.h
++  \brief The So at Gui@Object class is the common superclass for all So at Gui@ component classes.
++  \ingroup misc
++
++  The purpose of making this class the superclass of all So at Gui@
++  device, component and viewer classes is to be able to do run-time
++  type checking of the So at Gui@ objects.
++
++
++  You can place the macro SO at GUI@_OBJECT_HEADER(classname,parentname)
++  within a class definition header for So at Gui@ extension components to
++  automatically make the necessary definitions for setting up a
++  run-time type system for your extension classes:
++
++  \code
++  #ifndef MYSPECIALVIEWER_H
++  #define MYSPECIALVIEWER_H
++
++  class MySpecialViewer : public So at Gui@ExaminerViewer {
++    SO at GUI@_OBJECT_HEADER(MySpecialViewer, So at Gui@ExaminerViewer);
++    // [rest of class definition follows]
++  };
++
++  #endif // !MYSPECIALVIEWER_H
++  \endcode
++
++  Then put the SO at GUI@_OBJECT_SOURCE(classname) macro within the
++  actual implementation sourcecode file to include the necessary
++  code for the run-time type system:
++
++  \code
++  #include <MySpecialViewer.h>
++
++  SOQT_OBJECT_SOURCE(MySpecialViewer);
++
++  // [rest of class implementation]
++  \endcode
++
++
++  See also the documentation of the SoType class in Coin or Inventor.
++ */
++
++// *************************************************************************
++
++/*!
++  \fn SoType So at Gui@Object::getTypeId
++
++  Returns the type identification of an object derived from a class
++  inheriting So at Gui@Object.  This is used for run-time type checking
++  and "downward" casting.
++
++  Usage example:
++
++  \code
++  void foo(So at Gui@Viewer * comp)
++  {
++    if (comp->getTypeId() == So at Gui@ExaminerViewer::getClassTypeId()) {
++      // safe downward cast, knows the type
++      So at Gui@ExaminerViewer * exviewer = (So at Gui@ExaminerViewer *)comp;
++      /// [then something] ///
++    }
++    else if (comp->getTypeId().isOfType(So at Gui@FlyViewer::getClassTypeId())) {
++      // safe downward cast, knows the type
++      So at Gui@FlyViewer * flyviewer = (So at Gui@FlyViewer *)comp;
++      // then something else
++    }
++  }
++  \endcode
++*/
++// FIXME: add doc above to explain how external developers can use the
++// type system for their own extension classes. 20020502 mortene.
++
++// This is a private variable.
++SoType So at Gui@Object::classTypeId SO at GUI@_STATIC_SOTYPE_INIT;
++
++/*!
++  Sets up initialization for data common to all instances of this
++  class, submitting necessary information to the internal So at Gui@ type
++  system.
++*/
++void
++So at Gui@Object::initClass(void)
++{
++  assert(So at Gui@Object::classTypeId == SoType::badType());
++  So at Gui@Object::classTypeId =
++    SoType::createType(SoType::badType(), "So at Gui@Object");
++}
++
++/*!
++  Returns \c TRUE if the type of this object is either of the same
++  type or inherited from \a type.
++*/
++SbBool
++So at Gui@Object::isOfType(SoType type) const
++{
++  return this->getTypeId().isDerivedFrom(type);
++}
++
++/*!
++  This static method returns the SoType object associated with
++  objects of this class.
++*/
++SoType
++So at Gui@Object::getClassTypeId(void)
++{
++  return So at Gui@Object::classTypeId;
++}
++
++/*!
++  Initialize the type system of So at Gui@Object, all So at Gui@ device
++  classes and all So at Gui@ components (including viewers).
++*/
++void
++So at Gui@Object::init(void)
++{
++  So at Gui@Object::initClass();
++  So at Gui@Device::initClasses();
++  So at Gui@Component::initClasses();
++}
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiObject.h.in
+@@ -0,0 +1,146 @@
++#ifndef SO at GUI@OBJECT_H
++#define SO at GUI@OBJECT_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <assert.h>
++
++#include <Inventor/SbBasic.h>
++#include <Inventor/SbString.h>
++#include <Inventor/SoType.h>
++
++#include <Inventor/@Gui@/So at Gui@Basic.h>
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@Object {
++  static SoType classTypeId;
++
++public:
++  static void initClass(void);
++  static SoType getClassTypeId(void);
++  virtual SoType getTypeId(void) const = 0;
++  SbBool isOfType(SoType type) const;
++
++  static void init(void);
++
++  // FIXME: gcc-4 generates a warning when a class has virtual functions 
++  // but no virtual destructor. Currently this warning is suppressed using 
++  // the -Wno-non-virtual-dtor option, but this should be addressed for the
++  // next major version... 20060404 kyrah
++
++#if (SO at GUI@_MAJOR_VERSION > 1)
++#error Resolve missing virtual destructor issue for the new major release!
++#endif
++
++}; // So at Gui@Object
++
++// *************************************************************************
++
++// For a discussion about this #define, see Coin's SbBasic.h.
++
++#define SO at GUI@_SUN_CC_4_0_SOTYPE_INIT_BUG 0 /* assume compiler is ok for now */
++
++#if SO at GUI@_SUN_CC_4_0_SOTYPE_INIT_BUG
++#define SO at GUI@_STATIC_SOTYPE_INIT
++#else
++#define SO at GUI@_STATIC_SOTYPE_INIT = SoType::badType()
++#endif
++
++// *************************************************************************
++
++// The getTypeId() method should be abstract for abstract objects, but doing
++// that would cause custom components derived from abstract components to
++// have to include the typed object header / source, which could be a
++// problem if the custom component wasn't written for Coin in the first
++// place.
++
++#define SO at GUI@_OBJECT_ABSTRACT_HEADER(classname, parentname) \
++public: \
++  static void initClass(void); \
++  static SoType getClassTypeId(void); \
++  virtual SoType getTypeId(void) const /* = 0 (see comment above) */; \
++private: \
++  typedef parentname inherited; \
++  static SoType classTypeId
++
++#define SO at GUI@_OBJECT_HEADER(classname, parentname) \
++public: \
++  static void initClass(void); \
++  static SoType getClassTypeId(void); \
++  virtual SoType getTypeId(void) const; \
++  static void * createInstance(void); \
++private: \
++  typedef parentname inherited; \
++  static SoType classTypeId
++
++#define SO at GUI@_OBJECT_ABSTRACT_SOURCE(classname) \
++void classname::initClass(void) { \
++  assert(classname::classTypeId == SoType::badType()); \
++  classname::classTypeId = \
++    SoType::createType(inherited::getClassTypeId(), \
++                        SO__QUOTE(classname)); \
++} \
++SoType classname::getClassTypeId(void) { \
++  return classname::classTypeId; \
++} \
++SoType classname::getTypeId(void) const { \
++  return classname::classTypeId; \
++} \
++SoType classname::classTypeId SO at GUI@_STATIC_SOTYPE_INIT
++
++#define SO at GUI@_OBJECT_SOURCE(classname) \
++void classname::initClass(void) { \
++  assert(classname::classTypeId == SoType::badType()); \
++  classname::classTypeId = \
++    SoType::createType(inherited::getClassTypeId(), \
++                        SO__QUOTE(classname), \
++                        classname::createInstance); \
++} \
++SoType classname::getClassTypeId(void) { \
++  return classname::classTypeId; \
++} \
++SoType classname::getTypeId(void) const { \
++  return classname::classTypeId; \
++} \
++void * classname::createInstance(void) { \
++  assert(classname::classTypeId != SoType::badType()); \
++  return (void *) new classname; \
++} \
++SoType classname::classTypeId SO at GUI@_STATIC_SOTYPE_INIT
++
++// *************************************************************************
++
++#endif // ! SO at GUI@OBJECT_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiP.h.in
+@@ -0,0 +1,69 @@
++#ifndef SOGUIP_H
++#define SOGUIP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++// ************************************************************************
++
++#include <Inventor/C/threads/mutex.h>
++
++// ************************************************************************
++
++// This class contains private data and methods used within the
++// So at Gui@ class.
++
++class SoGuiP
++{
++public:
++  static void commonInit(void);
++  static void commonCleanup(void);
++
++  enum ABIError {
++    LINKTIME_MISMATCH, LINKSTYLE_MISMATCH, RUNTIME_MISMATCH
++  };
++  static void abort(SoGuiP::ABIError error);
++
++  static void sensorQueueChanged(void * cbdata);
++
++  static cc_mutex * gllockmutex;
++};
++
++// ************************************************************************
++
++#endif // ! SOGUIP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiRenderArea.cpp.in
+@@ -0,0 +1,2244 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/**************************************************************************\
++ *
++ *  A WORD OF ADVICE
++ *
++ *  It is fruitless to modify the contents of the So at Gui@RenderArea.cpp file
++ *  because it is autogenerated by configure from the SoGuiRenderArea.cpp.in
++ *  file which you will find in the src/Inventor/@Gui@/common/ directory.
++ *  Do your modifications to that file instead.
++ *
++\**************************************************************************/
++
++// *************************************************************************
++
++/*!
++  \class So at Gui@RenderArea Inventor/@Gui@/So at Gui@RenderArea.h
++  \brief The So at Gui@RenderArea class adds scenegraph handling and event management.
++  \ingroup components viewers
++
++  The So at Gui@RenderArea class is a component that adds scenegraph
++  management and input device event handling to the So at Gui@GLWidget
++  component.
++
++  The class has many convenient methods for controlling aspects of the
++  rendering, like for instance transparency, aliasing and for
++  scheduling of redraws.
++
++  Native toolkit events are caught by So at Gui@RenderArea components,
++  translated to Coin SoEvent instances and passed on to the
++  scenegraph, in case the user is doing interactive operations on for
++  instance Coin geometry draggers.
++
++
++  So at Gui@RenderArea is the first non-abstract component in it's
++  inheritance hierarchy that you can use directly from client
++  application code to set up a scenegraph viewer canvas.
++
++  For an So at Gui@RenderArea component to properly display your
++  scenegraph, it must contain an SoCamera-derived node and at least
++  one SoLight-derived lightsource node.
++
++  Here's a complete, stand-alone example on how to set up an
++  So at Gui@RenderArea with a scenegraph:
++
++  \code
++  #include <Inventor/@Gui@/So at Gui@.h>
++  #include <Inventor/@Gui@/So at Gui@RenderArea.h>
++  
++  #include <Inventor/nodes/SoCube.h>
++  #include <Inventor/nodes/SoRotor.h>
++  #include <Inventor/nodes/SoArray.h>
++  #include <Inventor/nodes/SoDirectionalLight.h>
++  #include <Inventor/nodes/SoPerspectiveCamera.h>
++  #include <Inventor/nodes/SoSeparator.h>
++  
++  // Set up a simple scenegraph, just for demonstration purposes.
++  static SoSeparator *
++  get_scene_graph(void)
++  {
++    SoSeparator * root = new SoSeparator;
++  
++    SoGroup * group = new SoGroup;
++  
++    SoRotor * rotor = new SoRotor;
++    rotor->rotation = SbRotation(SbVec3f(0.2, 0.5, 0.9), M_PI/4.0);
++    group->addChild(rotor);
++  
++    SoCube * cube = new SoCube;
++    group->addChild(cube);
++  
++    SoArray * array = new SoArray;
++    array->origin = SoArray::CENTER;
++    array->addChild(group);
++    array->numElements1 = 2;
++    array->numElements2 = 2;
++    array->separation1 = SbVec3f(4, 0, 0);
++    array->separation2 = SbVec3f(0, 4, 0);
++  
++    root->addChild(array);
++    return root;
++  }
++  
++  int
++  main(int argc, char ** argv)
++  {
++    @WIDGET@ window = So at Gui@::init(argv[0]);
++  
++    SoSeparator * root = new SoSeparator;
++    root->ref();
++  
++    SoPerspectiveCamera * camera;
++    root->addChild(camera = new SoPerspectiveCamera);
++  
++    root->addChild(new SoDirectionalLight);
++  
++    SoSeparator * userroot = get_scene_graph();
++    root->addChild(userroot);
++  
++    So at Gui@RenderArea * renderarea = new So at Gui@RenderArea(window);
++    camera->viewAll(userroot, renderarea->getViewportRegion());
++    renderarea->setSceneGraph(root);
++    renderarea->setBackgroundColor(SbColor(0.0f, 0.2f, 0.3f));
++    if (argc > 1) {
++      renderarea->setTitle(argv[1]);
++      renderarea->setIconTitle(argv[1]);
++    }
++    renderarea->show();
++  
++    So at Gui@::show(window);
++    So at Gui@::mainLoop();
++  
++    delete renderarea;
++    root->unref();
++  
++    return 0;
++  }
++  \endcode
++*/
++
++// *************************************************************************
++
++#include <Inventor/@Gui@/So at Gui@RenderArea.h>
++
++#include <string.h> // strchr()
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#if SOQT_DEBUG // For the "soinfo" debugging backdoor.
++#include <qgl.h>
++#include <qapplication.h>
++#endif // SOQT_DEBUG
++
++#include <Inventor/@Gui@/common/gl.h> // glDrawBuffer()
++
++#include <Inventor/SoSceneManager.h>
++#include <Inventor/actions/SoSearchAction.h>
++#include <Inventor/actions/SoWriteAction.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/events/SoKeyboardEvent.h>
++#include <Inventor/misc/SoBasic.h>
++#include <Inventor/nodekits/SoBaseKit.h>
++#include <Inventor/nodes/SoCamera.h>
++#include <Inventor/nodes/SoSelection.h>
++#include <Inventor/SoOffscreenRenderer.h>
++#include <Inventor/SbColor4f.h>
++
++#include <so at gui@defs.h>
++#include <Inventor/@Gui@/So at Gui@Basic.h>
++#include <Inventor/@Gui@/So at Gui@.h>
++#include <Inventor/@Gui@/devices/So at Gui@Keyboard.h>
++#include <Inventor/@Gui@/devices/So at Gui@Mouse.h>
++#ifdef HAVE_JOYSTICK_LINUX
++#include <Inventor/@Gui@/devices/So at Gui@LinuxJoystick.h>
++#endif // HAVE_JOYSTICK_LINUX
++#ifdef HAVE_SPACENAV_SUPPORT
++#include <Inventor/@Gui@/devices/So at Gui@SpacenavDevice.h>
++#endif // HAVE_SPACENAV_SUPPORT 
++
++#include <Inventor/@Gui@/So at Gui@GLWidgetP.h>
++#include <Inventor/@Gui@/SoAny.h>
++
++#define RENDERAREA_DEBUG_REDRAWS 0
++
++#define PRIVATE(obj) ((obj)->pimpl)
++#define PUBLIC(obj) ((obj)->pub)
++
++// *************************************************************************
++
++SO at GUI@_OBJECT_SOURCE(So at Gui@RenderArea);
++
++// *************************************************************************
++
++#ifndef DOXYGEN_SKIP_THIS
++
++class So at Gui@RenderAreaP {
++public:
++
++  So at Gui@RenderAreaP(class So at Gui@RenderArea * pub);
++  ~So at Gui@RenderAreaP(void);
++
++  SbBool clear;
++  SbBool clearZBuffer;
++  SbBool clearOverlay;
++
++  SoSceneManager * normalManager;
++  SoSceneManager * overlayManager;
++
++  SbColor * normalColormap;
++  int normalColormapSize;
++  int normalColormapStart;
++  SbColor * overlayColormap;
++  int overlayColormapSize;
++  int overlayColormapStart;
++
++  SbPList * devicelist;
++
++  struct {
++    So at Gui@Keyboard * keyboard;
++    So at Gui@Mouse * mouse;
++#ifdef HAVE_SPACENAV_SUPPORT
++    So at Gui@SpacenavDevice * spacenav;
++#endif // HAVE_SPACENAV_SUPPORT
++  } devices;
++
++  SbBool autoRedraw;
++
++  void replaceSoSelectionMonitor(SoSelection * newsel, SoSelection * oldsel) const;
++  SoSelection * normalselection;
++  SoSelection * overlayselection;
++
++  static const int GL_DEFAULT_MODE;
++
++  void constructor(SbBool mouseInput, SbBool keyboardInput, SbBool build);
++  static void renderCB(void * user, SoSceneManager * manager);
++  static void selection_redraw_cb(void * data, SoSelection * sel);
++  void setDevicesWindowSize(const SbVec2s size);
++
++  // OpenGL info-window hack.
++  enum { NONE, OPENGL, INVENTOR, TOOLKIT, DUMPSCENEGRAPH, DUMPCAMERAS, OFFSCREENGRAB };
++  int checkMagicSequences(const char c);
++  void showOpenGLDriverInformation(void);
++  void showInventorInformation(void);
++  void showToolkitInformation(void);
++  void dumpScenegraph(void);
++  void dumpCameras(void);
++  void offScreenGrab(void);
++
++  SbBool invokeAppCB(@EVENT@ event);
++  const SoEvent * getSoEvent(@EVENT@ event);
++
++  So at Gui@RenderAreaEventCB * appeventhandler;
++  void * appeventhandlerdata;
++
++private:
++  So at Gui@RenderArea * pub; // public interface class
++  SbString currentinput; // For the OpenGL info-window hack.
++};
++
++const int So at Gui@RenderAreaP::GL_DEFAULT_MODE = (SO_GL_RGB |
++                                                 SO_GL_ZBUFFER |
++                                                 SO_GL_DOUBLE );
++
++#if SO at GUI@_DEBUG && defined(__COIN__)
++// Disabled when compiling against SGI / TGS Inventor, as we're using
++// our Coin-specific extension SbString::sprintf() a lot.
++#define DEBUGGING_EGGS 1
++#endif // SO at GUI@_DEBUG && __COIN__
++
++// Note: assumes a valid current OpenGL context.
++void
++So at Gui@RenderAreaP::showOpenGLDriverInformation(void)
++{
++#if DEBUGGING_EGGS
++  const GLubyte * vendor = glGetString(GL_VENDOR);
++  const GLubyte * renderer = glGetString(GL_RENDERER);
++  const GLubyte * version = glGetString(GL_VERSION);
++  const GLubyte * extensions = glGetString(GL_EXTENSIONS);
++
++  SbString info = "GL_VENDOR: \""; info += (const char *)vendor; info += "\"\n";
++  info += "GL_RENDERER: \""; info += (const char *)renderer; info += "\"\n";
++  info += "GL_VERSION: \""; info += (const char *)version; info += "\"\n";
++  info += "GL_EXTENSIONS: \"\n   ";
++    
++  SbString exts = (const char *)extensions;
++  const char * p;
++  int count = 0;
++  // (the extra parentheses in the while-expression kills a gcc warning)
++  while ((p = strchr(exts.getString(), ' '))) {
++    const char * start = exts.getString();
++    info += exts.getSubString(0, p - start);
++    exts.deleteSubString(0, p - start);
++    count++;
++    if (count == 4) { // number of extensions listed on each line
++      info += "\n   ";
++      count = 0;
++    }
++  }
++  if (exts.getLength() > 0) { info += "\n   "; info += exts; }
++  info += "\"\n";
++
++  // FIXME: should also show available GLX / WGL / AGL
++  // extensions. 20020802 mortene.
++
++  // Misc implementation info
++  {
++    SbVec2f range;
++    float granularity;
++    PUBLIC(this)->getPointSizeLimits(range, granularity);
++
++    SbString s;
++    s.sprintf("glPointSize(): range=[%f, %f], granularity=%f\n",
++              range[0], range[1], granularity);
++    info += s;
++
++
++    PUBLIC(this)->getLineWidthLimits(range, granularity);
++
++    s.sprintf("glLineWidth(): range=[%f, %f], granularity=%f\n",
++              range[0], range[1], granularity);
++    info += s;
++
++    GLint depthbits[1];
++    glGetIntegerv(GL_DEPTH_BITS, depthbits);
++    s.sprintf("GL_DEPTH_BITS==%d\n", depthbits[0]);
++    info += s;
++
++    GLint colbits[4];
++    glGetIntegerv(GL_RED_BITS, &colbits[0]);
++    glGetIntegerv(GL_GREEN_BITS, &colbits[1]);
++    glGetIntegerv(GL_BLUE_BITS, &colbits[2]);
++    glGetIntegerv(GL_ALPHA_BITS, &colbits[3]);
++    s.sprintf("GL_[RED|GREEN|BLUE|ALPHA]_BITS==[%d, %d, %d, %d]\n",
++              colbits[0], colbits[1], colbits[2], colbits[3]);
++    info += s;
++
++    GLint accumbits[4];
++    glGetIntegerv(GL_ACCUM_RED_BITS, &accumbits[0]);
++    glGetIntegerv(GL_ACCUM_GREEN_BITS, &accumbits[1]);
++    glGetIntegerv(GL_ACCUM_BLUE_BITS, &accumbits[2]);
++    glGetIntegerv(GL_ACCUM_ALPHA_BITS, &accumbits[3]);
++    s.sprintf("GL_ACCUM_[RED|GREEN|BLUE|ALPHA]_BITS==[%d, %d, %d, %d]\n",
++              accumbits[0], accumbits[1], accumbits[2], accumbits[3]);
++    info += s;
++
++    GLint stencilbits;
++    glGetIntegerv(GL_STENCIL_BITS, &stencilbits);
++    s.sprintf("GL_STENCIL_BITS==%d\n", stencilbits);
++    info += s;
++
++    GLint maxdims[2];
++    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, maxdims);
++    s.sprintf("GL_MAX_VIEWPORT_DIMS==<%d, %d>\n", maxdims[0], maxdims[1]);
++    info += s;
++
++    GLint texdim;
++    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texdim);
++    s.sprintf("GL_MAX_TEXTURE_SIZE==%d\n", texdim);
++    info += s;
++
++    GLint maxlights;
++    glGetIntegerv(GL_MAX_LIGHTS, &maxlights);
++    s.sprintf("GL_MAX_LIGHTS==%d\n", maxlights);
++    info += s;
++
++    GLint maxplanes;
++    glGetIntegerv(GL_MAX_CLIP_PLANES, &maxplanes);
++    s.sprintf("GL_MAX_CLIP_PLANES==%d\n", maxplanes);
++    info += s;
++
++    // FIXME: other implementation specifics to print are
++    //
++    //  * maximum stack depths (attribute, modelview matrix, name,
++    //    projection matrix, texture matrix)
++    //
++    //  * max display list nesting
++    //
++    //  * max 3D texture size (needs specific extension?)
++    //
++    // 20020802 mortene.
++  }
++
++  SbString s;
++  s.sprintf("\n"
++            "Rendering is %sdirect.\n",
++            SoGuiGLWidgetP::isDirectRendering(PUBLIC(this)) ? "" : "in");
++  info += s;
++
++  So at Gui@::createSimpleErrorDialog(NULL, "OpenGL driver information",
++                                    info.getString());
++#endif // DEBUGGING_EGGS
++}
++
++void
++So at Gui@RenderAreaP::showInventorInformation(void)
++{
++#if DEBUGGING_EGGS
++  SbString info;
++  info.sprintf("%s\n", SoDB::getVersion());
++
++  // Display calculated maximum resolution of SbTime::getTimeOfDay().
++  {
++    const double DURATION = 0.2;  // in seconds
++    SbTime current = SbTime::getTimeOfDay();
++    SbTime end(current + DURATION);
++    SbTime last = current;
++    unsigned int ticks = 0;
++    do {
++      current = SbTime::getTimeOfDay();
++      if (current.getValue() != last.getValue()) { ticks++; last = current; }
++    } while (current < end);
++    SbString s;
++    s.sprintf("\nSbTime::getTimeOfDay() resolution: ~ %d Hz\n",
++              (int)(((double)ticks) / DURATION));
++    info += s;
++  }
++
++  // FIXME: dump list of available node classes? 20010927 mortene.
++  So at Gui@::createSimpleErrorDialog(NULL, "Inventor implementation info",
++                                    info.getString());
++
++#endif // DEBUGGING_EGGS
++}
++
++void
++So at Gui@RenderAreaP::showToolkitInformation(void)
++{
++#if DEBUGGING_EGGS
++  SbString info = "So at Gui@ version "; info += SO at GUI@_VERSION; info += "\n";
++#if SO at GUI@_MAKE_DLL
++  info += "Built as MSWindows DLL.\n";
++#endif // !SO at GUI@_MAKE_DLL
++
++  // FIXME: include information about the underlying toolkit library,
++  // if possible, like we do for Qt below (ie Gtk version, Motif
++  // implementation, MSWindows version, ...).  20010927 mortene.
++
++#ifdef SOQT_INTERNAL
++  // Qt implementation info.
++  {
++    SbString s;
++    s.sprintf("\nQt version: %s\n", qVersion());
++    info += s;
++  }
++#endif // SOQT_INTERNAL
++
++  // FIXME: information about DLL path(s) (both for the So at Gui@ and
++  // Coin/Inventor library) would be _extremely_ useful for debugging
++  // "remote" applications, as application programmers (including
++  // ourselves) tend to spread those files around misc diskdrive
++  // directories -- especially on MSWindows platforms.  Mismatches for
++  // run-time binding and link-time binding then causes bugs which are
++  // impossible to make sense of.
++  //
++  // I don't know if any platforms have enough introspection
++  // functionality to enable us to do this, though. Should
++  // investigate. (update: GetModuleHandle() looks like the place to
++  // start looking in the Win32 API.)
++  //
++  // 20010927 mortene.
++
++  // OpenGL canvas settings.
++  {
++    SbString s;
++    s.sprintf("\nCurrent OpenGL canvas:\n"
++              "         %sbuffer\n"
++              "         drawing to %sbuffer\n"
++              "         %s rendering%s\n"
++              "         %s mode\n"
++              "         with%s overlay planes\n",
++              PUBLIC(this)->isDoubleBuffer() ? "double" : "single",
++              PUBLIC(this)->isDrawToFrontBufferEnable() ? "front" : "back",
++              PUBLIC(this)->isStereoBuffer() ? "stereo" : "mono",
++              PUBLIC(this)->isQuadBufferStereo() ? " (OpenGL quadbuffer)" : "",
++              PUBLIC(this)->isRGBMode() ? "RGB" : "colorindex",
++              PUBLIC(this)->isOverlayRender() ? "" : "out");
++
++    // FIXME: information about the native OpenGL widget format?
++    // 20010927 mortene.
++
++    info += s;
++  }
++
++  // Underlying Inventor implementation.
++  {
++    SbString s;
++    s.sprintf("\nInventor implementation: %s\n", SoDB::getVersion());
++    info += s;
++  }
++
++  So at Gui@::createSimpleErrorDialog(NULL, "So at Gui@ implementation info",
++                                    info.getString());
++#endif // DEBUGGING_EGGS
++}
++
++void
++So at Gui@RenderAreaP::dumpScenegraph(void)
++{
++#ifdef DEBUGGING_EGGS
++  SoOutput out;
++  SbString filename = SbTime::getTimeOfDay().format();
++  filename += "-dump.iv";
++  SbBool ok = out.openFile(filename.getString());
++  if (!ok) {
++    SoDebugError::post("So at Gui@RenderAreaP::dumpScenegraph",
++                       "couldn't open file '%s'", filename.getString());
++    return;
++  }
++  SoWriteAction wa(&out);
++  wa.apply(this->normalManager->getSceneGraph());
++  SoDebugError::postInfo("So at Gui@RenderAreaP::dumpScenegraph",
++                         "dumped scenegraph to '%s'", filename.getString());
++#endif // DEBUGGING_EGGS
++}
++
++void
++So at Gui@RenderAreaP::dumpCameras(void)
++{
++#ifdef DEBUGGING_EGGS
++  const SbBool kitsearch = SoBaseKit::isSearchingChildren();
++  SoBaseKit::setSearchingChildren(TRUE);
++
++  SoSearchAction search;
++  search.setType(SoCamera::getClassTypeId());
++  search.setInterest(SoSearchAction::ALL);
++  search.setSearchingAll(TRUE);
++  search.apply(this->normalManager->getSceneGraph());
++
++  SoBaseKit::setSearchingChildren(kitsearch);
++
++  const SoPathList & pl = search.getPaths();
++  const unsigned int numcams = pl.getLength();
++  SoDebugError::postInfo("So at Gui@RenderAreaP::dumpCameras",
++                         "Number of cameras in scene graph: %d",
++                         numcams);
++
++  for (unsigned int i = 0; i < numcams; i++) {
++    const SoPath * p = pl[i];
++    SoNode * n = p->getTail();
++    assert(n->isOfType(SoCamera::getClassTypeId()));
++    SoCamera * cam = (SoCamera *)n;
++
++    const SbVec3f pos = cam->position.getValue();
++    const SbRotation rot = cam->orientation.getValue();
++    SbVec3f axis;
++    float angle;
++    rot.getValue(axis, angle);
++
++    SoDebugError::postInfo("So at Gui@RenderAreaP::dumpCameras",
++                           "type==%s, name=='%s', position==<%f, %f, %f>, "
++                           "orientation-rotation==<%f, %f, %f>--%f",
++                           cam->getTypeId().getName().getString(),
++                           cam->getName().getString(),
++                           pos[0], pos[1], pos[2],
++                           axis[0], axis[1], axis[2], angle);
++  }
++#endif // DEBUGGING_EGGS
++}
++
++/*
++  Behaviour controlled by environment variables
++    COIN_SOGRAB_GEOMETRY  (maximum geometry - on-screen aspect is preserved)
++    COIN_SOGRAB_FILENAME  (filename template - can use %d to insert counter)
++
++  Examples:
++    export COIN_SOGRAB_GEOMETRY=1024x768
++    export COIN_SOGRAB_FILENAME=c:\\grab%03d.png
++
++*/
++
++void
++So at Gui@RenderAreaP::offScreenGrab(void)
++{
++#ifdef DEBUGGING_EGGS
++  static int maxwidth = -1;
++  static int maxheight = -1;
++  static int counter = 0;
++  static const char fallback_ext[] = ".rgb";
++  static const char fallback_name[] = "coingrab%03d.rgb";
++
++  /*
++    FIXME:
++
++    - schedule a regular render-pass and hook into the render
++      pipe-line to check all the interesting GL context features that
++      might need to be enabled for the offscreen renderer context.
++      Then set up the offscreen renderer context to match those
++      features, so the rendering becomes the same.
++    - create a clone of the on-screen renderaction to get the same
++      kind of custom rendering.
++    - check if we might be able to hook up the on-screen pre-render
++      callback to the offscreen renderer as well, if any point.
++    - disable accidentally enabled seek mode again (from typing 'osgrab').
++
++    20050606 larsa.
++  */
++
++  counter++;
++  if ( maxwidth <= 0 ) {
++    const char * env = 
++      SoAny::si()->getenv("COIN_SOGRAB_GEOMETRY");
++    if ( env ) {
++      sscanf(env, "%dx%d", &maxwidth, &maxheight);
++    }
++    if ( (maxwidth <= 0) || !env ) {
++      SbVec2s vp = PUBLIC(this)->getViewportRegion().getWindowSize();
++      maxwidth = vp[0];
++      maxheight = vp[1];
++    }
++  }
++
++  if ( maxwidth <= 0 || maxheight <= 0 ) {
++    SoDebugError::post("So at Gui@RenderAreaP::offScreenGrab",
++                       "invalid geometry: %dx%d", maxwidth, maxheight);
++    return;
++  }
++  SbVec2s vp = PUBLIC(this)->getViewportRegion().getWindowSize();
++
++  const char * filenametpl =
++    SoAny::si()->getenv("COIN_SOGRAB_FILENAME");
++  if ( !filenametpl ) filenametpl = fallback_name;
++
++  SbString filename;
++  filename.sprintf(filenametpl, counter);
++  const char * ext = strrchr(filename.getString(), '.');
++  if ( !ext ) ext = fallback_ext;
++  ext++;
++
++  SbVec2s osvp(maxwidth, maxheight);
++  if ( vp[0] > maxwidth || vp[1] > maxheight ||
++       (vp[0] < maxwidth && vp[1] < maxheight) ) {
++    float onscaspect = float(vp[0]) / float(vp[1]);
++    float offscaspect = float(maxwidth) / float(maxheight);
++
++    osvp[1] = maxheight;
++    osvp[0] = short(maxheight * onscaspect);
++    if ( osvp[0] > maxwidth ) {
++      osvp[0] = maxwidth;
++      osvp[1] = short(maxwidth * (1.0f / onscaspect));
++    }
++  }
++
++  SoOffscreenRenderer os(osvp);
++  if ( !os.render(PUBLIC(this)->getSceneManager()->getSceneGraph()) ) {
++    return;
++  }
++
++  SbBool written = FALSE;
++  if (strcmp(ext, "rgb") == 0) {
++    written = os.writeToRGB(filename.getString());
++  }
++  else {
++    written = os.writeToFile(filename, ext);
++  }
++
++  if (written) {
++    SoDebugError::postInfo("So at Gui@RenderAreaP::offScreenGrab",
++                           "wrote image #%d, %dx%d as '%s'",
++                           counter, osvp[0], osvp[1],
++                           filename.getString());
++  }
++  else {
++    SoDebugError::post("So at Gui@RenderAreaP::offScreenGrab",
++                       "tried to write image '%s', but failed for unknown "
++                       "reason",
++                       filename.getString());
++  }
++#endif // DEBUGGING_EGGS
++}
++
++int
++So at Gui@RenderAreaP::checkMagicSequences(const char c)
++{
++#if DEBUGGING_EGGS
++  this->currentinput += c;
++
++  if (0) { // handy for debugging keyboard handling
++    SoDebugError::postInfo("So at Gui@RenderAreaP::checkMagicSequences",
++                           "'%s'", this->currentinput.getString());
++  }
++
++  const int cl = this->currentinput.getLength();
++
++  static const char * keyseq[] = {
++    "glinfo", "ivinfo", "soinfo", "dumpiv", "cameras", "osgrab"
++  };
++  static const int id[] = {
++    So at Gui@RenderAreaP::OPENGL,
++    So at Gui@RenderAreaP::INVENTOR,
++    So at Gui@RenderAreaP::TOOLKIT,
++    So at Gui@RenderAreaP::DUMPSCENEGRAPH,
++    So at Gui@RenderAreaP::DUMPCAMERAS,
++    So at Gui@RenderAreaP::OFFSCREENGRAB
++  };
++
++  for (unsigned int i = 0; i < (sizeof(keyseq) / sizeof(keyseq[0])); i++) {
++    const int ml = strlen(keyseq[i]);
++    if (cl >= ml && this->currentinput.getSubString(cl - ml) == keyseq[i]) {
++      return id[i];
++    }
++  }
++
++  // Limit memory usage.
++  if (cl > 1024) { this->currentinput = ""; }
++#endif // DEBUGGING_EGGS
++
++  return So at Gui@RenderAreaP::NONE;
++}
++
++// This method sets the window size data in all the connected device
++// classes.
++void
++So at Gui@RenderAreaP::setDevicesWindowSize(const SbVec2s size)
++{
++  if (!this->devicelist) return;
++  const int num = this->devicelist->getLength();
++  for (int i = 0; i < num; i++)
++    ((So at Gui@Device *)(*this->devicelist)[i])->setWindowSize(size);
++}
++
++// *************************************************************************
++
++void
++So at Gui@RenderAreaP::renderCB(void * closure, SoSceneManager * manager)
++{
++  assert(closure && manager);
++  So at Gui@RenderArea * thisptr = (So at Gui@RenderArea *) closure;
++  if (manager == PRIVATE(thisptr)->normalManager) {
++    thisptr->render();
++  } else if (manager == PRIVATE(thisptr)->overlayManager) {
++    thisptr->renderOverlay();
++  } else {
++#if SO at GUI@_DEBUG
++    SoDebugError::post("So at Gui@RenderAreaP::renderCB",
++                       "invoked for unknown SoSceneManager (%p)", manager);
++#endif // SO at GUI@_DEBUG
++    return;
++  }
++}
++
++// Callback for automatic redraw on SoSelection changes.
++void
++So at Gui@RenderAreaP::selection_redraw_cb(void * closure, SoSelection * sel)
++{
++  So at Gui@RenderArea * ra = (So at Gui@RenderArea *) closure;
++  if (sel == PRIVATE(ra)->normalselection)
++    ra->scheduleRedraw();
++  else if (sel == PRIVATE(ra)->overlayselection)
++    ra->scheduleOverlayRedraw();
++  else
++    assert(0 && "callback on unknown SoSelection node");
++}
++
++// Private class constructor.
++So at Gui@RenderAreaP::So at Gui@RenderAreaP(So at Gui@RenderArea * api)
++{
++  PUBLIC(this) = api;
++
++  this->normalManager = new SoSceneManager;
++  this->overlayManager = new SoSceneManager;
++
++  this->normalColormap = NULL;
++  this->normalColormapSize = 0;
++  this->overlayColormap = NULL;
++  this->overlayColormapSize = 0;
++
++  this->clear = TRUE;
++  this->clearZBuffer = TRUE;
++  this->clearOverlay = TRUE;
++  this->autoRedraw = TRUE;
++
++  this->normalselection = NULL;
++  this->overlayselection = NULL;
++
++  this->devices.mouse = NULL;
++  this->devices.keyboard = NULL;
++#ifdef HAVE_SPACENAV_SUPPORT
++  this->devices.spacenav = NULL;
++#endif // HAVE_SPACENAV_SUPPORT
++
++}
++
++// Private class destructor.
++So at Gui@RenderAreaP::~So at Gui@RenderAreaP()
++{
++  delete this->normalManager;
++  delete this->overlayManager;
++  delete [] this->normalColormap;
++  delete [] this->overlayColormap;
++}
++
++// Common code for all constructors.
++void
++So at Gui@RenderAreaP::constructor(SbBool mouseInput,
++                                SbBool keyboardInput,
++                                SbBool build)
++{
++  this->normalManager->setRenderCallback(So at Gui@RenderAreaP::renderCB, PUBLIC(this));
++  this->normalManager->activate();
++  this->overlayManager->setRenderCallback(So at Gui@RenderAreaP::renderCB, PUBLIC(this));
++  this->overlayManager->activate();
++  // FIXME: what is this magic number doing here - shouldn't we use
++  // SoGLCacheContextElement::getUniqueCacheContext() for Coin, and
++  // magic numbers just for SGI / TGS Inventor?
++  //
++  // On a side note: won't this code fail if we construct several
++  // So at Gui@RenderArea instances with overlays? They will all use
++  // cachecontext==1 for their SoGLRenderAction instances -- is that
++  // kosher?
++  //
++  // 20010831 mortene.
++  this->overlayManager->getGLRenderAction()->setCacheContext(1);
++
++  this->appeventhandler = NULL;
++  this->appeventhandlerdata = NULL;
++
++  this->devicelist = new SbPList;
++
++  if (mouseInput) {
++    this->devices.mouse = new So at Gui@Mouse;
++    PUBLIC(this)->registerDevice(this->devices.mouse);
++  }
++
++  if (keyboardInput) {
++    this->devices.keyboard = new So at Gui@Keyboard;
++    PUBLIC(this)->registerDevice(this->devices.keyboard);
++  }
++
++  if (! build) return;
++  PUBLIC(this)->setClassName("So at Gui@RenderArea");
++  @WIDGET@ glarea = PUBLIC(this)->buildWidget(PUBLIC(this)->getParentWidget());
++  PUBLIC(this)->setBaseWidget(glarea);
++  PUBLIC(this)->setSize(SbVec2s(400, 400));
++}
++
++// This method invokes the application event handler, if one is set.
++SbBool
++So at Gui@RenderAreaP::invokeAppCB(@EVENT@ event)
++{
++  if (this->appeventhandler != NULL)
++    return this->appeventhandler(this->appeventhandlerdata, event);
++  return FALSE;
++}
++
++// This method returns an SoEvent * corresponding to the given \a
++// event, or \c NULL if there are none.
++const SoEvent *
++So at Gui@RenderAreaP::getSoEvent(@EVENT@ event)
++{
++  if (!this->devicelist)
++    return (SoEvent *) NULL;
++
++  const SoEvent * soevent = NULL;
++  const int num = this->devicelist->getLength();
++  for (int i = 0; (i < num) && (soevent == NULL); i++)
++    soevent = ((So at Gui@Device *)(*this->devicelist)[i])->translateEvent(event);
++
++  return soevent;
++}
++
++#endif // DOXYGEN_SKIP_THIS
++
++// *************************************************************************
++
++/*!
++  Public constructor.
++*/
++So at Gui@RenderArea::So at Gui@RenderArea(@WIDGET@ parent,
++                                     const char * name,
++                                     SbBool embed,
++                                     SbBool mouseInput,
++                                     SbBool keyboardInput)
++  : inherited(parent, name, embed, So at Gui@RenderAreaP::GL_DEFAULT_MODE, FALSE)
++{
++  PRIVATE(this) = new So at Gui@RenderAreaP(this);
++  PRIVATE(this)->constructor(mouseInput, keyboardInput, TRUE);
++}
++
++/*!
++  Protected constructor used by derived classes.
++*/
++So at Gui@RenderArea::So at Gui@RenderArea(@WIDGET@ parent,
++                                     const char * name,
++                                     SbBool embed,
++                                     SbBool mouseInput,
++                                     SbBool keyboardInput,
++                                     SbBool build)
++  : inherited(parent, name, embed, So at Gui@RenderAreaP::GL_DEFAULT_MODE, FALSE)
++{
++  PRIVATE(this) = new So at Gui@RenderAreaP(this);
++  PRIVATE(this)->constructor(mouseInput, keyboardInput, build);
++}
++
++/*!
++  Destructor.
++*/
++So at Gui@RenderArea::~So at Gui@RenderArea()
++{
++  // Clean out any callbacks we may have registered with SoSelection
++  // nodes.
++  this->redrawOverlayOnSelectionChange(NULL);
++  this->redrawOnSelectionChange(NULL);
++
++  for (int i = PRIVATE(this)->devicelist->getLength() - 1; i >= 0; i--) {
++    So at Gui@Device * device = (So at Gui@Device *) ((*PRIVATE(this)->devicelist)[i]);
++    this->unregisterDevice(device);
++    delete device;
++  }
++  delete PRIVATE(this)->devicelist;
++  delete PRIVATE(this);
++}
++
++// *************************************************************************
++
++/*!
++  This method adds \a device to the list of devices handling events
++  for this component.
++*/
++void
++So at Gui@RenderArea::registerDevice(So at Gui@Device * device)
++{
++  int idx = PRIVATE(this)->devicelist->find(device);
++  if (idx != -1) {
++#if SO at GUI@_DEBUG
++    SoDebugError::postWarning("So at Gui@RenderArea::registerDevice",
++                              "device already registered");
++#endif // SO at GUI@_DEBUG
++    return;
++  }
++
++  PRIVATE(this)->devicelist->append(device);
++  @WIDGET@ w = this->getGLWidget();
++  if (w != NULL) {
++#ifdef __COIN_SOXT__
++    device->enable(w, (SoXtEventHandler *) &So at Gui@GLWidget::eventHandler, (void *)this);
++#else
++    device->enable(w, &So at Gui@GLWidgetP::eventHandler, (void *)this);
++#endif
++    device->setWindowSize(this->getGLSize());
++  }
++}
++
++/*!
++  This method removes \a device from the list of devices handling
++  events for this component.
++*/
++void
++So at Gui@RenderArea::unregisterDevice(So at Gui@Device * device)
++{
++  assert(PRIVATE(this)->devicelist != NULL);
++  const int idx = PRIVATE(this)->devicelist->find(device);
++  if (idx == -1) {
++#if SO at GUI@_DEBUG
++    SoDebugError::post("So at Gui@RenderArea::unregisterDevice",
++                       "tried to remove nonexisting device");
++#endif // SO at GUI@_DEBUG
++    return;
++  }
++
++  PRIVATE(this)->devicelist->remove(idx);
++  @WIDGET@ w = this->getGLWidget();
++  if (w != NULL) { device->disable(w, NULL, NULL); }
++}
++
++// *************************************************************************
++
++// Documented in superclass.
++void
++So at Gui@RenderArea::afterRealizeHook(void)
++{
++  inherited::afterRealizeHook();
++
++#ifdef HAVE_JOYSTICK_LINUX
++  if (So at Gui@LinuxJoystick::exists())
++    this->registerDevice(new So at Gui@LinuxJoystick);
++#endif // HAVE_JOYSTICK_LINUX
++
++#ifdef HAVE_SPACENAV_SUPPORT
++  PRIVATE(this)->devices.spacenav = new So at Gui@SpacenavDevice;
++  this->registerDevice(PRIVATE(this)->devices.spacenav);
++#endif // HAVE_SPACENAV_SUPPORT
++}
++
++/*!
++  This method sets the scene graph to be rendered in the normal bitmap
++  planes.
++
++  \sa getSceneGraph(), setOverlaySceneGraph()
++*/
++void
++So at Gui@RenderArea::setSceneGraph(SoNode * scene)
++{
++  PRIVATE(this)->normalManager->setSceneGraph(scene);
++}
++
++/*!
++  This method returns a reference to the scene graph root node as set
++  by the user.
++
++  \sa So at Gui@RenderArea::getSceneManager()
++*/
++SoNode *
++So at Gui@RenderArea::getSceneGraph(void)
++{
++  return PRIVATE(this)->normalManager->getSceneGraph();
++}
++
++/*!
++  This method sets the scene graph to render for the overlay bitmap
++  planes.
++
++  It will automatically take care of setting up overplay planes in the
++  OpenGL canvas if the OpenGL hardware and driver supports it.
++
++  Important note: not all graphics hardware and / or drivers for
++  graphics hardware support overlay planes, so application programmers
++  are adviced to find some other way of accomplishing what they want
++  to do before resorting to using overlay planes.  Using overlay
++  planes will in practice severely limit the portability of
++  applications which depend on them being available.
++
++  \sa setSceneGraph(), getOverlaySceneGraph()
++*/
++void
++So at Gui@RenderArea::setOverlaySceneGraph(SoNode * scene)
++{
++  SoNode * oldroot = this->getOverlaySceneGraph();
++  PRIVATE(this)->overlayManager->setSceneGraph(scene);
++
++  if (!oldroot && scene) { this->setOverlayRender(TRUE); }
++  else if (oldroot && !scene) { this->setOverlayRender(FALSE); }
++}
++
++/*!
++  This method returns the scene graph for the overlay scene.
++*/
++SoNode *
++So at Gui@RenderArea::getOverlaySceneGraph(void)
++{
++  return PRIVATE(this)->overlayManager->getSceneGraph();
++}
++
++// *************************************************************************
++
++/*!
++  This method sets the background color of the scene.
++*/
++void
++So at Gui@RenderArea::setBackgroundColor(const SbColor & color)
++{
++  assert(PRIVATE(this)->normalManager != NULL);
++  PRIVATE(this)->normalManager->setBackgroundColor(color);
++  this->scheduleRedraw();
++}
++
++/*!
++  This method returns the background color for the scene.
++*/
++const SbColor &
++So at Gui@RenderArea::getBackgroundColor(void) const
++{
++  assert(PRIVATE(this)->normalManager != NULL);
++#if HAVE_SBCOLOR4F_GETBACKGROUNDCOLOR
++  SbColor4f bgcol = PRIVATE(this)->normalManager->getBackgroundColor();
++  return SbColor(bgcol[0], bgcol[1], bgcol[2]);
++#else
++  return PRIVATE(this)->normalManager->getBackgroundColor();
++#endif
++}
++
++// *************************************************************************
++
++/*!
++  This method sets the index of the background color for the scene.
++*/
++void
++So at Gui@RenderArea::setBackgroundIndex(int idx)
++{
++  assert(PRIVATE(this)->normalManager != NULL);
++  PRIVATE(this)->normalManager->setBackgroundIndex(idx);
++  this->scheduleRedraw();
++}
++
++/*!
++  This method returns the index of the background color for the scene.
++*/
++int
++So at Gui@RenderArea::getBackgroundIndex(void) const
++{
++  assert(PRIVATE(this)->normalManager != NULL);
++  return PRIVATE(this)->normalManager->getBackgroundIndex();
++}
++
++// *************************************************************************
++
++/*!
++  This method sets the index of the background for the overlay scene.
++*/
++void
++So at Gui@RenderArea::setOverlayBackgroundIndex(int idx)
++{
++  assert(PRIVATE(this)->overlayManager != NULL);
++  PRIVATE(this)->overlayManager->setBackgroundIndex(idx);
++  this->scheduleOverlayRedraw();
++}
++
++/*!
++  This method returns the index of the background for the overlay scene.
++*/
++int
++So at Gui@RenderArea::getOverlayBackgroundIndex(void) const
++{
++  assert(PRIVATE(this)->overlayManager != NULL);
++  return PRIVATE(this)->overlayManager->getBackgroundIndex();
++}
++
++// *************************************************************************
++
++/*!
++  This method sets the colormap for the scene.
++*/
++void
++So at Gui@RenderArea::setColorMap(int start, int num, const SbColor * colors)
++{
++  delete [] PRIVATE(this)->normalColormap;
++  PRIVATE(this)->normalColormapStart = start;
++  PRIVATE(this)->normalColormapSize = num;
++  PRIVATE(this)->normalColormap = new SbColor [ num ];
++  for (int i = 0; i < num; i++)
++    PRIVATE(this)->normalColormap[i] = colors[i];
++  this->scheduleRedraw();
++}
++
++/*!
++  This method sets the colormap for the overlay scene.
++*/
++void
++So at Gui@RenderArea::setOverlayColorMap(int start, int num,
++                                      const SbColor * colors)
++{
++  delete [] PRIVATE(this)->overlayColormap;
++  PRIVATE(this)->overlayColormapStart = start;
++  PRIVATE(this)->overlayColormapSize = num;
++  PRIVATE(this)->overlayColormap = new SbColor [ num ];
++  for (int i = 0; i < num; i++) {
++    PRIVATE(this)->overlayColormap[i] = colors[i];
++  }
++  this->scheduleOverlayRedraw();
++}
++
++// *************************************************************************
++
++/*!
++  This method sets the viewport region.
++*/
++void
++So at Gui@RenderArea::setViewportRegion(const SbViewportRegion & region)
++{
++  if (region.getWindowSize()[0] == -1) return;
++
++#if SO at GUI@_DEBUG && 0 // debug
++  SoDebugError::postInfo("So at Gui@RenderArea::setViewportRegion",
++                         "size=<%d, %d>",
++                         region.getWindowSize()[0],
++                         region.getWindowSize()[1]);
++#endif // debug
++
++  PRIVATE(this)->normalManager->setViewportRegion(region);
++  PRIVATE(this)->overlayManager->setViewportRegion(region);
++  this->scheduleRedraw();
++}
++
++/*!
++  This method returns the viewport region.
++*/
++const SbViewportRegion &
++So at Gui@RenderArea::getViewportRegion(void) const
++{
++  assert(PRIVATE(this)->normalManager != NULL);
++  return PRIVATE(this)->normalManager->getGLRenderAction()->getViewportRegion();
++}
++
++// *************************************************************************
++
++/*!
++  This method sets the transparency type to be used for the scene.
++*/
++void
++So at Gui@RenderArea::setTransparencyType(SoGLRenderAction::TransparencyType type)
++{
++  assert(PRIVATE(this)->normalManager != NULL);
++  PRIVATE(this)->normalManager->getGLRenderAction()->setTransparencyType(type);
++  PRIVATE(this)->overlayManager->getGLRenderAction()->setTransparencyType(type);
++  this->scheduleRedraw();
++}
++
++/*!
++  This method returns the transparency type used for the scene.
++*/
++SoGLRenderAction::TransparencyType
++So at Gui@RenderArea::getTransparencyType(void) const
++{
++  assert(PRIVATE(this)->normalManager != NULL);
++  return PRIVATE(this)->normalManager->getGLRenderAction()->getTransparencyType();
++}
++
++// *************************************************************************
++
++/*!
++  This method sets the antialiasing used for the scene.
++
++  The \a smoothing flag signifies whether or not line and point
++  aliasing should be turned on. See documentation of
++  SoGLRenderAction::setSmoothing(), which will be called from this
++  function.
++
++  \a numPasses gives the number of re-renderings to do of the scene,
++  blending together the results from slight "jitters" of the camera
++  view, into the OpenGL accumulation buffer. For further information,
++  see documentation of SoGLRenderAction::setNumPasses() and
++  So at Gui@GLWidget::setAccumulationBuffer().
++*/
++void
++So at Gui@RenderArea::setAntialiasing(SbBool smoothing, int numPasses)
++{
++  // FIXME: is this really necessary? I think we should either ignore
++  // the call or store values for later migration if the scenemanager
++  // instance(s) haven't been made yet. 20010331 mortene.
++  assert(PRIVATE(this)->normalManager != NULL);
++
++  // Instead of piping the call further to
++  // SoSceneManager::setAntialiasing(), we duplicate the code found in
++  // that function. The reason for this is that we want to work around
++  // a bug found in SGI Inventor, where they define the
++  // setAntialiasing() method, but doesn't actually implement it.  So
++  // we don't use it to avoid a linker error for those compiling So*
++  // libraries on top of the older SGI Inventor versions with this
++  // bug.
++  //
++  // We should perhaps throw in a configure check for the
++  // SoSceneManager::setAntialiasing() method and only activate this
++  // code when actually needed?
++  //                                                   mortene at sim.no
++  enum { MGRS = 2 };
++  SoSceneManager * mgrs[MGRS] = { PRIVATE(this)->normalManager,
++                                  PRIVATE(this)->overlayManager };
++  for (int i=0; i < MGRS; i++) {
++    SoGLRenderAction * glra = mgrs[i]->getGLRenderAction();
++    if (glra) {
++      glra->setSmoothing(smoothing);
++      glra->setNumPasses(numPasses);
++    }
++  }
++
++  this->scheduleRedraw();
++}
++
++/*!
++  This method returns the antialiasing used for the scene.
++*/
++void
++So at Gui@RenderArea::getAntialiasing(SbBool & smoothing, int & numPasses) const
++{
++  // FIXME: there's an API design flaw here, as it is assumed that the
++  // antialiasing setting for the renderaction in the "normal"
++  // rendering context always matches what is the case for the
++  // renderaction in the overlay manager. This is not necessarily
++  // true. Could be solved by an additional argument to
++  // getAntialiasing(): a boolean indicator on whether or not we want
++  // the overlay context with a default value (false) to keep API
++  // compatibility. 20010331 mortene.
++
++  assert(PRIVATE(this)->normalManager != NULL);
++
++  // About why we don't use SoSceneManager::getAntialiasing()
++  // directly, see comment in SoGuiRenderArea::setAntiAliasing().
++  SoGLRenderAction * glra = PRIVATE(this)->normalManager->getGLRenderAction();
++  smoothing = glra->isSmoothing();
++  numPasses = glra->getNumPasses();
++}
++
++/*!
++  This method sets whether the render buffer should be cleared before
++  rendering.
++
++  The first argument specifies whether or not to clear out the pixels
++  in the buffer, the second argument specifies whether or not the
++  z-buffer values should be cleared between renderings.
++
++  Setting the first argument to \c FALSE can for instance be used when
++  you want to clear out the buffer yourself, for instance by drawing a
++  background image "under" the 3D scene rendered by Coin / Inventor.
++*/
++void
++So at Gui@RenderArea::setClearBeforeRender(SbBool enable, SbBool zbEnable)
++{
++  PRIVATE(this)->clear = enable;
++  PRIVATE(this)->clearZBuffer = zbEnable;
++
++  this->scheduleRedraw();
++}
++
++/*!
++  This method returns whether the render buffer is cleared before each
++  render.
++*/
++SbBool
++So at Gui@RenderArea::isClearBeforeRender(void) const
++{
++  return PRIVATE(this)->clear;
++}
++
++/*!
++  This method returns whether the render buffer's Z buffer is cleared
++  before each render.
++*/
++SbBool
++So at Gui@RenderArea::isClearZBufferBeforeRender(void) const
++{
++  return PRIVATE(this)->clearZBuffer;
++}
++
++/*!
++  This method sets whether the overlay render buffer should be cleared
++  before each render or not.
++*/
++void
++So at Gui@RenderArea::setClearBeforeOverlayRender(SbBool enable)
++{
++  PRIVATE(this)->clearOverlay = enable;
++  this->scheduleOverlayRedraw();
++}
++
++/*!
++  This method returns whether the overlay render buffer is cleared
++  before each redraw or not.
++*/
++SbBool
++So at Gui@RenderArea::isClearBeforeOverlayRender(void) const
++{
++  return PRIVATE(this)->clearOverlay;
++}
++
++/*!
++  This method sets whether redrawing should be handled automatically
++  or not when data in the scenegraph changes.
++
++  The default setting causes the renderarea to automatically trigger a
++  redraw of the scenegraph contents.
++*/
++void
++So at Gui@RenderArea::setAutoRedraw(SbBool enable)
++{
++  if (enable) {
++    PRIVATE(this)->normalManager->activate();
++    PRIVATE(this)->overlayManager->activate();
++  }
++  else {
++    PRIVATE(this)->normalManager->deactivate();
++    PRIVATE(this)->overlayManager->deactivate();
++  }
++  PRIVATE(this)->autoRedraw = enable;
++}
++
++/*!
++  This method returns whether redrawing is handled automatically 
++  not.
++*/
++SbBool
++So at Gui@RenderArea::isAutoRedraw(void) const
++{
++  return PRIVATE(this)->autoRedraw;
++}
++
++/*!
++  This method sets the redraw priority.
++*/
++void
++So at Gui@RenderArea::setRedrawPriority(uint32_t priority)
++{
++  PRIVATE(this)->normalManager->setRedrawPriority(priority);
++  PRIVATE(this)->overlayManager->setRedrawPriority(priority);
++}
++
++/*!
++  This method returns the redraw priority.
++*/
++uint32_t
++So at Gui@RenderArea::getRedrawPriority(void) const
++{
++  assert(PRIVATE(this)->normalManager != NULL);
++  return PRIVATE(this)->normalManager->getRedrawPriority();
++}
++
++/*!
++  This function returns the default redraw priority.
++*/
++uint32_t
++So at Gui@RenderArea::getDefaultRedrawPriority(void)
++{
++  return SoSceneManager::getDefaultRedrawPriority();
++}
++
++/*!
++  This method causes the immediate rendering of the scene, by calling
++  So at Gui@RenderArea::redraw().
++*/
++void
++So at Gui@RenderArea::render(void)
++{
++  this->redraw();
++}
++
++/*!
++  This method renders the overlay scene.
++*/
++void
++So at Gui@RenderArea::renderOverlay(void)
++{
++  this->redrawOverlay();
++}
++
++/*!
++  This method schedules a redraw to happen at a later time (when the
++  application has processed it's other events first).
++*/
++void
++So at Gui@RenderArea::scheduleRedraw(void)
++{
++#if SO at GUI@_DEBUG && RENDERAREA_DEBUG_REDRAWS // debug
++  SoDebugError::postInfo("So at Gui@RenderArea::scheduleRedraw",
++                         "invoked");
++#endif // debug
++  
++  assert(PRIVATE(this)->normalManager != NULL);
++  PRIVATE(this)->normalManager->scheduleRedraw(); // Redraw when idle.
++}
++
++/*!
++  This method schedules a redraw of the overlay scene.
++*/
++void
++So at Gui@RenderArea::scheduleOverlayRedraw(void)
++{
++  assert(PRIVATE(this)->overlayManager != NULL);
++  PRIVATE(this)->overlayManager->scheduleRedraw(); // Redraw when idle.
++}
++
++#ifndef DOXYGEN_SKIP_THIS
++void
++So at Gui@RenderAreaP::replaceSoSelectionMonitor(SoSelection * newsel,
++                                              SoSelection * oldsel) const
++{
++  if (newsel) { newsel->ref(); }
++
++  if (oldsel) {
++    oldsel->removeChangeCallback(So at Gui@RenderAreaP::selection_redraw_cb,
++                                 PUBLIC(this));
++    oldsel->unref();
++  }
++
++  if (newsel) {
++    newsel->addChangeCallback(So at Gui@RenderAreaP::selection_redraw_cb,
++                              PUBLIC(this));
++  }
++}
++#endif // DOXYGEN_SKIP_THIS
++
++// FIXME: the interface below is badly designed, see the comment in
++// the function documentation. 20001002 mortene.
++
++/*!
++  Do automatic redraw of the scenegraph when a selection under the
++  SoSelection node is changed.
++
++  Pass \c NULL to deactivate.
++
++  (Only one SoSelection node can be monitored at any given time. This
++  is obviously a rather silly design flaw. We choose to match the
++  original Inventor API here, but this will probably change in the
++  next major revision of the library.)
++*/
++void
++So at Gui@RenderArea::redrawOnSelectionChange(SoSelection * selection)
++{
++  PRIVATE(this)->replaceSoSelectionMonitor(selection, PRIVATE(this)->normalselection);
++  PRIVATE(this)->normalselection = selection;
++}
++
++/*!
++  Do automatic redraw of the scenegraph in the overlay planes when a
++  selection under the SoSelection node is changed.
++
++  Pass \c NULL to deactivate.
++
++  \sa So at Gui@RenderArea::redrawOnSelectionChange()
++*/
++void
++So at Gui@RenderArea::redrawOverlayOnSelectionChange(SoSelection * selection)
++{
++  PRIVATE(this)->replaceSoSelectionMonitor(selection, PRIVATE(this)->overlayselection);
++  PRIVATE(this)->overlayselection = selection;
++}
++
++/*!
++  This method sets the render area event callback.
++*/
++void
++So at Gui@RenderArea::setEventCallback(So at Gui@RenderAreaEventCB * func,
++                                    void * user)
++{
++  PRIVATE(this)->appeventhandler = func;
++  PRIVATE(this)->appeventhandlerdata = user;
++}
++
++/*!
++  This method sets the normal scene SoSceneManager object.
++
++  The previous set scene manager is deleted, and there is no way to
++  currently avoid that.  This might change in the future.
++*/
++void
++So at Gui@RenderArea::setSceneManager(SoSceneManager * manager)
++{
++  assert(PRIVATE(this)->normalManager != NULL);
++  PRIVATE(this)->normalManager->setRenderCallback(NULL, NULL);
++
++  // NOTE: Although deleting the previous scene manager here is correct
++  // behaviour from a compatibility-POV, I think it is ugly and should
++  // be addressed in some other way if possible. It is also inconsistent
++  // with overlay scenemanager management.  20061015 larsa
++  delete PRIVATE(this)->normalManager;
++
++  PRIVATE(this)->normalManager = manager;
++  if (PRIVATE(this)->normalManager) {
++    PRIVATE(this)->normalManager->setSize(this->getGLSize());
++  }
++}
++
++/*!
++  This method returns the normal scene SoSceneManager object.
++
++  Having a reference to the SoSceneManager instance is useful for
++  getting at the \e real root node of the rendering scenegraph,
++  including camera, headlight and miscellaneous drawstyle nodes.  The
++  getSceneGraph() method will only return the \e user scenegrah for
++  So at Gui@RenderArea subclass So at Gui@Viewer and further subclasses. The
++  reason this is not always what you want is because certain actions
++  (like the SoRayPickAction) needs to traverse a valid camera if it
++  should work as expected.
++
++  If you need to get a pointer to the \e real root node use this
++  method to get the SoSceneManager instance reference used by the
++  So at Gui@RenderArea, then use SoSceneManager::getSceneGraph() to get
++  the root node Coin uses for rendering.
++*/
++SoSceneManager *
++So at Gui@RenderArea::getSceneManager(void) const
++{
++  return PRIVATE(this)->normalManager;
++}
++
++/*!
++  This method sets the overlay scene SoSceneManager object.
++
++  The previous set scene manager is not freed and will leak unless
++  the user frees it.
++*/
++void
++So at Gui@RenderArea::setOverlaySceneManager(SoSceneManager * manager)
++{
++  PRIVATE(this)->overlayManager = manager;
++  if (PRIVATE(this)->overlayManager) {
++    PRIVATE(this)->overlayManager->setSize(this->getGLSize());
++  }
++}
++
++/*!
++  This method returns the overlay scene SoSceneManager object.
++*/
++SoSceneManager *
++So at Gui@RenderArea::getOverlaySceneManager(void) const
++{
++  return PRIVATE(this)->overlayManager;
++}
++
++/*!
++  This method sets the SoGLRenderAction object for the normal scene.
++*/
++void
++So at Gui@RenderArea::setGLRenderAction(SoGLRenderAction * action)
++{
++  assert(PRIVATE(this)->normalManager != NULL);
++  PRIVATE(this)->normalManager->setGLRenderAction(action);
++  // Force an update of the SoGLRenderAction to the correct
++  // updatearea, aspectratio, etc.
++  this->sizeChanged(this->getSize());
++}
++
++/*!
++  This method returns the SoGLRenderAction object for the normal scene.
++*/
++SoGLRenderAction *
++So at Gui@RenderArea::getGLRenderAction(void) const
++{
++  assert(PRIVATE(this)->normalManager != NULL);
++  return PRIVATE(this)->normalManager->getGLRenderAction();
++}
++
++/*!
++  This method sets the SoGLRenderAction object for rendering the
++  overlay scenegraph.
++*/
++void
++So at Gui@RenderArea::setOverlayGLRenderAction(SoGLRenderAction * action)
++{
++  assert(PRIVATE(this)->overlayManager != NULL);
++  PRIVATE(this)->overlayManager->setGLRenderAction(action);
++}
++
++/*!
++  This method returns the SoGLRenderAction object for the overlay scene
++  graph.
++*/
++SoGLRenderAction *
++So at Gui@RenderArea::getOverlayGLRenderAction(void) const
++{
++  assert(PRIVATE(this)->overlayManager != NULL);
++  return PRIVATE(this)->overlayManager->getGLRenderAction();
++}
++
++/*!
++  This method is called from the render() method and takes care of
++  setting up the context for OpenGL rendering (by making the OpenGL
++  canvas the current context and specifying either the front or back
++  buffer for rendering, depending on whether we're in singlebuffer or
++  doublebuffer mode).
++
++  After setting up the OpenGL context, it calls actualRedraw() for the
++  actual scenegraph rendering to take place.
++
++  Finally, the OpenGL buffers are either swapped back-to-front (for
++  doublebuffering) or flushed (for singlebuffering), and our OpenGL
++  context is unlocked.
++
++  The application programmer may override this method if extreme
++  low-level control of the rendering process is necessary. Usually,
++  you should be able to get away with overriding actualRedraw() for
++  special cases, though.
++*/
++void
++So at Gui@RenderArea::redraw(void)
++{
++#if SO at GUI@_DEBUG && RENDERAREA_DEBUG_REDRAWS // debug
++  SoDebugError::postInfo("So at Gui@RenderArea::redraw",
++                         "start (isVisible=%s waitForExpose=%s)",
++                         this->isVisible() ? "TRUE" : "FALSE",
++                         this->waitForExpose ? "TRUE" : "FALSE");
++#endif // debug
++
++  if (! this->isVisible() || !this->hasNormalGLArea() || this->waitForExpose)
++    return;
++  this->glLockNormal(); // this makes the GL context "current"
++
++  SbBool drawfront =
++    ! this->isDoubleBuffer() ||
++    this->isDrawToFrontBufferEnable();
++
++  glDrawBuffer(drawfront ? GL_FRONT : GL_BACK);
++
++  this->actualRedraw();
++
++  if (!drawfront) { this->glSwapBuffers(); }
++  else { this->glFlushBuffer(); }
++  this->glUnlockNormal();
++
++#if SO at GUI@_DEBUG && RENDERAREA_DEBUG_REDRAWS // debug
++  SoDebugError::postInfo("So at Gui@RenderArea::render", "done");
++#endif // debug
++}
++
++// Note: the following function documentation block will also be used
++// for all the miscellaneous viewer subclasses, so keep it general.
++/*!
++  This method instantly redraws the normal (non-overlay) scenegraph by
++  calling SoSceneManager::render().
++
++  Subclasses may override this method to add their own rendering
++  before or after Coin renders it's scenegraph.
++
++  The following is a complete example that demonstrates one way of
++  adding both a background image and foreground (overlay) geometry to
++  the "normal" rendering:
++
++  \code
++  // This example shows how to put a permanent background image on
++  // your viewer canvas, below the 3D graphics, plus overlay
++  // foreground geometry.  Written by mortene.
++  // Copyright Kongsberg Oil & Gas Technologies 2002.
++  
++  // *************************************************************************
++  
++  #include <Inventor/@Gui@/So at Gui@.h>
++  #include <Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.h>
++  #include <Inventor/nodes/SoBaseColor.h>
++  #include <Inventor/nodes/SoCone.h>
++  #include <Inventor/nodes/SoCube.h>
++  #include <Inventor/nodes/SoImage.h>
++  #include <Inventor/nodes/SoLightModel.h>
++  #include <Inventor/nodes/SoOrthographicCamera.h>
++  #include <Inventor/nodes/SoRotationXYZ.h>
++  #include <Inventor/nodes/SoSeparator.h>
++  #include <Inventor/nodes/SoTranslation.h>
++  
++  #include <GL/gl.h>
++  
++  // *************************************************************************
++  
++  class MyExaminerViewer : public So at Gui@ExaminerViewer {
++  
++  public:
++    MyExaminerViewer(@WIDGET@ parent, const char * filename);
++    ~MyExaminerViewer();
++  
++  protected:
++    virtual void actualRedraw(void);
++  
++  private:
++    SoSeparator * bckgroundroot;
++    SoSeparator * foregroundroot;
++    SoRotationXYZ * arrowrotation;
++  };
++  
++  MyExaminerViewer::MyExaminerViewer(@WIDGET@ parent, const char * filename)
++    : So at Gui@ExaminerViewer(parent)
++  {
++    // Coin should not clear the pixel-buffer, so the background image
++    // is not removed.
++    this->setClearBeforeRender(FALSE, TRUE);
++  
++  
++    // Set up background scenegraph with image in it.
++  
++    this->bckgroundroot = new SoSeparator;
++    this->bckgroundroot->ref();
++  
++    SoOrthographicCamera * cam = new SoOrthographicCamera;
++    cam->position = SbVec3f(0, 0, 1);
++    cam->height = 1;
++    // SoImage will be at z==0.0.
++    cam->nearDistance = 0.5;
++    cam->farDistance = 1.5;
++  
++    SoImage * img = new SoImage;
++    img->vertAlignment = SoImage::HALF;
++    img->horAlignment = SoImage::CENTER;
++    img->filename = filename;
++  
++    this->bckgroundroot->addChild(cam);
++    this->bckgroundroot->addChild(img);
++  
++    // Set up foreground, overlayed scenegraph.
++  
++    this->foregroundroot = new SoSeparator;
++    this->foregroundroot->ref();
++  
++    SoLightModel * lm = new SoLightModel;
++    lm->model = SoLightModel::BASE_COLOR;
++  
++    SoBaseColor * bc = new SoBaseColor;
++    bc->rgb = SbColor(1, 1, 0);
++  
++    cam = new SoOrthographicCamera;
++    cam->position = SbVec3f(0, 0, 5);
++    cam->height = 10;
++    cam->nearDistance = 0;
++    cam->farDistance = 10;
++  
++    const double ARROWSIZE = 2.0;
++  
++    SoTranslation * posit = new SoTranslation;
++    posit->translation = SbVec3f(-2.5 * ARROWSIZE, 1.5 * ARROWSIZE, 0);
++  
++    arrowrotation = new SoRotationXYZ;
++    arrowrotation->axis = SoRotationXYZ::Z;
++  
++    SoTranslation * offset = new SoTranslation;
++    offset->translation = SbVec3f(ARROWSIZE/2.0, 0, 0);
++  
++    SoCube * cube = new SoCube;
++    cube->width = ARROWSIZE;
++    cube->height = ARROWSIZE/15.0;
++  
++    this->foregroundroot->addChild(cam);
++    this->foregroundroot->addChild(lm);
++    this->foregroundroot->addChild(bc);
++    this->foregroundroot->addChild(posit);
++    this->foregroundroot->addChild(arrowrotation);
++    this->foregroundroot->addChild(offset);
++    this->foregroundroot->addChild(cube);
++  }
++  
++  MyExaminerViewer::~MyExaminerViewer()
++  {
++    this->bckgroundroot->unref();
++    this->foregroundroot->unref();
++  }
++  
++  void
++  MyExaminerViewer::actualRedraw(void)
++  {
++    // Must set up the OpenGL viewport manually, as upon resize
++    // operations, Coin won't set it up until the SoGLRenderAction is
++    // applied again. And since we need to do glClear() before applying
++    // the action..
++    const SbViewportRegion vp = this->getViewportRegion();
++    SbVec2s origin = vp.getViewportOriginPixels();
++    SbVec2s size = vp.getViewportSizePixels();
++    glViewport(origin[0], origin[1], size[0], size[1]);
++  
++    const SbColor col = this->getBackgroundColor();
++    glClearColor(col[0], col[1], col[2], 0.0f);
++    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
++  
++    // Render our scenegraph with the image.
++    SoGLRenderAction * glra = this->getGLRenderAction();
++    glra->apply(this->bckgroundroot);
++  
++  
++    // Render normal scenegraph.
++    So at Gui@ExaminerViewer::actualRedraw();
++  
++  
++    // Increase arrow angle with 1/1000 � every frame.
++    arrowrotation->angle = arrowrotation->angle.getValue() + (0.001 / M_PI * 180);
++    // Render overlay front scenegraph.
++    glClear(GL_DEPTH_BUFFER_BIT);
++    glra->apply(this->foregroundroot);
++  }
++  
++  // *************************************************************************
++  
++  int
++  main(int argc, char ** argv)
++  {
++    if (argc != 2) {
++      (void)fprintf(stderr, "\n\n\tUsage: %s <image-filename>\n\n", argv[0]);
++      exit(1);
++    }
++  
++    @WIDGET@ window = So at Gui@::init(argv[0]);
++  
++    MyExaminerViewer * viewer = new MyExaminerViewer(window, argv[1]);
++  
++    viewer->setSceneGraph(new SoCone);
++    viewer->show();
++  
++    So at Gui@::show(window);
++    So at Gui@::mainLoop();
++  
++    delete viewer;
++    return 0;
++  }
++  
++  // *************************************************************************
++  \endcode
++*/
++void
++So at Gui@RenderArea::actualRedraw(void)
++{
++  assert(PRIVATE(this)->normalManager != NULL);
++  if ( !this->isVisible() ) return;
++  PRIVATE(this)->normalManager->render(PRIVATE(this)->clear, PRIVATE(this)->clearZBuffer);
++}
++
++/*!
++  This method redraws the overlay scene.
++*/
++void
++So at Gui@RenderArea::redrawOverlay(void)
++{
++  if (!this->isVisible() || this->waitForExpose || !this->hasOverlayGLArea()) {
++    return;
++  }
++  
++  this->glLockOverlay();
++  this->actualOverlayRedraw();
++  this->glFlushBuffer();
++  this->glUnlockOverlay();
++}
++
++/*!
++  This method renders the overlay scene.
++*/
++void
++So at Gui@RenderArea::actualOverlayRedraw(void)
++{
++  assert(PRIVATE(this)->overlayManager != NULL);
++  if (! this->isVisible()) return;
++  PRIVATE(this)->overlayManager->render(PRIVATE(this)->clearOverlay,
++                                        PRIVATE(this)->clearZBuffer);
++}
++
++/*!
++  This method is invoked to initialize the normal graphics.
++*/
++void
++So at Gui@RenderArea::initGraphic(void)
++{
++  SoSceneManager * mgr = this->getSceneManager();
++  if (mgr) {
++    mgr->reinitialize();
++    mgr->setRGBMode(this->isRGBMode());
++
++    SoGLRenderAction * renderaction = mgr->getGLRenderAction();
++    renderaction->setCacheContext(SoAny::si()->getSharedCacheContextId(this));
++    SbBool isdirect = SoGuiGLWidgetP::isDirectRendering(this);
++    renderaction->setRenderingIsRemote(!isdirect);
++  }
++  // FIXME: if not RGB mode, load colormap. pederb.
++
++  inherited::initGraphic();
++}
++
++/*!
++  This method is invoked to initialize the overlay graphics.
++*/
++void
++So at Gui@RenderArea::initOverlayGraphic(void)
++{
++  SoSceneManager * mgr = this->getOverlaySceneManager();
++  if (mgr) {
++    mgr->reinitialize();
++    // FIXME: does overlays really _have_ to be in colorindex mode?
++    // 20020916 mortene.
++    mgr->setRGBMode(FALSE);
++
++    SoGLRenderAction * renderaction = mgr->getGLRenderAction();
++    SbBool isdirect = SoGuiGLWidgetP::isDirectRendering(this);
++    renderaction->setRenderingIsRemote(!isdirect);
++    // FIXME: shouldn't we also setCacheContext() on the renderaction?
++    // 20020916 mortene.
++  }
++  // FIXME: if not RGB mode, load colormap. pederb.
++
++  // FIXME: shouldn't we do inherited::initOverlayGraphic() ? 20010831 mortene.
++}
++
++// doc in super
++void
++So at Gui@RenderArea::sizeChanged(const SbVec2s & size)
++{
++#if SO at GUI@_DEBUG && 0
++  SoDebugError::postInfo("So at Gui@RenderArea::sizeChanged",
++                          "invoked, <%d, %d>", size[0], size[1]);
++#endif // SO at GUI@_DEBUG
++
++  SbVec2s newsize(size);
++
++  if (size[0] == -1)
++    return;
++
++  assert(PRIVATE(this)->normalManager != NULL);
++  assert(PRIVATE(this)->overlayManager != NULL);
++
++  // Workaround for a bug in Qt/Mac 3.1.0 and 3.1.1 (which has been
++  // confirmed fixed in 3.1.2):
++  // 
++  // If the OpenGL context overlaps with the QSizeGrip widget
++  // (generated by default), resizing does not work any more. The
++  // workaround is to leave 15 pixels at the lower border of the
++  // window blank...
++
++#if defined Q_WS_MAC && ((QT_VERSION == 0x030100) || (QT_VERSION == 0x030101))
++
++  // Environment variable to override Qt/Mac 3.1.x workarounds.
++  const char * forcenoresizeworkaround =
++    SoAny::si()->getenv("FORCE_NO_QTMAC_31_RESIZE_WORKAROUND");
++  if (!forcenoresizeworkaround || (atoi(forcenoresizeworkaround) == 0)) {
++
++    if (this->getTypeId() == So at Gui@RenderArea::getClassTypeId()) { 
++      // SoQtRenderArea used as standalone component
++      newsize -= SbVec2s(0, 15);
++
++      // spit out a warning that this is a Qt/Mac bug, not an SoQt problem
++      const char * env = SoAny::si()->getenv("SOQT_NO_QTMAC_BUG_WARNINGS");
++      if (!env || !atoi(env)) {        
++        SoDebugError::postWarning("SoQtRenderArea::sizeChanged",
++                                  "\nThis version of Qt/Mac contains a bug "
++                                  "that makes it necessary to leave the\n"
++                                  "lowermost 15 pixels of the viewer window "
++                                  "blank. Set the environment variable\n"
++                                  "FORCE_NO_QTMAC_31_RESIZE_WORKAROUND=1 to "
++                                  "override this workaround. \n"
++                                  "You can turn off warnings about Qt/Mac "
++                                  "bugs permanently by setting \n"
++                                  "SOQT_NO_QTMAC_BUG_WARNINGS=1.\n");
++      } 
++    } 
++  }
++
++#endif
++
++  this->setGLSize(newsize);
++  const SbVec2s glsize = this->getGLSize();
++
++
++#if SO at GUI@_DEBUG && 0
++  SoDebugError::postInfo("So at Gui@RenderArea::sizeChanged",
++                          "glsize==<%d, %d>", glsize[0], glsize[1]);
++#endif // SO at GUI@_DEBUG
++
++  if (glsize[0] <= 0 || glsize[1] <= 0)
++    return;
++
++  this->setViewportRegion(SbViewportRegion(glsize));
++  PRIVATE(this)->setDevicesWindowSize(glsize);
++
++  // FIXME: aren't both these calls unnecessary as we set the full
++  // viewportregion a few lines above this one? 20020103 mortene.
++  PRIVATE(this)->normalManager->setWindowSize(glsize);
++  PRIVATE(this)->normalManager->setSize(glsize);
++
++  // FIXME: aren't both these calls unnecessary as we set the full
++  // viewportregion a few lines above this one? 20020103 mortene.
++  PRIVATE(this)->overlayManager->setWindowSize(glsize);
++  PRIVATE(this)->overlayManager->setSize(glsize);
++
++  inherited::sizeChanged(glsize);
++
++  // this->scheduleRedraw(); // already done through setViewportRegion()
++}
++
++// Documented in superclass.
++void
++So at Gui@RenderArea::widgetChanged(@WIDGET@ widget)
++{
++  PRIVATE(this)->normalManager->reinitialize();
++  PRIVATE(this)->overlayManager->reinitialize();
++  // FIXME: colorindex mode not supported yet, so this has no
++  // effect. 20001121 mortene.
++#if 0
++  PRIVATE(this)->normalManager->setRGBMode(this->isRGBMode());
++  PRIVATE(this)->overlayManager->setRGBMode(this->isRGBMode());
++#endif
++
++  // FIXME: should also walk through all registered devices and do a
++  // disable() on the old widget and enable() on the new one.
++  // 20001121 mortene.
++}
++
++// Documented in superclass.
++ at WIDGET@
++So at Gui@RenderArea::buildWidget(@WIDGET@ parent)
++{
++  @WIDGET@ widget = inherited::buildWidget(parent);
++
++  if (PRIVATE(this)->devicelist != NULL) {
++    const int num = PRIVATE(this)->devicelist->getLength();
++    for (int i = 0; i < num; i++) {
++      So at Gui@Device * device = (So at Gui@Device *) (*PRIVATE(this)->devicelist)[i];
++#ifdef __COIN_SOXT__
++      device->enable(this->getGLWidget(),
++                     (SoXtEventHandler *) &So at Gui@GLWidget::eventHandler,
++                     (void *) this);
++#else
++      device->enable(this->getGLWidget(),
++                     &So at Gui@GLWidgetP::eventHandler, (void *) this);
++#endif
++    }
++  }
++
++  return widget;
++}
++
++// Documented in superclass.
++const char *
++So at Gui@RenderArea::getDefaultWidgetName(void) const
++{
++  static const char defaultWidgetName[] = "So at Gui@WidgetName";
++  return defaultWidgetName;
++}
++
++// Documented in superclass.
++const char *
++So at Gui@RenderArea::getDefaultTitle(void) const
++{
++  static const char defaultTitle[] = "@Gui@ RenderArea";
++  return defaultTitle;
++}
++
++// Documented in superclass.
++const char *
++So at Gui@RenderArea::getDefaultIconTitle(void) const
++{
++  static const char defaultIconTitle[] = "@Gui@ RenderArea";
++  return defaultIconTitle;
++}
++
++// *************************************************************************
++
++/*!
++  Toolkit-native events are attempted converted to Coin-generic events
++  in the So at Gui@RenderArea::processEvent() method.  If this succeeds,
++  they are forwarded to this method.
++
++  This is a virtual method, and is overridden in it's subclasses to
++  catch events of particular interest to the viewer classes, for
++  instance.
++
++  Return \c TRUE iff the event was processed. If not it should be
++  passed on further up in the inheritance hierarchy by the caller.
++  This last point is extremely important to take note of if you are
++  expanding the toolkit with your own viewer class.
++
++  This method is not part of the original SGI InventorXt API. Note
++  that you can still override the toolkit-native processEvent() method
++  instead of this "generic" method.
++*/
++SbBool
++So at Gui@RenderArea::processSoEvent(const SoEvent * const event)
++{
++  if (PRIVATE(this)->overlayManager->processEvent(event)) { return TRUE; }
++  if (PRIVATE(this)->normalManager->processEvent(event)) { return TRUE; }
++  return FALSE;
++}
++
++// *************************************************************************
++
++/*!
++  Overrides So at Gui@GLWidget::processEvent() to attempt to convert
++  toolkit-native events to Coin-generic events.  If this succeeds, the
++  generic SoEvent is forwarded to So at Gui@RenderArea::processSoEvent().
++ */
++void
++So at Gui@RenderArea::processEvent(@EVENT@ event)
++{
++  // FIXME: This method is not reentrant, but certain GUI toolkits may
++  // run the event-loop recursively with events injected while processing
++  // other events. We must detect when this happens, and queue up the
++  // event for delayed processing after the primary event is done processing.
++  // This means event instances can not be static and rewritten in the
++  // device handlers like they are currently...  20051013 larsa
++
++  if (PRIVATE(this)->invokeAppCB(event)) { return; }
++
++  const SoEvent * soevent = PRIVATE(this)->getSoEvent(event);
++
++  if (soevent != NULL) {
++#if SO at GUI@_DEBUG || defined(DEBUGGING_EGGS)
++    // Undocumented feature: there are several "magic" sequences of
++    // keys when tapped into the rendering canvas which'll pop up a
++    // dialog box with information about that particular feature.
++    //
++    // See code comments behind "case" statements below for which
++    // sequences are available so far.
++
++    if (soevent->isOfType(SoKeyboardEvent::getClassTypeId())) {
++      SoKeyboardEvent * ke = (SoKeyboardEvent *)soevent;
++      if (ke->getState() == SoButtonEvent::UP) {
++        char c = ke->getPrintableCharacter();
++        switch (PRIVATE(this)->checkMagicSequences(c)) {
++        case So at Gui@RenderAreaP::NONE:
++          break;
++        case So at Gui@RenderAreaP::OPENGL:  // "glinfo"
++          this->glLockNormal();
++          PRIVATE(this)->showOpenGLDriverInformation();
++          this->glUnlockNormal();
++          break;
++        case So at Gui@RenderAreaP::INVENTOR:  // "ivinfo"
++          PRIVATE(this)->showInventorInformation();
++          break;
++        case So at Gui@RenderAreaP::TOOLKIT:  // "soinfo"
++          PRIVATE(this)->showToolkitInformation();
++          break;
++        case So at Gui@RenderAreaP::DUMPSCENEGRAPH:  // "dumpiv"
++          PRIVATE(this)->dumpScenegraph();
++          break;
++        case So at Gui@RenderAreaP::DUMPCAMERAS:  // "cameras"
++          PRIVATE(this)->dumpCameras();
++          break;
++        case So at Gui@RenderAreaP::OFFSCREENGRAB:  // "osgrab"
++          PRIVATE(this)->offScreenGrab();
++          break;
++        default:
++          assert(FALSE && "unknown debug key sequence");
++          break;
++        }
++      }
++    }
++#endif // SO at GUI@_DEBUG
++
++    SbBool processed = this->processSoEvent(soevent);
++    if (processed) return;
++  }
++
++  inherited::processEvent(event);
++}
++
++// *************************************************************************
++
++// doc from parent
++SbBool 
++So at Gui@RenderArea::glScheduleRedraw(void)
++{
++  this->scheduleRedraw();
++  if (this->hasOverlayGLArea() && this->getOverlaySceneGraph()) {
++    this->scheduleOverlayRedraw();
++  }
++  return TRUE;
++}
++
++// *************************************************************************
++
++/*!
++  This method posts and processes an SoEvent object to the
++  So at Gui@RenderArea-based component and returns the result value from the
++  event handler.  This is a synchronous operation.
++*/
++SbBool
++So at Gui@RenderArea::sendSoEvent(const SoEvent * event)
++{
++  return this->processSoEvent(event);
++}
++
++// *************************************************************************
++
++#undef PRIVATE
++#undef PUBLIC
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiRenderArea.h.in
+@@ -0,0 +1,157 @@
++#ifndef SO at GUI@_RENDERAREA_H
++#define SO at GUI@_RENDERAREA_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/SbColor.h>
++#include <Inventor/SbViewportRegion.h>
++#include <Inventor/actions/SoGLRenderAction.h>
++#include <Inventor/SoSceneManager.h>
++
++#include <Inventor/@Gui@/So at Gui@GLWidget.h>
++
++class SbColor;
++class SoNode;
++class SoSelection;
++
++class So at Gui@Device;
++// So at Gui@RenderAreaP is only used in the "friend class" statement in
++// the class definition, so this shouldn't really be necessary. But
++// the OSF1/cxx compiler complains if it's left out.
++class So at Gui@RenderAreaP;
++
++typedef SbBool So at Gui@RenderAreaEventCB(void * closure, @EVENT@ event);
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@RenderArea : public So at Gui@GLWidget {
++  SO at GUI@_OBJECT_HEADER(So at Gui@RenderArea, So at Gui@GLWidget);
++
++public:
++  So at Gui@RenderArea(@WIDGET@ parent = NULL,
++                    const char * name = NULL,
++                    SbBool embed = TRUE,
++                    SbBool mouseInput = TRUE,
++                    SbBool keyboardInput = TRUE);
++  ~So at Gui@RenderArea();
++
++  virtual void setSceneGraph(SoNode * scene);
++  virtual SoNode * getSceneGraph(void);
++  void setOverlaySceneGraph(SoNode * scene);
++  SoNode * getOverlaySceneGraph(void);
++
++  void setBackgroundColor(const SbColor & color);
++  const SbColor & getBackgroundColor(void) const;
++  void setBackgroundIndex(int idx);
++  int getBackgroundIndex(void) const;
++  void setOverlayBackgroundIndex(int idx);
++  int getOverlayBackgroundIndex(void) const;
++  void setColorMap(int start, int num, const SbColor * colors);
++  void setOverlayColorMap(int start, int num, const SbColor * colors);
++  void setViewportRegion(const SbViewportRegion & newRegion);
++  const SbViewportRegion & getViewportRegion(void) const;
++  void setTransparencyType(SoGLRenderAction::TransparencyType type);
++  SoGLRenderAction::TransparencyType getTransparencyType(void) const;
++  void setAntialiasing(SbBool smoothing, int numPasses);
++  void getAntialiasing(SbBool & smoothing, int & numPasses) const;
++  void setClearBeforeRender(SbBool enable, SbBool zbEnable = TRUE);
++  SbBool isClearBeforeRender(void) const;
++  SbBool isClearZBufferBeforeRender(void) const;
++  void setClearBeforeOverlayRender(SbBool enable);
++  SbBool isClearBeforeOverlayRender(void) const;
++  void setAutoRedraw(SbBool enable);
++  SbBool isAutoRedraw(void) const;
++  void setRedrawPriority(uint32_t priority);
++  uint32_t getRedrawPriority(void) const;
++  static uint32_t getDefaultRedrawPriority(void);
++  void render(void);
++  void renderOverlay(void);
++  void scheduleRedraw(void);
++  void scheduleOverlayRedraw(void);
++  void redrawOnSelectionChange(SoSelection * selection);
++  void redrawOverlayOnSelectionChange(SoSelection * selection);
++  void setEventCallback(So at Gui@RenderAreaEventCB * func, void * user = NULL);
++  void setSceneManager(SoSceneManager * manager);
++  SoSceneManager * getSceneManager(void) const;
++  void setOverlaySceneManager(SoSceneManager * manager);
++  SoSceneManager * getOverlaySceneManager(void) const;
++  void setGLRenderAction(SoGLRenderAction * action);
++  SoGLRenderAction * getGLRenderAction(void) const;
++  void setOverlayGLRenderAction(SoGLRenderAction * action);
++  SoGLRenderAction * getOverlayGLRenderAction(void) const;
++
++  SbBool sendSoEvent(const SoEvent * event);
++
++  void registerDevice(So at Gui@Device * device);
++  void unregisterDevice(So at Gui@Device * device);
++
++
++protected:
++  So at Gui@RenderArea(@WIDGET@ parent,
++                    const char * name,
++                    SbBool embed,
++                    SbBool mouseInput,
++                    SbBool keyboardInput,
++                    SbBool build);
++
++  virtual void redraw(void);
++  virtual void actualRedraw(void);
++  virtual void redrawOverlay(void);
++  virtual void actualOverlayRedraw(void);
++
++  virtual SbBool processSoEvent(const SoEvent * const event);
++  virtual void processEvent(@EVENT@ event);
++  virtual void initGraphic(void);
++  virtual void initOverlayGraphic(void);
++  virtual void sizeChanged(const SbVec2s & size);
++  virtual void widgetChanged(@WIDGET@ widget);
++  virtual void afterRealizeHook(void);
++
++  @WIDGET@ buildWidget(@WIDGET@ parent);
++
++  virtual const char * getDefaultWidgetName(void) const;
++  virtual const char * getDefaultTitle(void) const;
++  virtual const char * getDefaultIconTitle(void) const;
++
++  virtual SbBool glScheduleRedraw(void);
++
++private:
++  class So at Gui@RenderAreaP * pimpl;
++  friend class So at Gui@RenderAreaP;
++};
++
++// *************************************************************************
++
++#endif // ! SO at GUI@_RENDERAREA_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiDevice.cpp.in
+@@ -0,0 +1,293 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// This file contains common sourcecode and documentation for the
++// So[Gui]Device classes, in template form.
++
++/*!
++  \class So at Gui@Device So at Gui@Device.h Inventor/@Gui@/devices/So at Gui@Device.h
++  \brief The So at Gui@Device class is the base class for the translation devices.
++  \ingroup devices
++
++  The So at Gui@ device classes provide glue functionality for
++  translating native GUI events from the underlying toolkit to
++  Inventor scenegraph SoEvent events.
++
++  The device classes are mainly of interest to application programmers
++  when writing extensions for new types of devices, and seldom in
++  other contexts -- so they can most often be ignored.
++*/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/@Gui@/devices/So at Gui@Device.h>
++#include <Inventor/@Gui@/devices/So at Gui@DeviceP.h>
++#include <Inventor/SbPList.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/events/SoEvent.h>
++
++#include <Inventor/@Gui@/devices/So at Gui@InputFocus.h>
++#include <Inventor/@Gui@/devices/So at Gui@Keyboard.h>
++#include <Inventor/@Gui@/devices/So at Gui@Mouse.h>
++
++#ifdef HAVE_JOYSTICK_LINUX
++#include <Inventor/@Gui@/devices/So at Gui@LinuxJoystick.h>
++#endif // HAVE_JOYSTICK_LINUX
++
++#define PRIVATE(p) (p->pimpl)
++#define PUBLIC(p) (p->pub)
++
++// *************************************************************************
++
++/*!
++  \fn So at Gui@Device::So at Gui@Device(void)
++  Constructor.  Protected to only enable invocation from derived device
++  classes.
++*/
++/*!
++  \fn So at Gui@Device::~So at Gui@Device()
++  Public virtual destructor.
++*/
++
++/*!
++  \fn void So at Gui@Device::enable(@WIDGET@ widget, So at Gui@EventHandler * handler, void * closure)
++
++  This method will enable the device for the widget.
++
++  \a handler is invoked with the \a closure argument when an event
++  occur in \a widget.
++*/
++
++/*!
++  \fn void So at Gui@Device::disable(@WIDGET@ widget, So at Gui@EventHandler * handler, void * closure)
++
++  This method will disable the handler for the device.
++*/
++
++/*!
++  \fn const SoEvent * So at Gui@Device::translateEvent(@EVENT@ event)
++
++  This method translates from native events to Open Inventor SoEvent
++  events.
++*/
++
++/*!
++  \fn void So at Gui@Device::invokeHandlers(@EVENT@ event)
++
++  Invoke all handlers registered with So at Gui@Device::addEventHandler().
++*/
++
++// *************************************************************************
++
++SO at GUI@_OBJECT_ABSTRACT_SOURCE(So at Gui@Device);
++
++// *************************************************************************
++
++/*!
++  This function initializes the type system for all the So at Gui@
++  device classes.  It is called indirectly when calling
++  So at Gui@::init(), so the application programmer doesn't have to
++  bother with it.
++*/
++void
++So at Gui@Device::initClasses(void)
++{
++  So at Gui@Device::initClass();
++  So at Gui@InputFocus::initClass();
++  So at Gui@Keyboard::initClass();
++  So at Gui@Mouse::initClass();
++#ifdef HAVE_JOYSTICK_LINUX
++  So at Gui@LinuxJoystick::initClass();
++#endif // HAVE_JOYSTICK_LINUX
++}
++
++// *************************************************************************
++
++/*!
++  This method sets the cached size of the window the device is
++  "attached" to.
++*/
++void
++So at Gui@Device::setWindowSize(const SbVec2s size)
++{
++  PRIVATE(this)->widgetsize = size;
++}
++
++/*!
++  This method returns the cached window size.
++*/
++SbVec2s
++So at Gui@Device::getWindowSize(void) const
++{
++  return PRIVATE(this)->widgetsize;
++}
++
++// *************************************************************************
++
++/*!
++  This method fills in the position information of \a event,
++  translating the coordinates into the correct coordinate system.
++*/
++void
++So at Gui@Device::setEventPosition(SoEvent * event, int x, int y) const
++{
++  SoGuiDeviceP::lasteventposition = SbVec2s(x, y);
++  event->setPosition(SbVec2s(x, PRIVATE(this)->widgetsize[1] - y - 1));
++}
++
++/*!
++  Returns last event position that was set with
++  So at Gui@Device::setEventPosition().
++ */
++SbVec2s
++So at Gui@Device::getLastEventPosition(void)
++{
++  return SoGuiDeviceP::lasteventposition;
++}
++
++// *************************************************************************
++
++/*!
++  Stores an event \a handler for the \a widget, which can later be
++  invoked with So at Gui@Device::invokeHandlers(). Used by extension
++  device types.
++ */
++void
++So at Gui@Device::addEventHandler(@WIDGET@ widget,
++                               So at Gui@EventHandler * handler,
++                               void * closure)
++{
++  PRIVATE(this)->addEventHandler(widget, handler, closure);
++}
++
++/*!
++  Remove a \a handler registered with So at Gui@Device::addEventHandler().
++ */
++void
++So at Gui@Device::removeEventHandler(@WIDGET@ widget,
++                                  So at Gui@EventHandler * handler,
++                                  void * closure)
++{
++  PRIVATE(this)->removeEventHandler(widget, handler, closure);
++}
++
++// *************************************************************************
++
++#ifndef DOXYGEN_SKIP_THIS
++
++// Remaining code is for the internal, private hidden implementation
++// class.
++
++SbVec2s SoGuiDeviceP::lasteventposition;
++
++struct SoGuiDevicePHandlerInfo {
++  @WIDGET@ widget;
++  So at Gui@EventHandler * handler;
++  void * closure;
++};
++
++SoGuiDeviceP::SoGuiDeviceP(So at Gui@Device * p)
++{
++  PUBLIC(this) = p;
++  this->handlers = NULL;
++  this->widgetsize = SbVec2s(0, 0);
++}
++
++SoGuiDeviceP::~SoGuiDeviceP()
++{
++  if (this->handlers) {
++    for (int i = 0; i < this->handlers->getLength(); i++) {
++      SoGuiDevicePHandlerInfo * info =
++        (SoGuiDevicePHandlerInfo *) (*this->handlers)[i];
++      delete info;
++    }
++    delete this->handlers;
++  }
++}
++
++void
++SoGuiDeviceP::addEventHandler(@WIDGET@ widget,
++                              So at Gui@EventHandler * handler,
++                              void * closure)
++{
++  if (this->handlers == NULL) { this->handlers = new SbPList; }
++  SoGuiDevicePHandlerInfo * info = new SoGuiDevicePHandlerInfo;
++  info->widget = widget;
++  info->handler = handler;
++  info->closure = closure;
++  this->handlers->append(info);
++}
++
++void
++SoGuiDeviceP::removeEventHandler(@WIDGET@ widget,
++                                 So at Gui@EventHandler * handler,
++                                 void * closure)
++{
++  if (this->handlers) {
++    for (int i = 0; i < this->handlers->getLength(); i++) {
++      SoGuiDevicePHandlerInfo * info =
++        (SoGuiDevicePHandlerInfo *) (*this->handlers)[i];
++      if ((info->widget == widget) && (info->handler == handler) &&
++           (info->closure == closure)) {
++        delete info;
++        this->handlers->remove(i);
++        return;
++      }
++    }
++  }
++#if SO at GUI@_DEBUG
++  SoDebugError::post("SoGuiDeviceP::removeEventHandler",
++                     "tried to remove nonexisting handler");
++#endif // SO at GUI@_DEBUG
++}
++
++void
++SoGuiDeviceP::invokeHandlers(HandlerCB * cb, @EVENT@ event)
++{
++  if (this->handlers) {
++    for (int i = 0; i < this->handlers->getLength(); i++) {
++      SoGuiDevicePHandlerInfo * info =
++        (SoGuiDevicePHandlerInfo *) (*this->handlers)[i];
++      cb(info->handler, info->widget, event, info->closure);
++    }
++  }
++}
++
++#endif // DOXYGEN_SKIP_THIS
++
++#undef PRIVATE
++#undef PUBLIC
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiDevice.h.in
+@@ -0,0 +1,106 @@
++#ifndef SO at GUI@_DEVICE_H
++#define SO at GUI@_DEVICE_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// *************************************************************************
++//
++// Toolkit-specific typedef and include(s). Put these before any Coin
++// and/or So at Gui@ includes, in case there are any dependency bugs in
++// the underlying native toolkit set of include files versus the
++// compiler environment's include files.
++
++#include <Inventor/@Gui@/So at Gui@Basic.h> // Contains __COIN_SO at GUI@__ define.
++
++#ifdef __COIN_SOQT__
++#include <qevent.h>
++typedef void So at Gui@EventHandler(@WIDGET@, void *, @EVENT@, bool *);
++#endif // __COIN_SOQT__
++#ifdef __COIN_SOXT__
++#include <X11/Intrinsic.h>
++typedef void So at Gui@EventHandler(@WIDGET@, XtPointer, XEvent *, Boolean *);
++#endif // __COIN_SOXT__
++#ifdef __COIN_SOGTK__
++#include <gtk/gtk.h>
++typedef gint So at Gui@EventHandler(@WIDGET@, @EVENT@, gpointer);
++#endif // __COIN_SOGTK__
++#ifdef __COIN_SOWIN__
++#include <windows.h>
++typedef LRESULT So at Gui@EventHandler(@WIDGET@, UINT, WPARAM, LPARAM);
++#endif // __COIN_SOWIN__
++
++// *************************************************************************
++
++#include <Inventor/SbLinear.h>
++#include <Inventor/@Gui@/So at Gui@Object.h>
++
++class SoEvent;
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@Device : public So at Gui@Object {
++  SO at GUI@_OBJECT_ABSTRACT_HEADER(So at Gui@Device, So at Gui@Object);
++
++public:
++  virtual ~So at Gui@Device();
++
++  virtual void enable(@WIDGET@ w, So at Gui@EventHandler * handler, void * closure) = 0;
++  virtual void disable(@WIDGET@ w, So at Gui@EventHandler * handler, void * closure) = 0;
++
++  virtual const SoEvent * translateEvent(@EVENT@ event) = 0;
++
++  void setWindowSize(const SbVec2s size);
++  SbVec2s getWindowSize(void) const;
++
++  static void initClasses(void);
++
++protected:
++  So at Gui@Device(void);
++
++  void setEventPosition(SoEvent * event, int x, int y) const;
++  static SbVec2s getLastEventPosition(void);
++
++  void addEventHandler(@WIDGET@, So at Gui@EventHandler *, void *);
++  void removeEventHandler(@WIDGET@, So at Gui@EventHandler *, void *);
++  void invokeHandlers(@EVENT@ event);
++
++private:
++  class So at Gui@DeviceP * pimpl;
++  friend class So at Gui@DeviceP;
++};
++
++// *************************************************************************
++
++#endif // !SO at GUI@_DEVICE_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiDeviceP.h.in
+@@ -0,0 +1,76 @@
++#ifndef SOGUI_DEVICEP_H
++#define SOGUI_DEVICEP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/@Gui@/devices/So at Gui@Device.h>
++
++// *************************************************************************
++
++class SoGuiDeviceP {
++
++public:
++  SoGuiDeviceP(So at Gui@Device * p);
++  virtual ~SoGuiDeviceP();
++
++  void addEventHandler(@WIDGET@ widget,
++                       So at Gui@EventHandler * handler,
++                       void * closure);
++  void removeEventHandler(@WIDGET@ widget,
++                          So at Gui@EventHandler * handler,
++                          void * closure);
++
++  typedef SbBool HandlerCB(So at Gui@EventHandler * handler,
++                           @WIDGET@ widget,
++                           @EVENT@ event,
++                           void * handlerclosure);
++
++  void invokeHandlers(HandlerCB * cb, @EVENT@ event);
++
++  SbPList * handlers;
++  static SbVec2s lasteventposition;
++  SbVec2s widgetsize;
++
++private:
++  class So at Gui@Device * pub;
++};
++
++// *************************************************************************
++
++#endif // !SOGUI_DEVICEP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiInputFocus.cpp.in
+@@ -0,0 +1,102 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/*!
++  \class So at Gui@InputFocus So at Gui@InputFocus.h Inventor/@Gui@/devices/So at Gui@InputFocus.h
++  \brief The So at Gui@InputFocus class is an abstraction for widget focus events as an input device.
++  \ingroup devices
++
++  This device class is a "virtual device" which can be used to get
++  events when the mouse pointer enters or leaves a specific widget.
++*/
++
++// *************************************************************************
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/@Gui@/devices/So at Gui@InputFocus.h>
++#include <Inventor/@Gui@/devices/SoGuiInputFocusP.h>
++
++// *************************************************************************
++
++SO at GUI@_OBJECT_SOURCE(So at Gui@InputFocus);
++
++// *************************************************************************
++
++/*!
++  \enum So at Gui@InputFocus::Events
++
++  Bit-wise enumeration over events handled by the So at Gui@InputFocus
++  device class.  Used in the So at Gui@InputFocus constructor.
++*/
++
++/*!
++  \var So at Gui@InputFocus::Events So at Gui@InputFocus::ENTER_WINDOW
++
++  Maskbit for receiving events when focus comes to a widget.
++*/
++
++/*!
++  \var So at Gui@InputFocus::Events So at Gui@InputFocus::LEAVE_WINDOW
++
++  Maskbit for receiving events when focus leaves a widget.
++*/
++
++/*!
++  \var So at Gui@InputFocus::Events So at Gui@InputFocus::ALL_EVENTS
++
++  Combined bitmask for all possible events.
++*/
++
++/*!
++  \fn So at Gui@InputFocus::So at Gui@InputFocus(int mask)
++
++  Constructor. The \a mask specifies which focus-related events to
++  handle. Others will just be ignored.
++*/
++
++// *************************************************************************
++
++SoGuiInputFocusP::SoGuiInputFocusP(So at Gui@InputFocus * p)
++{
++  this->pub = p;
++}
++
++SoGuiInputFocusP::~SoGuiInputFocusP()
++{
++}
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiInputFocus.h.in
+@@ -0,0 +1,70 @@
++#ifndef SO at GUI@_INPUTFOCUS_H
++#define SO at GUI@_INPUTFOCUS_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/devices/So at Gui@Device.h>
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@InputFocus : public So at Gui@Device {
++  SO at GUI@_OBJECT_HEADER(So at Gui@InputFocus, So at Gui@Device);
++
++public:
++  enum Events {
++    ENTER_WINDOW = 1 << 0,
++    LEAVE_WINDOW = 1 << 1,
++    ALL_EVENTS   = ENTER_WINDOW | LEAVE_WINDOW
++  };
++
++  So at Gui@InputFocus(int mask = ALL_EVENTS);
++  virtual ~So at Gui@InputFocus();
++
++  virtual void enable(@WIDGET@ widget, So at Gui@EventHandler * handler, void * closure);
++  virtual void disable(@WIDGET@ widget, So at Gui@EventHandler * handler, void * closure);
++
++  virtual const SoEvent * translateEvent(@EVENT@ event);
++
++private:
++  class So at Gui@InputFocusP * pimpl;
++  friend class SoGuiInputFocusP;
++  friend class So at Gui@InputFocusP;
++};
++
++#define SO_ at GUI@_ALL_FOCUS_EVENTS So at Gui@InputFocus::ALL_EVENTS;
++
++// *************************************************************************
++
++#endif // ! SO at GUI@_INPUTFOCUS_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiInputFocusP.h.in
+@@ -0,0 +1,57 @@
++#ifndef SOGUI_INPUTFOCUSP_H
++#define SOGUI_INPUTFOCUSP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++// *************************************************************************
++
++class SoGuiInputFocusP {
++public:
++  SoGuiInputFocusP(class So at Gui@InputFocus * p);
++  ~SoGuiInputFocusP();
++
++  int eventmask;
++
++protected:
++  class So at Gui@InputFocus * pub;
++};
++
++// *************************************************************************
++
++#endif // ! SOGUI_INPUTFOCUSP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiKeyboard.cpp.in
+@@ -0,0 +1,112 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/*!
++  \class So at Gui@Keyboard So at Gui@Keyboard.h Inventor/@Gui@/devices/So at Gui@Keyboard.h
++  \brief The So at Gui@Keyboard class is the keyboard input device abstraction.
++  \ingroup devices
++
++  The So at Gui@Keyboard class is the glue between native keyboard
++  handling and keyboard interaction with the Inventor scenegraph.
++
++  All components derived from the So at Gui@RenderArea have got an
++  So at Gui@Keyboard device attached by default.
++*/
++
++// *************************************************************************
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/@Gui@/devices/So at Gui@Keyboard.h>
++#include <Inventor/@Gui@/devices/SoGuiKeyboardP.h>
++#include <Inventor/events/SoKeyboardEvent.h>
++
++// *************************************************************************
++
++SO at GUI@_OBJECT_SOURCE(So at Gui@Keyboard);
++
++// *************************************************************************
++
++/*!
++  \enum So at Gui@Keyboard::Events
++  Enumeration over supported event types.
++*/
++
++/*!
++  \var So at Gui@Keyboard::Events So at Gui@Keyboard::KEY_PRESS
++  Maskbit for a keyboard button press event.
++*/
++
++/*!
++  \var So at Gui@Keyboard::Events So at Gui@Keyboard::KEY_RELEASE
++  Maskbit for a keyboard button release event.
++*/
++
++/*!
++  \var So at Gui@Keyboard::Events So at Gui@Keyboard::ALL_EVENTS
++  Combined bitmask for all possible events.
++*/
++
++/*!
++  \fn So at Gui@Keyboard::So at Gui@Keyboard(int mask)
++
++  Constructor. The \a mask specifies which keyboard-related events to
++  handle. Others will just be ignored.
++*/
++
++/*!
++  \fn So at Gui@Keyboard::~So at Gui@Keyboard()
++
++  Destructor.
++*/
++
++// *************************************************************************
++
++#ifndef DOXYGEN_SKIP_THIS
++
++SoGuiKeyboardP::SoGuiKeyboardP(void)
++{
++  this->kbdevent = new SoKeyboardEvent;
++}
++
++SoGuiKeyboardP::~SoGuiKeyboardP()
++{
++  delete this->kbdevent;
++}
++
++#endif // !DOXYGEN_SKIP_THIS
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiKeyboard.h.in
+@@ -0,0 +1,72 @@
++#ifndef SO at GUI@_KEYBOARD_H
++#define SO at GUI@_KEYBOARD_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/devices/So at Gui@Device.h>
++
++class SoKeyboardEvent;
++
++// *************************************************************************
++
++#define SO_ at GUI@_ALL_KEYBOARD_EVENTS So at Gui@Keyboard::ALL
++
++class SO at GUI@_DLL_API So at Gui@Keyboard : public So at Gui@Device {
++  SO at GUI@_OBJECT_HEADER(So at Gui@Keyboard, So at Gui@Device);
++
++public:
++  enum Events {
++    KEY_PRESS = 0x01,
++    KEY_RELEASE = 0x02,
++    ALL_EVENTS = KEY_PRESS | KEY_RELEASE
++  };
++
++  So at Gui@Keyboard(int eventmask = ALL_EVENTS);
++  virtual ~So at Gui@Keyboard(void);
++
++  virtual void enable(@WIDGET@ widget, So at Gui@EventHandler * handler, void * closure);
++  virtual void disable(@WIDGET@ widget, So at Gui@EventHandler * handler, void * closure);
++
++  virtual const SoEvent * translateEvent(@EVENT@ event);
++
++private:
++  class So at Gui@KeyboardP * pimpl;
++  friend class So at Gui@KeyboardP;
++  friend class SoGuiKeyboardP;
++};
++
++// *************************************************************************
++
++#endif // ! SO at GUI@_KEYBOARD_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiKeyboardP.h.in
+@@ -0,0 +1,57 @@
++#ifndef SOGUI_KEYBOARDP_H
++#define SOGUI_KEYBOARDP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++class SoKeyboardEvent;
++
++// *************************************************************************
++
++class SoGuiKeyboardP {
++public:
++  SoGuiKeyboardP(void);
++  ~SoGuiKeyboardP();
++
++  int eventmask;
++  SoKeyboardEvent * kbdevent;
++};
++
++// *************************************************************************
++
++#endif // ! SOGUI_KEYBOARDP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiMouse.cpp.in
+@@ -0,0 +1,174 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/@Gui@/devices/So at Gui@Mouse.h>
++#include <Inventor/@Gui@/devices/SoGuiMouseP.h>
++#include <Inventor/events/SoMouseButtonEvent.h>
++#include <Inventor/events/SoLocation2Event.h>
++
++/*!
++  \class So at Gui@Mouse So at Gui@Mouse.h Inventor/@Gui@/devices/So at Gui@Mouse.h
++  \brief The So at Gui@Mouse class is the mouse input device abstraction.
++  \ingroup devices
++
++  The So at Gui@Mouse class is the glue between native mouse handling and
++  mouse interaction in the Inventor scenegraph.
++
++  All components derived from the So at Gui@RenderArea have got an
++  So at Gui@Mouse device attached by default.
++
++  One important note for application programmers: our mappings to
++  SoMouseButtonEvent::BUTTON2 and SoMouseButtonEvent::BUTTON3 do not
++  match the mappings in SGI's InventorXt library or TGS's SoWin
++  library for 3-button mice. They map mouse buttons like this:
++
++  <ul>
++  <li>left button: SoMouseButtonEvent::BUTTON1</li>
++  <li>middle button: SoMouseButtonEvent::BUTTON2</li>
++  <li>right button: SoMouseButtonEvent::BUTTON3</li>
++  </ul>
++
++  While in this SIM So at Gui@ library the mappings are:
++
++  <ul>
++  <li>left button: SoMouseButtonEvent::BUTTON1</li>
++  <li>middle button: SoMouseButtonEvent::BUTTON3</li>
++  <li>right button: SoMouseButtonEvent::BUTTON2</li>
++  </ul>
++
++  This is a conscious design decision we've made.  The reason is that
++  BUTTON2 should be the right mouse button whether you have a 2-button
++  mouse or a 3-button mouse.
++*/
++
++// *************************************************************************
++
++SO at GUI@_OBJECT_SOURCE(So at Gui@Mouse);
++
++// *************************************************************************
++
++/*!
++  \enum So at Gui@Mouse::Events
++  Enumeration over supported mouse events.
++*/
++/*!
++  \var So at Gui@Mouse::Events So at Gui@Mouse::BUTTON_PRESS
++  Maskbit for mousebutton press events.
++*/
++/*!
++  \var So at Gui@Mouse::Events So at Gui@Mouse::BUTTON_RELEASE
++  Maskbit for mousebutton release events.
++*/
++/*!
++  \var So at Gui@Mouse::Events So at Gui@Mouse::POINTER_MOTION
++  Maskbit for mousepointer motion events.
++*/
++/*!
++  \var So at Gui@Mouse::Events So at Gui@Mouse::BUTTON_MOTION
++  Maskbit for mousepointer motion events with one or more mousebuttons
++  pressed.
++*/
++/*!
++  \var So at Gui@Mouse::Events So at Gui@Mouse::ALL_EVENTS
++
++  Mask which includes all the maskbits in the enum (ie use this to
++  signal interest in all kinds of events for the mouse device).
++*/
++
++// *************************************************************************
++
++/*!
++  \fn So at Gui@Mouse::So at Gui@Mouse(int mask)
++
++  Constructor. The \a mask argument should contain the set of
++  So at Gui@Mouse::Events one is interested in tracking.
++*/
++
++/*!
++  \fn So at Gui@Mouse::~So at Gui@Mouse()
++  Destructor.
++*/
++
++/*!
++  \fn const SoEvent * So at Gui@Mouse::translateEvent(@EVENT@ event)
++
++  Translates a native event from the underlying toolkit into a generic
++  event.
++
++  This is then returned in the form of an instance of a subclass of
++  the Inventor API's SoEvent class, either an SoMouseButtonEvent or an
++  SoLocation2Event, depending on whether the native event is a
++  mousebutton press / release, or a mousecursor movement event.
++
++  The mapping of the mousebuttons upon generation of
++  SoMouseButtonEvent events will be done as follows:
++
++  <ul>
++  <li>left mousebutton: SoMouseButtonEvent::BUTTON1</li>
++  <li>right mousebutton: SoMouseButtonEvent::BUTTON2</li>
++  <li>middle mousebutton, if available: SoMouseButtonEvent::BUTTON3</li>
++  <li>forward motion on a wheel mouse: SoMouseButtonEvent::BUTTON4</li>
++  <li>backward motion on a wheel mouse: SoMouseButtonEvent::BUTTON5</li>
++  </ul>
++
++  Note that the rightmost mousebutton will always map to
++  SoMouseButtonEvent::BUTTON2, even on a 3-button mouse.
++*/
++
++// *************************************************************************
++
++#ifndef DOXYGEN_SKIP_THIS
++
++SoGuiMouseP::SoGuiMouseP(So at Gui@Mouse * p)
++{
++  this->pub = p;
++
++  // Allocate system-neutral event objects once and reuse.
++  this->buttonevent = new SoMouseButtonEvent;
++  this->locationevent = new SoLocation2Event;
++}
++
++SoGuiMouseP::~SoGuiMouseP()
++{
++  delete this->buttonevent;
++  delete this->locationevent;
++}
++
++#endif // !DOXYGEN_SKIP_THIS
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiMouse.h.in
+@@ -0,0 +1,74 @@
++#ifndef SO at GUI@_MOUSE_H
++#define SO at GUI@_MOUSE_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/devices/So at Gui@Device.h>
++
++class SoMouseButtonEvent;
++class SoLocation2Event;
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@Mouse : public So at Gui@Device {
++  SO at GUI@_OBJECT_HEADER(So at Gui@Mouse, So at Gui@Device);
++
++public:
++  enum Events {
++    BUTTON_PRESS    = 0x01,
++    BUTTON_RELEASE  = 0x02,
++    POINTER_MOTION  = 0x04,
++    BUTTON_MOTION   = 0x08,
++
++    ALL_EVENTS = BUTTON_PRESS | BUTTON_RELEASE | POINTER_MOTION | BUTTON_MOTION
++  };
++
++  So at Gui@Mouse(int eventmask = ALL_EVENTS);
++  virtual ~So at Gui@Mouse(void);
++
++  virtual void enable(@WIDGET@ widget, So at Gui@EventHandler * handler, void * closure);
++  virtual void disable(@WIDGET@ widget, So at Gui@EventHandler * handler, void * closure);
++
++  virtual const SoEvent * translateEvent(@EVENT@ event);
++
++private:
++  class So at Gui@MouseP * pimpl;
++  friend class So at Gui@MouseP;
++  friend class SoGuiMouseP;
++};
++
++// *************************************************************************
++
++#endif // ! SO at GUI@_MOUSE_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiMouseP.h.in
+@@ -0,0 +1,62 @@
++#ifndef SOGUI_MOUSEP_H
++#define SOGUI_MOUSEP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++class SoMouseButtonEvent;
++class SoLocation2Event;
++
++// *************************************************************************
++
++class SoGuiMouseP {
++public:
++  SoGuiMouseP(class So at Gui@Mouse * p);
++  ~SoGuiMouseP();
++
++  SoMouseButtonEvent * buttonevent;
++  SoLocation2Event * locationevent;
++  int eventmask;
++
++protected:
++  class So at Gui@Mouse * pub;
++};
++
++// *************************************************************************
++
++#endif // ! SOGUI_MOUSEP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiSpacenavDevice.cpp.in
+@@ -0,0 +1,74 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/misc/SoBasic.h>
++#include <Inventor/@Gui@/devices/So at Gui@SpacenavDevice.h>
++
++SO at GUI@_OBJECT_SOURCE(So at Gui@SpacenavDevice);
++
++So at Gui@SpacenavDevice::So at Gui@SpacenavDevice()
++{
++}
++
++
++So at Gui@SpacenavDevice::~So at Gui@SpacenavDevice()
++{
++}
++
++
++void
++So at Gui@SpacenavDevice::enable(HWND w, So at Gui@EventHandler * handler, void * closure)
++{
++}
++
++
++void 
++So at Gui@SpacenavDevice::disable(HWND w, So at Gui@EventHandler * handler, void * closure)
++{
++}
++
++  
++const SoEvent * 
++So at Gui@SpacenavDevice::translateEvent(MSG * inevent)
++{
++  return NULL;
++}
++
++
++
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiSpacenavDevice.h.in
+@@ -0,0 +1,61 @@
++#ifndef SO at GUI@_SPACENAVDEVICE_H
++#define SO at GUI@_SPACENAVDEVICE_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/@Gui@/devices/So at Gui@Device.h>
++
++class SOWIN_DLL_API So at Gui@SpacenavDevice : public So at Gui@Device {
++  SOWIN_OBJECT_HEADER(So at Gui@SpacenavDevice, So at Gui@Device);
++
++ public:
++  So at Gui@SpacenavDevice();
++  virtual ~So at Gui@SpacenavDevice();
++
++  virtual void enable(HWND w, So at Gui@EventHandler * handler, void * closure);
++  virtual void disable(HWND w, So at Gui@EventHandler * handler, void * closure);
++  virtual const SoEvent * translateEvent(MSG * event);
++
++ private:
++  class So at Gui@SpacenavDeviceP * pimpl;
++  friend class So at Gui@SpacenavDeviceP;
++};
++
++
++#endif // !SO at GUI@_SPACENAVDEVICE_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/docs/README
+@@ -0,0 +1,2 @@
++This directory contains common development-related documentation for
++all So* toolkits.
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/docs/api-wish-list.txt
+@@ -0,0 +1,59 @@
++WHAT'S THIS?
++============
++
++This document describes API extension ideas where we think the So*
++libraries lacks necessary functionality.
++
++The listing of an API change or API extension in this file does not
++mean that it will be implemented, only that it will be considered for
++implementation.
++
++Ideas for this wish list can be submitted by anyone.
++
++
++THE WISH LIST
++=============
++
++* Mouse control configuration API
++  2001-12-17  write-up by <mortene at sim.no>
++  [upwards compatible extension]
++
++  A request from coin-discuss: it should be possible for application
++  programmers to change the default mousebutton combination
++  configurations for dragging / zooming / panning for the
++  So*ExaminerViewer, and likewise for the other viewer classes.
++
++
++* Doubleclick handling
++  2002-01-16  Morten Eriksen  <mortene at sim.no>
++
++  The So*Mouse device class has no notion of doubleclick events, which
++  complicates matters for application programmers who wants to offer
++  those to the end-user for interaction. They can of course just
++  compare timings between single clicks, but those numbers will then
++  have to be compared to the murky details of the underlying GUI
++  toolkit manually to make it blend in with the rest (end-users tend
++  to configure their OS doubleclick interval setting to wildly
++  differing values, in my experience).
++
++  To fix this API deficiency, we would probably also need to add to
++  the API of Coin's SoMouseEvent, which have no concept of
++  doubleclicks either.
++
++
++* API for the viewer scenegraph
++  2002-05-28  Peder Blekken  <pederb at sim.no>, writeup by <mortene at sim.no>
++
++  Parts of the viewer scenegraphs are interesting to get access to for
++  the application programmers, to configure certain viewer parameters
++  like color settings in wireframe / point / bbox rendering styles,
++  etc.
++
++  At the same time, we want to avoid bloating the So at Gui@*Viewer APIs
++  with all these simple accessor (set*()/get*()) methods.
++
++  Peder's idea for a solution: we can hide the actual scenegraph
++  structure within an extension nodekit class, setting up a separate
++  public API on this nodekit. This would give us implementation
++  hiding, full control over what gets exposed, and no additional bloat
++  on the So at Gui@*Viewer classes.
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/docs/doxygen/footer.html
+@@ -0,0 +1,6 @@
++<hr noshade>
++<p align="right">Copyright &copy by <a href="http://www.kongsberg.com/kogt">Kongsberg Oil & Gas Technologies</a>. All rights reserved.</p>
++<address style="align: right;"><small>
++Generated on $datetime for $projectname by <a href="http://www.doxygen.org/">Doxygen</a> $doxygenversion.</small></address>
++</body>
++</html>
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/docs/doxygen/header.html
+@@ -0,0 +1,16 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
++<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
++<title>$title</title>
++<link href="stylesheet.css" rel="stylesheet" type="text/css">
++</head><body><table width="100%">
++<tr>
++  <td>
++    <img src="Coin_logo.png" alt="Coin Logo">
++  </td>
++  <td align="right">
++    <a href="http://www.coin3d.org/">http://www.coin3d.org/</a><br />
++    <a href="http://www.kongsberg.com/kogt/">http://www.kongsberg.com/kogt/</a><br />
++  </td>
++</tr>
++</table>
++<hr noshade />
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/docs/doxygen/stylesheet.css
+@@ -0,0 +1,362 @@
++BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
++	font-family: Geneva, Arial, Helvetica, sans-serif;
++}
++BODY,TD {
++       font-size: 90%;
++}
++H1 {
++	text-align: center;
++       font-size: 160%;
++}
++H2 {
++       font-size: 120%;
++}
++H3 {
++       font-size: 100%;
++}
++IMG {
++       border: 0;
++}
++CAPTION { font-weight: bold }
++DIV.qindex {
++	width: 100%;
++	background-color: #e8eef2;
++	border: 1px solid #84b0c7;
++	text-align: center;
++	margin: 2px;
++	padding: 2px;
++	line-height: 140%;
++}
++DIV.nav {
++	width: 100%;
++	background-color: #e8eef2;
++	border: 1px solid #84b0c7;
++	text-align: center;
++	margin: 2px;
++	padding: 2px;
++	line-height: 140%;
++}
++DIV.navtab {
++       background-color: #e8eef2;
++       border: 1px solid #84b0c7;
++       text-align: center;
++       margin: 2px;
++       margin-right: 15px;
++       padding: 2px;
++}
++TD.navtab {
++       font-size: 70%;
++}
++A.qindex {
++       text-decoration: none;
++       font-weight: bold;
++       color: #1A419D;
++}
++A.qindex:visited {
++       text-decoration: none;
++       font-weight: bold;
++       color: #1A419D
++}
++A.qindex:hover {
++	text-decoration: none;
++	background-color: #ddddff;
++}
++A.qindexHL {
++	text-decoration: none;
++	font-weight: bold;
++	background-color: #6666cc;
++	color: #ffffff;
++	border: 1px double #9295C2;
++}
++A.qindexHL:hover {
++	text-decoration: none;
++	background-color: #6666cc;
++	color: #ffffff;
++}
++A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff }
++A.el { text-decoration: none; font-weight: bold }
++A.elRef { font-weight: bold }
++A.code:link { text-decoration: none; font-weight: normal; color: #0000FF}
++A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF}
++A.codeRef:link { font-weight: normal; color: #0000FF}
++A.codeRef:visited { font-weight: normal; color: #0000FF}
++A:hover { text-decoration: none; background-color: #f2f2ff }
++DL.el { margin-left: -1cm }
++.fragment {
++       font-family: monospace, fixed;
++       font-size: 95%;
++}
++PRE.fragment {
++	border: 1px solid #CCCCCC;
++	background-color: #f5f5f5;
++	margin-top: 4px;
++	margin-bottom: 4px;
++	margin-left: 2px;
++	margin-right: 8px;
++	padding-left: 6px;
++	padding-right: 6px;
++	padding-top: 4px;
++	padding-bottom: 4px;
++}
++DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px }
++
++DIV.groupHeader {
++       margin-left: 16px;
++       margin-top: 12px;
++       margin-bottom: 6px;
++       font-weight: bold;
++}
++DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% }
++BODY {
++	background: white;
++	color: black;
++	margin-right: 20px;
++	margin-left: 20px;
++}
++TD.indexkey {
++	background-color: #e8eef2;
++	font-weight: bold;
++	padding-right  : 10px;
++	padding-top    : 2px;
++	padding-left   : 10px;
++	padding-bottom : 2px;
++	margin-left    : 0px;
++	margin-right   : 0px;
++	margin-top     : 2px;
++	margin-bottom  : 2px;
++	border: 1px solid #CCCCCC;
++}
++TD.indexvalue {
++	background-color: #e8eef2;
++	font-style: italic;
++	padding-right  : 10px;
++	padding-top    : 2px;
++	padding-left   : 10px;
++	padding-bottom : 2px;
++	margin-left    : 0px;
++	margin-right   : 0px;
++	margin-top     : 2px;
++	margin-bottom  : 2px;
++	border: 1px solid #CCCCCC;
++}
++TR.memlist {
++   background-color: #f0f0f0; 
++}
++P.formulaDsp { text-align: center; }
++IMG.formulaDsp { }
++IMG.formulaInl { vertical-align: middle; }
++SPAN.keyword       { color: #008000 }
++SPAN.keywordtype   { color: #604020 }
++SPAN.keywordflow   { color: #e08000 }
++SPAN.comment       { color: #800000 }
++SPAN.preprocessor  { color: #806020 }
++SPAN.stringliteral { color: #002080 }
++SPAN.charliteral   { color: #008080 }
++.mdescLeft {
++       padding: 0px 8px 4px 8px;
++	font-size: 80%;
++	font-style: italic;
++	background-color: #FAFAFA;
++	border-top: 1px none #E0E0E0;
++	border-right: 1px none #E0E0E0;
++	border-bottom: 1px none #E0E0E0;
++	border-left: 1px none #E0E0E0;
++	margin: 0px;
++}
++.mdescRight {
++       padding: 0px 8px 4px 8px;
++	font-size: 80%;
++	font-style: italic;
++	background-color: #FAFAFA;
++	border-top: 1px none #E0E0E0;
++	border-right: 1px none #E0E0E0;
++	border-bottom: 1px none #E0E0E0;
++	border-left: 1px none #E0E0E0;
++	margin: 0px;
++}
++.memItemLeft {
++	padding: 1px 0px 0px 8px;
++	margin: 4px;
++	border-top-width: 1px;
++	border-right-width: 1px;
++	border-bottom-width: 1px;
++	border-left-width: 1px;
++	border-top-color: #E0E0E0;
++	border-right-color: #E0E0E0;
++	border-bottom-color: #E0E0E0;
++	border-left-color: #E0E0E0;
++	border-top-style: solid;
++	border-right-style: none;
++	border-bottom-style: none;
++	border-left-style: none;
++	background-color: #FAFAFA;
++	font-size: 80%;
++}
++.memItemRight {
++	padding: 1px 8px 0px 8px;
++	margin: 4px;
++	border-top-width: 1px;
++	border-right-width: 1px;
++	border-bottom-width: 1px;
++	border-left-width: 1px;
++	border-top-color: #E0E0E0;
++	border-right-color: #E0E0E0;
++	border-bottom-color: #E0E0E0;
++	border-left-color: #E0E0E0;
++	border-top-style: solid;
++	border-right-style: none;
++	border-bottom-style: none;
++	border-left-style: none;
++	background-color: #FAFAFA;
++	font-size: 80%;
++}
++.memTemplItemLeft {
++	padding: 1px 0px 0px 8px;
++	margin: 4px;
++	border-top-width: 1px;
++	border-right-width: 1px;
++	border-bottom-width: 1px;
++	border-left-width: 1px;
++	border-top-color: #E0E0E0;
++	border-right-color: #E0E0E0;
++	border-bottom-color: #E0E0E0;
++	border-left-color: #E0E0E0;
++	border-top-style: none;
++	border-right-style: none;
++	border-bottom-style: none;
++	border-left-style: none;
++	background-color: #FAFAFA;
++	font-size: 80%;
++}
++.memTemplItemRight {
++	padding: 1px 8px 0px 8px;
++	margin: 4px;
++	border-top-width: 1px;
++	border-right-width: 1px;
++	border-bottom-width: 1px;
++	border-left-width: 1px;
++	border-top-color: #E0E0E0;
++	border-right-color: #E0E0E0;
++	border-bottom-color: #E0E0E0;
++	border-left-color: #E0E0E0;
++	border-top-style: none;
++	border-right-style: none;
++	border-bottom-style: none;
++	border-left-style: none;
++	background-color: #FAFAFA;
++	font-size: 80%;
++}
++.memTemplParams {
++	padding: 1px 0px 0px 8px;
++	margin: 4px;
++	border-top-width: 1px;
++	border-right-width: 1px;
++	border-bottom-width: 1px;
++	border-left-width: 1px;
++	border-top-color: #E0E0E0;
++	border-right-color: #E0E0E0;
++	border-bottom-color: #E0E0E0;
++	border-left-color: #E0E0E0;
++	border-top-style: solid;
++	border-right-style: none;
++	border-bottom-style: none;
++	border-left-style: none;
++       color: #606060;
++	background-color: #FAFAFA;
++	font-size: 80%;
++}
++.search     { color: #003399;
++              font-weight: bold;
++}
++FORM.search {
++              margin-bottom: 0px;
++              margin-top: 0px;
++}
++INPUT.search { font-size: 75%;
++               color: #000080;
++               font-weight: normal;
++               background-color: #e8eef2;
++}
++TD.tiny      { font-size: 75%;
++}
++a {
++	color: #1A41A8;
++}
++a:visited {
++	color: #2A3798;
++}
++.dirtab { padding: 4px;
++          border-collapse: collapse;
++          border: 1px solid #84b0c7;
++}
++TH.dirtab { background: #e8eef2;
++            font-weight: bold;
++}
++HR { height: 1px;
++     border: none;
++     border-top: 1px solid black;
++}
++
++/* Style for detailed member documentation */
++.memtemplate {
++  font-size: 80%;
++  color: #606060;
++  font-weight: normal;
++  margin-left: 3px;
++} 
++.memnav { 
++  background-color: #e8eef2;
++  border: 1px solid #84b0c7;
++  text-align: center;
++  margin: 2px;
++  margin-right: 15px;
++  padding: 2px;
++}
++.memitem {
++  padding: 4px;
++  background-color: #eef3f5;
++  border-width: 1px;
++  border-style: solid;
++  border-color: #dedeee;
++  -moz-border-radius: 8px 8px 8px 8px;
++}
++.memname {
++  white-space: nowrap;
++  font-weight: bold;
++}
++.memdoc{
++  padding-left: 10px;
++}
++.memproto {
++  background-color: #d5e1e8;
++  width: 100%;
++  border-width: 1px;
++  border-style: solid;
++  border-color: #84b0c7;
++  font-weight: bold;
++  -moz-border-radius: 8px 8px 8px 8px;
++}
++.paramkey {
++  text-align: right;
++}
++.paramtype {
++  white-space: nowrap;
++}
++.paramname {
++  color: #602020;
++  font-style: italic;
++  white-space: nowrap;
++}
++/* End Styling for detailed member documentation */
++
++/* for the tree view */
++.ftvtree {
++	font-family: sans-serif;
++	margin:0.5em;
++}
++.directory { font-size: 9pt; font-weight: bold; }
++.directory h3 { margin: 0px; margin-top: 1em; font-size: 11pt; }
++.directory > h3 { margin-top: 0; }
++.directory p { margin: 0px; white-space: nowrap; }
++.directory div { display: none; margin: 0px; }
++.directory img { vertical-align: -30%; }
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/docs/todo.txt
+@@ -0,0 +1,24 @@
++WHAT'S THIS?
++============
++
++This document contains a list of various common deficiencies in the
++So*-libraries that are larger in scope than just simple API additions
++/ changes (see the api-wish-list.txt file for that kind of "mini"
++projects).
++
++
++
++COMMON STUFF TO FIX IN THE SO* LIBRARIES
++========================================
++
++
++* Cross-platform spaceball and joystick device support
++  2002-01-03  Morten Eriksen  <mortene at sim.no>
++
++  Requested by Coin PEL holder Daniel Soto Alvarez.
++
++  We already have support for spaceballs and joysticks implemented for
++  some of the So*-libraries.
++
++  For spaceball SDKs, see
++  <URL:http://www.3dconnexion.com/software/sdk/>.
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/editors/SoGuiColorEditor.cpp.in
+@@ -0,0 +1,647 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// FIXME: overload the getClassName() type functions
++
++#include <Inventor/SbPList.h>
++#include <Inventor/SoSceneManager.h>
++#include <Inventor/fields/SoSFColor.h>
++#include <Inventor/fields/SoMFColor.h>
++#include <Inventor/fields/SoMFUInt32.h>
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoTexture2.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++#include <Inventor/actions/SoGLRenderAction.h>
++
++#include <Inventor/@Gui@/SoAny.h>
++#include <Inventor/@Gui@/nodes/SoGuiViewportFix.h>
++#include <Inventor/@Gui@/nodes/SoGuiColorEditor.h>
++#include <Inventor/@Gui@/editors/So at Gui@ColorEditor.h>
++
++/*
++#include <Inventor/@Gui@/nodes/SoGuiPane.h>
++#include <Inventor/@Gui@/nodes/SoGuiClickCounter.h>
++#include <Inventor/@Gui@/nodes/SoGuiSlider1.h>
++#include <Inventor/@Gui@/nodes/SoGuiSlider2.h>
++*/
++
++
++/*!
++  \class So at Gui@ColorEditor Inventor/@Gui@/editors/So at Gui@ColorEditor.h
++  \brief The So at Gui@ColorEditor class is a GUI component for interactively
++  editing color fields.
++*/
++
++/*!
++  \enum So at Gui@ColorEditor::Sliders
++*/
++
++/*!
++  \val So at Gui@ColorEditor::NONE
++*/
++
++/*!
++  \val So at Gui@ColorEditor::INTENSITY
++*/
++
++/*!
++  \val So at Gui@ColorEditor::RGB
++*/
++
++/*!
++  \val So at Gui@ColorEditor::HSV
++*/
++
++/*!
++  \val So at Gui@ColorEditor::RGB_V
++*/
++
++/*!
++  \val So at Gui@ColorEditor::RGB_HSV
++*/
++
++/*!
++  \enum So at Gui@ColorEditor::UpdateFrequency
++*/
++
++/*!
++  \val So at Gui@ColorEditor::CONTINUOUS
++*/
++
++/*!
++  \val So at Gui@ColorEditor::AFTER_ACCEPT
++*/
++
++// *************************************************************************
++
++static const SbBool SGI_ATTACHMENT_REF_COMPATIBILITY = TRUE;
++
++enum Attachment {
++  DETACHED,
++  SFCOLOR,
++  MFCOLOR,
++  MFUINT32
++};
++
++// Name suffix used to avoid conflict with private part of the ColorEditor
++// node kit.
++
++class ColorEditorComponent {
++public:
++  So at Gui@ColorEditor * api;
++
++  static const char * superscene[];
++
++  SbPList callbacks;
++
++  // attachment is redundant - the existence of the field sensor, and the
++  // field type it is attached to is all the info needed really
++  Attachment attachment;
++  // the field pointers can actually be dropped since the sensor will have
++  // that info
++  SoSFColor * sfcolor;
++  SoMFColor * mfcolor;
++  SoMFUInt32 * mfuint32;
++  int mfindex;
++
++  SoFieldSensor * editor_sensor;
++  static void editor_update_cb(void * closure, SoSensor * sensor);
++
++  SoFieldSensor * attachment_sensor;
++  static void attachment_update_cb(void * closure, SoSensor * sensor);
++
++  SoGuiColorEditor * editor;
++
++  void invokeColorChangeCallbacks(void);
++  SbBool colorsEqual(void);
++};
++
++// *************************************************************************
++
++SO at GUI@_OBJECT_SOURCE(So at Gui@ColorEditor);
++
++#define PRIVATE(obj) ((ColorEditorComponent *) ((So at Gui@ColorEditor *) obj)->internals)
++#define PUBLIC(obj) (((ColorEditorComponent *) obj)->api)
++
++So at Gui@ColorEditor::So at Gui@ColorEditor(@WIDGET@ parent, const char * name, SbBool embed)
++  : inherited(parent, name, embed)
++{
++  this->internals = (void *) new ColorEditorComponent;
++  PRIVATE(this)->api = this;
++
++  PRIVATE(this)->attachment = DETACHED;
++  PRIVATE(this)->sfcolor = NULL;
++  PRIVATE(this)->sfcolor = NULL;
++  PRIVATE(this)->mfcolor = NULL;
++  PRIVATE(this)->mfuint32 = NULL;
++  PRIVATE(this)->mfindex = 0;
++
++  PRIVATE(this)->editor_sensor = NULL;
++  PRIVATE(this)->attachment_sensor = NULL;
++
++  PRIVATE(this)->editor = NULL;
++
++  this->setSize(SbVec2s(320, 256));
++
++  SoNode * root = SoAny::loadSceneGraph(ColorEditorComponent::superscene);
++  assert(root != NULL);
++  assert(root->isOfType(SoSeparator::getClassTypeId()));
++  SoSeparator * superscene = (SoSeparator *) root;
++
++  PRIVATE(this)->editor = new SoGuiColorEditor;
++  superscene->addChild(PRIVATE(this)->editor);
++  this->setSceneGraph(superscene);
++
++  PRIVATE(this)->attachment_sensor = new SoFieldSensor(ColorEditorComponent::attachment_update_cb, PRIVATE(this));
++
++  PRIVATE(this)->editor_sensor = new SoFieldSensor(ColorEditorComponent::editor_update_cb, PRIVATE(this));
++  PRIVATE(this)->editor_sensor->attach(&(PRIVATE(this)->editor->color));
++}
++
++So at Gui@ColorEditor::~So at Gui@ColorEditor(void)
++{
++  if ( PRIVATE(this)->attachment != DETACHED ) this->detach();
++  delete PRIVATE(this)->attachment_sensor;
++  delete PRIVATE(this)->editor_sensor;
++  this->setSceneGraph(NULL);
++  ColorEditorComponent * instance = PRIVATE(this);
++  delete instance;
++}
++
++/*!
++  Attach the editor to a color single field.  Any existing attachments are
++  detached.
++
++  The node argument defaults to NULL and is ignored.  It is part of the
++  argument list for compatibility reasons.
++*/
++
++void
++So at Gui@ColorEditor::attach(SoSFColor * color, SoBase * node)
++{
++  if ( PRIVATE(this)->attachment != DETACHED ) this->detach();
++  if ( color != NULL ) {
++    if ( SGI_ATTACHMENT_REF_COMPATIBILITY ) {
++      SoFieldContainer * container = color->getContainer();
++      if ( container != NULL ) container->ref();
++    }
++    PRIVATE(this)->attachment = SFCOLOR;
++    PRIVATE(this)->sfcolor = color;
++    assert(PRIVATE(this)->attachment_sensor != NULL);
++    PRIVATE(this)->attachment_sensor->attach(color);
++    PRIVATE(this)->editor->color.setValue(color->getValue());
++  }
++}
++
++/*!
++  Attach the editor to an element in a color multi field.  Any existing attachments are
++  detached.
++  
++  The node argument defaults to NULL and is ignored.  It is part of the
++  argument list for compatibility reasons.
++*/
++
++void
++So at Gui@ColorEditor::attach(SoMFColor * color, int idx, SoBase * node)
++{
++  if ( PRIVATE(this)->attachment != DETACHED ) this->detach();
++  if ( color != NULL ) {
++    if ( SGI_ATTACHMENT_REF_COMPATIBILITY ) {
++      SoFieldContainer * container = color->getContainer();
++      if ( container != NULL ) container->ref();
++    }
++    PRIVATE(this)->attachment = MFCOLOR;
++    PRIVATE(this)->mfcolor = color;
++    PRIVATE(this)->mfindex = idx;
++    assert(PRIVATE(this)->attachment_sensor != NULL);
++    PRIVATE(this)->attachment_sensor->attach(color);
++    PRIVATE(this)->editor->color.setValue(color->operator[](idx));
++  }
++}
++
++/*!
++  Attach the editor to an element in an uint32 multi field.  The field
++  is assumed to be of the RGBA packed color format.  Any existing attachments are
++  detached.
++  
++  The node argument defaults to NULL and is ignored.  It is part of the
++  argument list for compatibility reasons.
++*/
++
++void
++So at Gui@ColorEditor::attach(SoMFUInt32 * color, int idx, SoBase * node)
++{
++  if ( PRIVATE(this)->attachment != DETACHED ) this->detach();
++  if ( color != NULL ) {
++    if ( SGI_ATTACHMENT_REF_COMPATIBILITY ) {
++      SoFieldContainer * container = color->getContainer();
++      if ( container != NULL ) container->ref();
++    }
++    PRIVATE(this)->attachment = MFUINT32;
++    PRIVATE(this)->mfuint32 = color;
++    PRIVATE(this)->mfindex = idx;
++    assert(PRIVATE(this)->attachment_sensor != NULL);
++    PRIVATE(this)->attachment_sensor->attach(color);
++    SbColor col;
++    float transparency = 0.0f;
++    col.setPackedValue(color->operator[](idx), transparency);
++    PRIVATE(this)->editor->color.setValue(col);
++  }
++}
++
++/*!
++  Detach the editor from the field it is attached to.
++*/
++
++void
++So at Gui@ColorEditor::detach(void)
++{
++  if ( PRIVATE(this)->attachment != DETACHED ) {
++    SoField * field = NULL;
++    switch ( PRIVATE(this)->attachment ) {
++    case SFCOLOR:
++      field = PRIVATE(this)->sfcolor;
++      PRIVATE(this)->sfcolor = NULL;
++      break;
++    case MFCOLOR:
++      field = PRIVATE(this)->mfcolor;
++      PRIVATE(this)->mfcolor = NULL;
++      break;
++    case MFUINT32:
++      field = PRIVATE(this)->mfuint32;
++      PRIVATE(this)->mfuint32 = NULL;
++      break;
++    case DETACHED:
++    default:
++      assert(0 && "impossible switch case");
++      break;
++    }
++    assert(field != NULL);
++    if ( field != NULL ) {
++      assert(PRIVATE(this)->attachment_sensor != NULL);
++      PRIVATE(this)->attachment_sensor->detach();
++      if ( SGI_ATTACHMENT_REF_COMPATIBILITY ) {
++        SoFieldContainer * container = field->getContainer();
++        if ( container != NULL ) container->unref();
++      }
++    }
++    PRIVATE(this)->attachment = DETACHED;
++  }
++}
++
++/*!
++  This method returns whether or not the editor is currently attached to a field.
++*/
++
++SbBool
++So at Gui@ColorEditor::isAttached(void) const
++{
++  return (PRIVATE(this)->attachment != DETACHED) ? TRUE : FALSE;
++}
++
++/*
++  Add a callback to be triggered when the color value is changed.
++
++  \sa So at Gui@ColorEditor::setUpdateFrequency
++*/
++
++void
++So at Gui@ColorEditor::addColorChangedCallback(So at Gui@ColorEditorCB * callback, void * closure)
++{
++  PRIVATE(this)->callbacks.append((void *) callback);
++  PRIVATE(this)->callbacks.append(closure);
++}
++
++/*!
++  Remove all color change callbacks matching the given arguments.
++*/
++
++void
++So at Gui@ColorEditor::removeColorChangedCallback(So at Gui@ColorEditorCB * callback, void * closure)
++{
++  const int len = PRIVATE(this)->callbacks.getLength();
++  int i;
++  for ( i = 0; i < len; i += 2 ) {
++    So at Gui@ColorEditorCB * cb =
++      (So at Gui@ColorEditorCB *) PRIVATE(this)->callbacks[i];
++    if ( (callback == cb) && (closure == PRIVATE(this)->callbacks[i+1]) ) {
++      PRIVATE(this)->callbacks.remove(i+1);
++      PRIVATE(this)->callbacks.remove(i);
++      i -= 2;
++    }
++  }
++}
++
++/*!
++  Set a new color value.
++
++  If the field value gets updated, the color change callbacks will be triggered.
++*/
++
++void
++So at Gui@ColorEditor::setColor(const SbColor & color)
++{
++  // callbacks are triggered on the sensor rebound...
++  switch ( PRIVATE(this)->attachment ) {
++  case DETACHED:
++    break;
++  case SFCOLOR:
++    assert(PRIVATE(this)->sfcolor != NULL);
++    if ( PRIVATE(this)->sfcolor->getValue() != color ) {
++      PRIVATE(this)->sfcolor->setValue(color);
++    }
++    break;
++  case MFCOLOR:
++    assert(PRIVATE(this)->mfcolor != NULL);
++    if ( PRIVATE(this)->mfcolor->operator[](PRIVATE(this)->mfindex) != color ) {
++      PRIVATE(this)->mfcolor->set1Value(PRIVATE(this)->mfindex, color);
++    }
++    break;
++  case MFUINT32:
++    assert(PRIVATE(this)->mfuint32 != NULL);
++    if ( PRIVATE(this)->mfuint32->operator[](PRIVATE(this)->mfindex) != color.getPackedValue() ) {
++      PRIVATE(this)->mfuint32->set1Value(PRIVATE(this)->mfindex, color.getPackedValue());
++    }
++    break;
++  }
++  assert(PRIVATE(this)->editor != NULL);
++  PRIVATE(this)->editor->color.setValue(color);
++}
++
++/*!
++  Get the current color value.
++*/
++
++const SbColor &
++So at Gui@ColorEditor::getColor(void) const
++{
++  assert(PRIVATE(this)->editor != NULL);
++  return PRIVATE(this)->editor->color.getValue();
++}
++
++/*!
++  Not implemented yet.
++
++  Sets whether or not the color sliders should be in WYSIWYG mode.
++  When enabled, the color backgrounds in the sliders will be updated to
++  reflect what the color will be, taken all color components into account.
++  When disabled, the color backgrounds only reflect the component the slider
++  controls.
++*/
++
++void
++So at Gui@ColorEditor::setWYSIWYG(SbBool enable)
++{
++  assert(PRIVATE(this)->editor != NULL);
++  PRIVATE(this)->editor->wysiwyg.setValue(enable);
++}
++
++/*!
++  Returns whether or not the editor sliders are in WYSIWYG mode.
++*/
++
++SbBool
++So at Gui@ColorEditor::isWYSIWYG(void) const
++{
++  assert(PRIVATE(this)->editor != NULL);
++  return PRIVATE(this)->editor->wysiwyg.getValue();
++}
++
++/*!
++  Sets which if the slider sets is to be used.
++
++  \sa So at Gui@ColorEditor::Sliders
++*/
++
++void
++So at Gui@ColorEditor::setCurrentSliders(So at Gui@ColorEditor::Sliders which)
++{
++  assert(PRIVATE(this)->editor != NULL);
++  PRIVATE(this)->editor->sliders.setValue((So at Gui@ColorEditor::Sliders) which);
++}
++
++/*!
++  Returns which slider sets is being used.
++
++  \sa So at Gui@ColorEditor::Sliders
++*/
++
++So at Gui@ColorEditor::Sliders
++So at Gui@ColorEditor::getCurrentSliders(void) const
++{
++  assert(PRIVATE(this)->editor != NULL);
++  return (So at Gui@ColorEditor::Sliders) PRIVATE(this)->editor->sliders.getValue();
++}
++
++/*!
++  Sets the update-frequency setting, which affects when color change callbacks
++  will be triggered.
++
++  \sa So at Gui@ColorEditor::UpdateFrequency
++*/
++
++void
++So at Gui@ColorEditor::setUpdateFrequency(So at Gui@ColorEditor::UpdateFrequency freq)
++{
++  assert(PRIVATE(this)->editor != NULL);
++  PRIVATE(this)->editor->update.setValue((So at Gui@ColorEditor::UpdateFrequency) freq);
++}
++
++/*!
++  Returns the update-frequency setting.
++
++  \sa So at Gui@ColorEditor::UpdateFrequency
++*/
++
++So at Gui@ColorEditor::UpdateFrequency
++So at Gui@ColorEditor::getUpdateFrequency(void) const
++{
++  assert(PRIVATE(this)->editor != NULL);
++  return (So at Gui@ColorEditor::UpdateFrequency) PRIVATE(this)->editor->update.getValue();
++}
++
++SoGuiColorEditor *
++So at Gui@ColorEditor::getEditor(void) const
++{
++  return PRIVATE(this)->editor;
++}
++
++// *************************************************************************
++
++const char *
++So at Gui@ColorEditor::getDefaultWidgetName(void) const
++{
++  static const char widgetName[] = "So at Gui@ColorEditor";
++  return widgetName;
++}
++
++const char *
++So at Gui@ColorEditor::getDefaultTitle(void) const
++{
++  static const char title[] = "ColorEditor";
++  return title;
++}
++
++const char *
++So at Gui@ColorEditor::getDefaultIconTitle(void) const
++{
++  static const char iconTitle[] = "ColEd";
++  return iconTitle;
++}
++
++// *************************************************************************
++// ColorEditorComponent
++// *************************************************************************
++
++const char *
++ColorEditorComponent::superscene[] =
++{
++  "#Inventor V2.1 ascii",
++  "",
++  "Separator {",
++  "  DirectionalLight { direction 0 0 -1 color 1 1 1 intensity 0.8 }",
++  "  OrthographicCamera { }",
++  "  DEF viewportfix SoGuiViewportFix { }",
++  "  Material { ambientColor 0.8 0.8 0.8 }",
++  "}",
++  NULL
++};
++
++// *************************************************************************
++
++void
++ColorEditorComponent::invokeColorChangeCallbacks(void)
++{
++  int i;
++  for ( i = 0; i < this->callbacks.getLength(); i += 2 ) {
++    So at Gui@ColorEditorCB * callback = (So at Gui@ColorEditorCB *) this->callbacks[i];
++    void * closure = this->callbacks[i+1];
++    callback(closure, &this->editor->color.getValue());
++  }
++}
++
++SbBool
++ColorEditorComponent::colorsEqual(void)
++{
++  SbColor attachmentColor;
++  switch ( this->attachment ) {
++  case SFCOLOR:
++    assert(this->sfcolor != NULL);
++    attachmentColor = this->sfcolor->getValue();
++    break;
++  case MFCOLOR:
++    assert(this->mfcolor != NULL);
++    attachmentColor = this->mfcolor->operator[](this->mfindex);
++    break;
++  case MFUINT32:
++    assert(this->mfcolor != NULL);
++    do {
++      float transparency = 0.0f;
++      attachmentColor.setPackedValue(this->mfuint32->operator[](this->mfindex), transparency);
++    } while ( FALSE );
++    break;
++  case DETACHED:
++  default:
++    return TRUE;
++  }
++  return (attachmentColor == this->editor->color.getValue()) ? TRUE : FALSE;
++}
++
++void
++ColorEditorComponent::attachment_update_cb(void * closure, SoSensor * sensor)
++{
++  assert(closure != NULL);
++  ColorEditorComponent * me = (ColorEditorComponent *) closure;
++  if ( me->colorsEqual() ) return;
++
++  switch ( me->attachment ) {
++  case SFCOLOR:
++    assert(me->sfcolor != NULL);
++    me->editor->color.setValue(me->sfcolor->getValue());
++    break;
++  case MFCOLOR:
++    assert(me->mfcolor != NULL);
++    me->editor->color.setValue(me->mfcolor->operator[](me->mfindex));
++    break;
++  case MFUINT32:
++    assert(me->mfcolor != NULL);
++    do {
++      SbColor color;
++      float transparency = 0.0f;
++      color.setPackedValue(me->mfuint32->operator[](me->mfindex), transparency);
++      me->editor->color.setValue(color);
++    } while ( FALSE );
++    break;
++  case DETACHED:
++  default:
++    break;
++  }
++}
++
++void
++ColorEditorComponent::editor_update_cb(void * closure, SoSensor * sensor)
++{
++  assert(closure != NULL);
++  ColorEditorComponent * me = (ColorEditorComponent *) closure;
++  if ( me->colorsEqual() ) return;
++
++  SbColor color = me->editor->color.getValue();
++
++  switch ( me->attachment ) {
++  case SFCOLOR:
++    assert(me->sfcolor != NULL);
++    me->sfcolor->setValue(color);
++    break;
++  case MFCOLOR:
++    assert(me->mfcolor != NULL);
++    me->mfcolor->set1Value(me->mfindex, color);
++    break;
++  case MFUINT32:
++    assert(me->mfuint32 != NULL);
++    me->mfuint32->set1Value(me->mfindex, color.getPackedValue());
++    break;
++  case DETACHED:
++  default:
++    break;
++  }
++
++  if ( me->editor->update.getValue() == SoGuiColorEditor::CONTINUOUS )
++    me->invokeColorChangeCallbacks();
++}
++
++// *************************************************************************
++
++#undef PRIVATE
++#undef PUBLIC
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/editors/SoGuiColorEditor.h.in
+@@ -0,0 +1,102 @@
++#ifndef COIN_SO at GUI@COLOREDITOR_H
++#define COIN_SO at GUI@COLOREDITOR_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/nodes/SoGuiColorEditor.h>
++#include <Inventor/@Gui@/So at Gui@RenderArea.h>
++
++typedef void So at Gui@ColorEditorCB(void * closure, const SbColor * color);
++        
++class SbColor;
++class SoSFColor;
++class SoMFColor;
++class SoMFUInt32;
++
++class So at Gui@ColorEditor : public So at Gui@RenderArea {
++  SO at GUI@_OBJECT_HEADER(So at Gui@ColorEditor, So at Gui@RenderArea);
++
++public:
++  So at Gui@ColorEditor(@WIDGET@ parent = NULL, const char * name = NULL, SbBool embed = TRUE);
++  ~So at Gui@ColorEditor(void);
++
++  enum Sliders {
++    NONE = SoGuiColorEditor::NONE, 
++    INTENSITY = SoGuiColorEditor::INTENSITY,
++    RGB = SoGuiColorEditor::RGB, 
++    HSV = SoGuiColorEditor::HSV, 
++    RGB_V = SoGuiColorEditor::RGB_V, 
++    RGB_HSV = SoGuiColorEditor::RGB_HSV
++  };
++  
++  enum UpdateFrequency {
++    CONTINUOUS = SoGuiColorEditor::CONTINUOUS,
++    AFTER_ACCEPT = SoGuiColorEditor::AFTER_ACCEPT
++  };
++  
++  void attach(SoSFColor * color, SoBase * node = NULL);
++  void attach(SoMFColor * color, int idx = 0, SoBase * node = NULL);
++  void attach(SoMFUInt32 * color, int idx = 0, SoBase * node = NULL);
++  void detach(void);
++  SbBool isAttached(void) const;
++  
++  void addColorChangedCallback(So at Gui@ColorEditorCB * cb, void * closure = NULL);
++  void removeColorChangedCallback(So at Gui@ColorEditorCB * cb, void * closure = NULL);
++  
++  void setColor(const SbColor & color);
++  const SbColor & getColor(void) const;
++  
++  void setWYSIWYG(SbBool enable);
++  SbBool isWYSIWYG(void) const;
++  
++  void setCurrentSliders(Sliders which);
++  Sliders getCurrentSliders(void) const;
++  
++  void setUpdateFrequency(UpdateFrequency freq);
++  UpdateFrequency getUpdateFrequency(void) const;
++
++  SoGuiColorEditor * getEditor(void) const;
++
++protected:
++  virtual const char * getDefaultWidgetName(void) const;
++  virtual const char * getDefaultTitle(void) const;
++  virtual const char * getDefaultIconTitle(void) const;
++
++private:
++  void * internals;
++
++};
++
++#endif // !COIN_SO at GUI@COLOREDITOR_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/editors/SoGuiMaterialEditor.cpp.in
+@@ -0,0 +1,356 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/SbPList.h>
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoMaterial.h>
++#include <Inventor/sensors/SoNodeSensor.h>
++#ifdef HAVE_SOVRMLMATERIAL
++#include <Inventor/VRMLnodes/SoVRMLMaterial.h>
++#endif // HAVE_SOVRMLMATERIAL
++
++#include <Inventor/@Gui@/SoAny.h>
++#include <Inventor/@Gui@/nodes/SoGuiMaterialEditor.h>
++#include <Inventor/@Gui@/editors/So at Gui@ColorEditor.h>
++#include <Inventor/@Gui@/editors/So at Gui@MaterialEditor.h>
++
++// *************************************************************************
++
++class MaterialEditorComponent {
++public:
++  MaterialEditorComponent(void);
++  ~MaterialEditorComponent(void);
++
++  So at Gui@MaterialEditor * api;
++
++  void constructor(void);
++
++  So at Gui@MaterialEditor::UpdateFrequency frequency;
++
++  SbPList * callbacks;
++  void invokeCallbacks(void);
++
++  SoNodeSensor * attachment;
++  SoMaterial * material;
++  SoGuiMaterialEditor * editor;
++
++  static SoGuiColorEditor * coloreditoropen_cb(void * closure);
++  static void coloreditorclose_cb(void * closure, SoGuiColorEditor * editor);
++  So at Gui@ColorEditor * coloreditor;
++
++  static SoSeparator * getSuperScene(void);
++  static SoNode * getSceneGraph(void);
++  static const char * superscene[];
++};
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((MaterialEditorComponent *) obj->internals)
++
++SO at GUI@_OBJECT_SOURCE(So at Gui@MaterialEditor);
++
++So at Gui@MaterialEditor::So at Gui@MaterialEditor(@WIDGET@ parent, const char * name, SbBool embed)
++  : inherited(parent, name, embed)
++{
++  this->internals = new MaterialEditorComponent;
++  PRIVATE(this)->api = this;
++  PRIVATE(this)->constructor();
++}
++
++So at Gui@MaterialEditor::So at Gui@MaterialEditor(@WIDGET@ parent, const char * const name, SbBool embed, SbBool build)
++: inherited(parent, name, embed)
++{
++  this->internals = new MaterialEditorComponent;
++  PRIVATE(this)->api = this;
++  PRIVATE(this)->constructor();
++}
++
++So at Gui@MaterialEditor::~So at Gui@MaterialEditor(void)
++{
++  assert(PRIVATE(this)->editor);
++  MaterialEditorComponent * obj = PRIVATE(this);
++  delete obj;
++}
++
++void
++So at Gui@MaterialEditor::attach(SoMaterial * material, int index)
++{
++  assert(PRIVATE(this)->editor);
++  PRIVATE(this)->editor->material.setValue(material);
++  PRIVATE(this)->editor->index.setValue(index);
++}
++
++void
++So at Gui@MaterialEditor::attach(SoVRMLMaterial * material)
++{
++  assert(PRIVATE(this)->editor);
++#ifdef HAVE_SOVRMLMATERIAL
++  PRIVATE(this)->editor->material.setValue(material);
++#else // !HAVE_SOVRMLMATERIAL
++  PRIVATE(this)->editor->material.setValue((SoNode *) material);
++#endif // !HAVE_SOVRMLMATERIAL
++}
++
++void
++So at Gui@MaterialEditor::detach(void)
++{
++  PRIVATE(this)->editor->material.setValue(NULL);
++}
++
++SbBool
++So at Gui@MaterialEditor::isAttached(void)
++{
++  assert(PRIVATE(this)->editor != NULL);
++  return (PRIVATE(this)->editor->material.getValue() != NULL) ? TRUE : FALSE;
++}
++
++void
++So at Gui@MaterialEditor::addMaterialChangedCallback(So at Gui@MaterialEditorCB * callback, void * closure)
++{
++  if ( PRIVATE(this)->callbacks == NULL )
++    PRIVATE(this)->callbacks = new SbPList;
++  PRIVATE(this)->callbacks->append((void *) callback);
++  PRIVATE(this)->callbacks->append(closure);
++}
++
++void
++So at Gui@MaterialEditor::removeMaterialChangedCallback(So at Gui@MaterialEditorCB * callback, void * closure)
++{
++  assert(PRIVATE(this)->callbacks);
++  int i;
++  for ( i = PRIVATE(this)->callbacks->getLength(); i > 0; i -= 2 ) {
++    So at Gui@MaterialEditorCB * cb = (So at Gui@MaterialEditorCB *) (*(PRIVATE(this)->callbacks))[i-2];
++    void * cl = (*(PRIVATE(this)->callbacks))[i-1];
++    if ( cb == callback && cl == closure ) {
++      PRIVATE(this)->callbacks->remove(i-1);
++      PRIVATE(this)->callbacks->remove(i-2);
++    }
++  }
++}
++
++void
++So at Gui@MaterialEditor::setUpdateFrequency(So at Gui@MaterialEditor::UpdateFrequency frequency)
++{
++  PRIVATE(this)->frequency = frequency;
++}
++
++So at Gui@MaterialEditor::UpdateFrequency
++So at Gui@MaterialEditor::getUpdateFrequency(void) const
++{
++  return PRIVATE(this)->frequency;
++}
++
++void
++So at Gui@MaterialEditor::setMaterial(const SoMaterial & material)
++{
++  PRIVATE(this)->material->ambientColor.setValue(material.ambientColor[0]);
++  PRIVATE(this)->material->diffuseColor.setValue(material.diffuseColor[0]);
++  PRIVATE(this)->material->specularColor.setValue(material.specularColor[0]);
++  PRIVATE(this)->material->emissiveColor.setValue(material.emissiveColor[0]);
++  PRIVATE(this)->material->shininess.setValue(material.shininess[0]);
++  PRIVATE(this)->material->transparency.setValue(material.transparency[0]);
++}
++
++void
++So at Gui@MaterialEditor::setMaterial(const SoVRMLMaterial & material)
++{
++#ifdef HAVE_SOVRMLMATERIAL
++  float h, s, v;
++  h = 0.0f;
++  s = 0.0f;
++  v = material.ambientIntensity.getValue();
++  SbColor ambient;
++  ambient.setHSVValue(h, s, v);
++  PRIVATE(this)->material->ambientColor.setValue(ambient);
++  PRIVATE(this)->material->diffuseColor.setValue(material.diffuseColor.getValue());
++  PRIVATE(this)->material->specularColor.setValue(material.specularColor.getValue());
++  PRIVATE(this)->material->emissiveColor.setValue(material.emissiveColor.getValue());
++  PRIVATE(this)->material->shininess.setValue(material.shininess.getValue());
++  PRIVATE(this)->material->transparency.setValue(material.transparency.getValue());
++#endif // HAVE_SOVRMLMATERIAL
++}
++
++const SoMaterial &
++So at Gui@MaterialEditor::getMaterial(void) const
++{
++  return *(PRIVATE(this)->material);
++}
++
++SbBool
++So at Gui@MaterialEditor::isAttachedVRML(void)
++{
++  SoNode * material = PRIVATE(this)->editor->material.getValue();
++#ifdef HAVE_SOVRMLMATERIAL
++  return (material && material->isOfType(SoVRMLMaterial::getClassTypeId())) ? TRUE : FALSE;
++#endif
++  return FALSE;
++}
++
++SoGuiMaterialEditor *
++So at Gui@MaterialEditor::getEditor(void) const
++{
++  assert(0);
++  return NULL;
++}
++
++// *************************************************************************
++
++const char *
++So at Gui@MaterialEditor::getDefaultWidgetName(void) const
++{
++  static const char widgetName[] = "So at Gui@MaterialEditor";
++  return widgetName;
++}
++
++const char *
++So at Gui@MaterialEditor::getDefaultTitle(void) const
++{
++  static const char title[] = "MaterialEditor";
++  return title;
++}
++
++const char *
++So at Gui@MaterialEditor::getDefaultIconTitle(void) const
++{
++  static const char iconTitle[] = "MatEd";
++  return iconTitle;
++}
++
++#undef PRIVATE
++
++// *************************************************************************
++// MaterialEditorComponent
++// *************************************************************************
++
++#define PUBLIC(obj)  (obj->api)
++
++const char *
++MaterialEditorComponent::superscene[] =
++{
++  "#Inventor V2.1 ascii",
++  "",
++  "Separator {",
++  "  DirectionalLight { direction 0 0 -1 color 1 1 1 intensity 0.8 }",
++  "  OrthographicCamera { }",
++  "  DEF viewportfix SoGuiViewportFix { }",
++  "  Material { ambientColor 0.8 0.8 0.8 }",
++  "}",
++  NULL
++};
++
++// *************************************************************************
++
++MaterialEditorComponent::MaterialEditorComponent(void)
++{
++  this->api = NULL;
++  this->attachment = NULL;
++  this->editor = NULL;
++  this->callbacks = NULL;
++  this->material = NULL;
++}
++
++MaterialEditorComponent::~MaterialEditorComponent(void)
++{
++  if ( this->attachment != NULL ) {
++    delete this->attachment;
++  }
++  if ( this->callbacks != NULL )
++    delete this->callbacks;
++}
++
++void
++MaterialEditorComponent::constructor(void)
++{
++  PUBLIC(this)->setSize(SbVec2s(550,300));
++  SoNode * scene = MaterialEditorComponent::getSceneGraph();
++  PUBLIC(this)->setSceneGraph(scene);
++  assert(scene->isOfType(SoSeparator::getClassTypeId()));
++  SoSeparator * sceneroot = (SoSeparator *) scene;
++  this->editor = (SoGuiMaterialEditor *) sceneroot->getChild(sceneroot->getNumChildren()-1);
++  assert(this->editor->isOfType(SoGuiMaterialEditor::getClassTypeId()));
++  this->material = this->editor->getSphereMaterialNode();
++  this->editor->setColorEditorCallbacks(MaterialEditorComponent::coloreditoropen_cb, MaterialEditorComponent::coloreditorclose_cb, this);
++}
++
++void
++MaterialEditorComponent::invokeCallbacks(void)
++{
++  // FIXME
++}
++
++SoSeparator *
++MaterialEditorComponent::getSuperScene(void)
++{
++  SoNode * root = SoAny::loadSceneGraph(MaterialEditorComponent::superscene);
++  assert(root != NULL);
++  assert(root->isOfType(SoSeparator::getClassTypeId()));
++  return (SoSeparator *) root;
++}
++
++SoNode *
++MaterialEditorComponent::getSceneGraph(void)
++{
++  SoSeparator * root = MaterialEditorComponent::getSuperScene();
++  assert(root != NULL);
++  // FIXME: route ViewportFix field value into editor
++  root->addChild(new SoGuiMaterialEditor);
++  return root;
++}
++
++SoGuiColorEditor *
++MaterialEditorComponent::coloreditoropen_cb(void * closure)
++{
++  MaterialEditorComponent * me = (MaterialEditorComponent *) closure;
++  me->coloreditor = new So at Gui@ColorEditor;
++  me->coloreditor->show();
++  return me->coloreditor->getEditor();
++}
++
++void
++MaterialEditorComponent::coloreditorclose_cb(void * closure, SoGuiColorEditor * editor)
++{
++  assert(closure);
++  MaterialEditorComponent * me = (MaterialEditorComponent *) closure;
++  me->coloreditor->hide();
++  delete me->coloreditor;
++  me->coloreditor = NULL;
++}
++
++#undef PUBLIC
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/editors/SoGuiMaterialEditor.h.in
+@@ -0,0 +1,94 @@
++#ifndef COIN_SO at GUI@MATERIALEDITOR_H
++#define COIN_SO at GUI@MATERIALEDITOR_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/nodes/SoGuiMaterialEditor.h>
++#include <Inventor/@Gui@/So at Gui@RenderArea.h>
++
++class SoMaterial;
++class SoVRMLMaterial;
++
++// *************************************************************************
++
++typedef void So at Gui@MaterialEditorCB(void * userdata, const SoMaterial * material);
++
++class SO at GUI@_DLL_API So at Gui@MaterialEditor : public So at Gui@RenderArea {
++  SO at GUI@_OBJECT_HEADER(So at Gui@MaterialEditor, So at Gui@RenderArea);
++
++public:
++  So at Gui@MaterialEditor(@WIDGET@ parent = NULL, const char * name = NULL, SbBool embed = TRUE);
++  ~So at Gui@MaterialEditor(void);
++
++  enum UpdateFrequency {
++    CONTINUOUS = SoGuiMaterialEditor::CONTINUOUS,
++    AFTER_ACCEPT = SoGuiMaterialEditor::AFTER_ACCEPT
++  };
++
++  void attach(SoMaterial * material, int index = 0);
++  void attach(SoVRMLMaterial * material);
++  void detach(void);
++  SbBool isAttached(void);
++
++  void addMaterialChangedCallback(
++    So at Gui@MaterialEditorCB * callback, void * closure = NULL);
++  void removeMaterialChangedCallback(
++    So at Gui@MaterialEditorCB * callback, void * closure = NULL);
++
++  void setUpdateFrequency(So at Gui@MaterialEditor::UpdateFrequency frequency);
++  So at Gui@MaterialEditor::UpdateFrequency getUpdateFrequency(void) const;
++
++  void setMaterial(const SoMaterial & material);
++  void setMaterial(const SoVRMLMaterial & material);
++  const SoMaterial & getMaterial(void) const;
++  SbBool isAttachedVRML(void);
++
++  SoGuiMaterialEditor * getEditor(void) const;
++
++protected:
++  So at Gui@MaterialEditor(@WIDGET@ parent, const char * const name, SbBool embed, SbBool build);
++
++  virtual const char * getDefaultWidgetName(void) const;
++  virtual const char * getDefaultTitle(void) const;
++  virtual const char * getDefaultIconTitle(void) const;
++
++private:
++  void * internals;
++
++}; // class So at Gui@MaterialEditor
++
++// *************************************************************************
++
++#endif // !COIN_SO at GUI@MATERIALEDITOR_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/engines/Engines.cpp.in
+@@ -0,0 +1,43 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/engines/SoGuiEngines.h>
++
++void
++SoGuiEngines::initClasses(void)
++{
++  SoGuiRadioGroup::initClass();
++  SoGuiFormat::initClass();
++}
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/engines/Engines.h.in
+@@ -0,0 +1,51 @@
++#ifndef COIN_SOGUIENGINES_H
++#define COIN_SOGUIENGINES_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif // !SO at GUI@_INTERNAL
++
++#include <Inventor/@Gui@/engines/SoGuiRadioGroup.h>
++#include <Inventor/@Gui@/engines/SoGuiFormat.h>
++
++class SoGuiEngines {
++public:
++  static void initClasses(void);
++
++};
++
++#endif // !COIN_SOGUIENGINES_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/engines/Format.cpp.in
+@@ -0,0 +1,84 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif // !SO at GUI@_INTERNAL
++
++#include <Inventor/SbString.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <stdio.h>
++
++#include <Inventor/@Gui@/engines/SoGuiFormat.h>
++
++void
++SoGuiFormat::initClass(void)
++{
++  SO_ENGINE_INIT_CLASS(SoGuiFormat, SoEngine, "Engine");
++}
++
++SO_ENGINE_SOURCE(SoGuiFormat);
++
++SoGuiFormat::SoGuiFormat(void)
++{
++  this->internals = NULL;
++
++  SO_ENGINE_CONSTRUCTOR(SoGuiFormat);
++
++  SO_ENGINE_ADD_INPUT(float1, (0.0f));
++  SO_ENGINE_ADD_INPUT(format, (""));
++
++  SO_ENGINE_ADD_OUTPUT(output, SoSFString);
++}
++
++SoGuiFormat::~SoGuiFormat(void)
++{
++}
++
++void
++SoGuiFormat::evaluate(void)
++{
++#ifdef __COIN__
++  SbString result;
++  result.sprintf(this->format.getValue().getString(), this->float1.getValue());
++#else // __COIN__
++  char buf[4096]; // FIXME: temporary workaround
++  sprintf(buf, this->format.getValue().getString(), this->float1.getValue());
++  SbString result = buf;
++#endif // ! __COIN__
++ 
++  // SoDebugError::postInfo("SoGuiFormat::evaluate", "%s", result.getString());
++  SO_ENGINE_OUTPUT(output, SoSFString, setValue(result));
++}
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/engines/Format.h.in
+@@ -0,0 +1,73 @@
++#ifndef COIN_SOGUIFORMAT_H
++#define COIN_SOGUIFORMAT_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif // !SO at GUI@_INTERNAL
++
++#include <Inventor/fields/SoSFString.h>
++#include <Inventor/fields/SoSFFloat.h>
++#include <Inventor/engines/SoSubEngine.h>
++#ifdef __COIN__
++#include <Inventor/engines/SoEngineOutput.h>
++#endif // __COIN__
++#include <Inventor/engines/SoEngine.h>
++
++class SoGuiFormat : public SoEngine {
++  typedef SoEngine inherited;
++  SO_ENGINE_HEADER(SoGuiFormat);
++
++public:
++  static void initClass(void);
++  SoGuiFormat(void);
++
++  SoSFFloat float1;
++
++  SoSFString format;
++
++  SoEngineOutput output;
++
++protected:
++  virtual ~SoGuiFormat(void);
++  virtual void evaluate(void);
++
++private:
++  void * internals;
++
++};
++
++#endif // !COIN_SOGUIFORMAT_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/engines/RadioGroup.cpp.in
+@@ -0,0 +1,122 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/engines/SoGuiRadioGroup.h>
++#include <assert.h>
++
++SO_ENGINE_SOURCE(SoGuiRadioGroup);
++
++void
++SoGuiRadioGroup::initClass(void)
++{
++  SO_ENGINE_INIT_CLASS(SoGuiRadioGroup, SoEngine, "Engine");
++}
++
++SoGuiRadioGroup::SoGuiRadioGroup(void)
++{
++  this->index = -1;
++
++  SO_ENGINE_CONSTRUCTOR(SoGuiRadioGroup);
++
++  SO_ENGINE_ADD_INPUT(in0, (FALSE));
++  SO_ENGINE_ADD_INPUT(in1, (FALSE));
++  SO_ENGINE_ADD_INPUT(in2, (FALSE));
++  SO_ENGINE_ADD_INPUT(in3, (FALSE));
++  SO_ENGINE_ADD_INPUT(in4, (FALSE));
++  SO_ENGINE_ADD_INPUT(in5, (FALSE));
++  SO_ENGINE_ADD_INPUT(in6, (FALSE));
++  SO_ENGINE_ADD_INPUT(in7, (FALSE));
++
++  SO_ENGINE_ADD_OUTPUT(out0, SoSFBool);
++  SO_ENGINE_ADD_OUTPUT(out1, SoSFBool);
++  SO_ENGINE_ADD_OUTPUT(out2, SoSFBool);
++  SO_ENGINE_ADD_OUTPUT(out3, SoSFBool);
++  SO_ENGINE_ADD_OUTPUT(out4, SoSFBool);
++  SO_ENGINE_ADD_OUTPUT(out5, SoSFBool);
++  SO_ENGINE_ADD_OUTPUT(out6, SoSFBool);
++  SO_ENGINE_ADD_OUTPUT(out7, SoSFBool);
++}
++
++SoGuiRadioGroup::~SoGuiRadioGroup(void)
++{
++}
++
++void
++SoGuiRadioGroup::inputChanged(SoField * which)
++{
++  SoSFBool * fields[] = {
++    &(this->in0),
++    &(this->in1),
++    &(this->in2),
++    &(this->in3),
++    &(this->in4),
++    &(this->in5),
++    &(this->in6),
++    &(this->in7),
++    NULL
++  };
++  int i;
++  for ( i = 0; which != fields[i] && fields[i] != NULL; i++ ) { }
++  assert(fields[i] != NULL );
++  if ( ((SoSFBool *)which)->getValue() != FALSE ) {
++    this->index = i;
++  } else {
++    if ( this->index == i ) this->index = -1;
++  }
++}
++
++void
++SoGuiRadioGroup::evaluate(void)
++{
++  if ( this->index == -1 ) return; // avoid update
++  SoSFBool * fields[] = {
++    &(this->in0), &(this->in1), &(this->in2), &(this->in3),
++    &(this->in4), &(this->in5), &(this->in6), &(this->in7),
++    NULL
++  };
++  SoEngineOutput * outputs[] = {
++    &(this->out0), &(this->out1), &(this->out2), &(this->out3),
++    &(this->out4), &(this->out5), &(this->out6), &(this->out7),
++    NULL
++  };
++  int i;
++  for ( i = 0; i < 8; i++ ) {
++    if ( i == this->index ) {
++      SO_ENGINE_OUTPUT((*outputs[i]), SoSFBool, setValue(TRUE));
++    } else {
++      SO_ENGINE_OUTPUT((*outputs[i]), SoSFBool, setValue(FALSE));
++    }
++  }
++}
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/engines/RadioGroup.h.in
+@@ -0,0 +1,85 @@
++#ifndef COIN_SOGUIRADIOGROUP_H
++#define COIN_SOGUIRADIOGROUP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif // !SO at GUI@_INTERNAL
++
++#include <Inventor/fields/SoSFBool.h>
++#include <Inventor/engines/SoSubEngine.h>
++#ifdef __COIN__
++#include <Inventor/engines/SoEngineOutput.h>
++#endif // __COIN__
++#include <Inventor/engines/SoEngine.h>
++
++class SoGuiRadioGroup : public SoEngine {
++  typedef SoEngine inherited;
++  SO_ENGINE_HEADER(SoGuiRadioGroup);
++
++public:
++  static void initClass(void);
++  SoGuiRadioGroup(void);
++
++  SoSFBool in0;
++  SoSFBool in1;
++  SoSFBool in2;
++  SoSFBool in3;
++  SoSFBool in4;
++  SoSFBool in5;
++  SoSFBool in6;
++  SoSFBool in7;
++
++  SoEngineOutput out0;
++  SoEngineOutput out1;
++  SoEngineOutput out2;
++  SoEngineOutput out3;
++  SoEngineOutput out4;
++  SoEngineOutput out5;
++  SoEngineOutput out6;
++  SoEngineOutput out7;
++
++protected:
++  virtual ~SoGuiRadioGroup(void);
++
++private:
++  virtual void inputChanged(SoField * which);
++  virtual void evaluate(void);
++
++  int index;
++};
++
++#endif // !COIN_SOGUIRADIOGROUP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/gl.h.in
+@@ -0,0 +1,91 @@
++#ifndef SO at GUI@_GL_H
++#define SO at GUI@_GL_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/* This header file is supposed to take care of all operating system
++ * dependent anomalies connected to the gl.h include file.  It is only
++ * for use while building the Coin library, and should not be installed
++ * with the rest of the header files (at least not yet).  20010913 larsa */
++
++#ifndef SO at GUI@_VERSION
++#error "you must include config.h before including Inventor/system/gl.h"
++#endif /* !SO at GUI_VERSION */
++
++#ifdef HAVE_WINDOWS_H
++/* on windows, headers do not include their dependencies */
++#include <windows.h>
++#endif /* HAVE_WINDOWS_H */
++
++#ifdef HAVE_GL_GL_H
++/* the preferred gl.h path */
++#include <GL/gl.h>
++#else
++#ifdef HAVE_OPENGL_GL_H
++/* how Mac OS X organizes things - should we now stuff Coin header in
++   OpenInventor/?  (that *was* irony) */
++#include <OpenGL/gl.h>
++#else
++#error "don't know how to include gl.h header"
++#endif /* !HAVE_GL_GL_H */
++#endif /* !HAVE_OPENGL_GL_H */
++
++#ifdef HAVE_GL_GLU_H
++#include <GL/glu.h>
++#else
++#ifdef HAVE_OPENGL_GLU_H
++#include <OpenGL/glu.h>
++#endif
++#endif
++
++/*
++  At least MS Windows often has very old gl.h files, so we just define
++  these values here if not defined already. Run-time checks are used
++  to determine which feature to use.
++*/
++
++#ifndef GL_CLAMP_TO_EDGE
++#define GL_CLAMP_TO_EDGE         0x812F
++#endif /* GL_CLAMP_TO_EDGE */
++
++#ifndef GL_CLAMP_TO_EDGE_EXT
++#define GL_CLAMP_TO_EDGE_EXT     0x812F
++#endif /* GL_CLAMP_TO_EDGE_EXT */
++
++#ifndef GL_CLAMP_TO_EDGE_SGIS
++#define GL_CLAMP_TO_EDGE_SGIS    0x812F
++#endif /* GL_CLAMP_TO_EDGE_SGIS */
++
++#endif /* ! COIN_GL_H */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/libm4.m4
+@@ -0,0 +1,695 @@
++divert(-1)                                                   -*- Autoconf -*-
++# This file is part of Autoconf.
++# Base m4 layer.
++# Requires GNU m4.
++# Copyright (C) 1999, 2000 Free Software Foundation, Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2, or (at your option)
++# any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
++# 02111-1307, USA.
++#
++# As a special exception, the Free Software Foundation gives unlimited
++# permission to copy, distribute and modify the configure scripts that
++# are the output of Autoconf.  You need not follow the terms of the GNU
++# General Public License when using or distributing such scripts, even
++# though portions of the text of Autoconf appear in them.  The GNU
++# General Public License (GPL) does govern all other use of the material
++# that constitutes the Autoconf program.
++#
++# Certain portions of the Autoconf source text are designed to be copied
++# (in certain cases, depending on the input) into the output of
++# Autoconf.  We call these the "data" portions.  The rest of the Autoconf
++# source text consists of comments plus executable code that decides which
++# of the data portions to output in any given case.  We call these
++# comments and executable code the "non-data" portions.  Autoconf never
++# copies any of the non-data portions into its output.
++#
++# This special exception to the GPL applies to versions of Autoconf
++# released by the Free Software Foundation.  When you make and
++# distribute a modified version of Autoconf, you may extend this special
++# exception to the GPL to apply to your modified version as well, *unless*
++# your modified version has the potential to copy into its output some
++# of the text that was the non-data portion of the version that you started
++# with.  (In other words, unless your change moves or copies text from
++# the non-data portions to the data portions.)  If your modification has
++# such potential, you must delete any notice of this special exception
++# to the GPL from your modified version.
++#
++# Written by Akim Demaille.
++#
++
++# Set the quotes, whatever the current quoting system.
++changequote()
++changequote([, ])
++
++# Some old m4's don't support m4exit.  But they provide
++# equivalent functionality by core dumping because of the
++# long macros we define.
++ifdef([__gnu__], ,
++[errprint(Autoconf requires GNU m4. Install it before installing Autoconf or
++set the M4 environment variable to its path name.)
++m4exit(2)])
++
++
++## --------------------------------- ##
++## Defining macros and name spaces.  ##
++## --------------------------------- ##
++
++# m4_rename(SRC, DST)
++# -------------------
++#
++# Rename the macro SRC as DST.
++define([m4_rename],
++[define([$2], defn([$1]))undefine([$1])])
++
++# Some m4 internals have names colliding with tokens we might use.
++# Rename them a` la `m4 --prefix-builtins'.
++m4_rename([eval],    [m4_eval])
++m4_rename([format],  [m4_format])
++m4_rename([shift],   [m4_shift])
++m4_rename([symbols], [m4_symbols])
++
++
++## --------------------------------------------- ##
++## Move some m4 builtins to a safer name space.  ##
++## --------------------------------------------- ##
++
++# m4_errprint(MSG)
++# ----------------
++# Same as `errprint', but reports the file and line.
++define([m4_errprint], [errprint(__file__:__line__: [$1
++])])
++
++
++# m4_warn(MSG)
++# ------------
++# Warn the user.
++define([m4_warn], [m4_errprint([warning: $1])])
++
++
++# m4_fatal(MSG, [EXIT-STATUS])
++# ----------------------------
++# Fatal the user.                                                      :)
++define([m4_fatal],
++[m4_errprint([error: $1])dnl
++m4exit(ifelse([$2],, 1, [$2]))])
++
++
++# m4_assert( EXPRESSION [, EXIT-STATUS = 1 ])
++# ------------------------------------------
++# This macro ensures that EXPRESSION evaluates to true, and exits if
++# EXPRESSION evaluates to false.
++define([m4_assert],
++[ifelse(m4_eval([$1]), 0,
++        [m4_fatal([assert failed: $1], [$2])],
++        [])])
++
++
++# We also want to neutralize include (and sinclude for symmetry),
++# but we want to extend them slightly: warn when a file is included
++# several times.  This is in general a dangerous operation because
++# quite nobody quotes the first argument of define.
++#
++# For instance in the following case:
++#   define(foo, [bar])
++# then a second reading will turn into
++#   define(bar, [bar])
++# which is certainly not what was meant.
++
++# m4_include_unique(FILE)
++# -----------------------
++# Declare that the FILE was loading; and warn if it has already
++# been included.
++define([m4_include_unique],
++[ifdef([m4_include($1)],
++       [m4_warn([file `$1' included several times])])dnl
++define([m4_include($1)])])
++
++
++# m4_include(FILE)
++# ----------------
++# As the builtin include, but warns against multiple inclusions.
++define([m4_include],
++[m4_include_unique([$1])dnl
++builtin([include], [$1])])
++
++
++# m4_sinclude(FILE)
++# -----------------
++# As the builtin sinclude, but warns against multiple inclusions.
++define([m4_sinclude],
++[m4_include_unique([$1])dnl
++builtin([sinclude], [$1])])
++
++# Neutralize include and sinclude.
++undefine([include])
++undefine([sinclude])
++
++
++## --------------------------------------- ##
++## Some additional m4 structural control.  ##
++## --------------------------------------- ##
++
++# Both `ifval' and `ifset' tests against the empty string.  The
++# difference is that `ifset' is specialized on macros.
++#
++# In case of arguments of macros, eg $[1], it makes little difference.
++# In the case of a macro `FOO', you don't want to check `ifval(FOO,
++# TRUE)', because if `FOO' expands with commas, there is a shifting of
++# the arguments.  So you want to run `ifval([FOO])', but then you just
++# compare the *string* `FOO' against `', which, of course fails.
++#
++# So you want a variation of `ifset' that expects a macro name as $[1].
++# If this macro is both defined and defined to a non empty value, then
++# it runs TRUE etc.
++
++
++# ifval(COND, [IF-TRUE], [IF-FALSE])
++# ----------------------------------
++# If COND is not the empty string, expand IF-TRUE, otherwise IF-FALSE.
++# Comparable to ifdef.
++define([ifval], [ifelse([$1],[],[$3],[$2])])
++
++
++# ifset(MACRO, [IF-TRUE], [IF-FALSE])
++# -----------------------------------
++# If MACRO has no definition, or of its definition is the empty string,
++# expand IF-FALSE, otherwise IF-TRUE.
++define([ifset],
++[ifdef([$1],
++       [ifelse(defn([$1]), [], [$3], [$2])],
++       [$3])])
++
++
++# ifndef(NAME, [IF-NOT-DEFINED], [IF-DEFINED])
++# --------------------------------------------
++define([ifndef],
++[ifdef([$1], [$3], [$2])])
++
++
++# m4_default(EXP1, EXP2)
++# ----------------------
++# Returns EXP1 if non empty, otherwise EXP2.
++define([m4_default], [ifval([$1], [$1], [$2])])
++
++
++# m4_shiftn( N, ... )
++# -------------------
++# Returns ... shifted N times.  Useful for recursive "varargs" constructs.
++define([m4_shiftn],
++[m4_assert(($1 >= 0) && ($# > $1))dnl
++_m4_shiftn($@)])
++
++define([_m4_shiftn],
++[ifelse([$1], 0,
++        [m4_shift($@)],
++        [_m4_shiftn(m4_eval([$1]-1), m4_shift(m4_shift($@)))])])
++
++
++# m4_case(SWITCH, VAL1, IF-VAL1, VAL2, IF-VAL2, ..., DEFAULT)
++# -----------------------------------------------------------
++# m4 equivalent of
++# switch (SWITCH)
++# {
++#   case VAL1:
++#     IF-VAL1;
++#     break;
++#   case VAL2:
++#     IF-VAL2;
++#     break;
++#   ...
++#   default:
++#     DEFAULT;
++#     break;
++# }.
++# All the values are optional, and the macro is robust to active
++# symbols properly quoted.
++define([m4_case],
++[ifelse([$#], 0, [],
++	[$#], 1, [],
++	[$#], 2, [$2],
++        [$1], [$2], [$3],
++        [m4_case([$1], m4_shiftn(3, $@))])])
++
++
++# m4_match(SWITCH, RE1, VAL1, RE2, VAL2, ..., DEFAULT)
++# ----------------------------------------------------
++# m4 equivalent of
++#
++# if (SWITCH =~ RE1)
++#   VAL1;
++# elif (SWITCH =~ RE2)
++#   VAL2;
++# elif ...
++#   ...
++# else
++#   DEFAULT
++#
++# All the values are optional, and the macro is robust to active symbols
++# properly quoted.
++define([m4_match],
++[ifelse([$#], 0, [],
++	[$#], 1, [],
++	[$#], 2, [$2],
++        regexp([$1], [$2]), -1, [m4_match([$1], m4_shiftn(3, $@))],
++        [$3])])
++
++# m4_do(STRING, ...)
++# ------------------
++# This macro invokes all its arguments (in sequence, of course).  It is
++# useful for making your macros more structured and readable by dropping
++# unecessary dnl's and have the macros indented properly.
++
++define([m4_do],
++  [ifelse($#, 0, [],
++          $#, 1, [$1],
++          [$1[]m4_do(m4_shift($@))])])
++
++## --------------------- ##
++## Implementing m4 loops ##
++## --------------------- ##
++
++
++# m4_for(VARIABLE, FIRST, LAST, [STEP = +/-1], EXPRESSION)
++# --------------------------------------
++# Expand EXPRESSION defining VARIABLE to FROM, FROM + 1, ..., TO.
++# Both limits are included.
++
++define([m4_for],
++[m4_case(m4_sign(m4_eval($3 - $2)),
++         1, [m4_assert(m4_sign(m4_default($4, 1)) == 1)],
++        -1, [m4_assert(m4_sign(m4_default($4, -1)) == -1)])dnl
++pushdef([$1], [$2])dnl
++ifelse(m4_eval([$3 > $2]), 1,
++       [_m4_for([$1], [$3], m4_default([$4], 1), [$5])],
++       [_m4_for([$1], [$3], m4_default([$4], -1), [$5])])dnl
++popdef([$1])])
++
++define([_m4_for],
++[$4[]dnl
++ifelse($1, [$2], [],
++       [define([$1], m4_eval($1+[$3]))_m4_for([$1], [$2], [$3], [$4])])])
++
++
++# Implementing `foreach' loops in m4 is much more tricky than it may
++# seem.  Actually, the example of a `foreach' loop in the m4
++# documentation is wrong: it does not quote the arguments properly,
++# which leads to undesired expansions.
++#
++# The example in the documentation is:
++#
++# | # foreach(VAR, (LIST), STMT)
++# | define([foreach],
++# |        [pushdef([$1])_foreach([$1], [$2], [$3])popdef([$1])])
++# | define([_arg1], [$1])
++# | define([_foreach],
++# | 	   [ifelse([$2], [()], ,
++# | 		   [define([$1], _arg1$2)$3[]_foreach([$1],
++# |                                                   (shift$2),
++# |                                                   [$3])])])
++#
++# But then if you run
++#
++# | define(a, 1)
++# | define(b, 2)
++# | define(c, 3)
++# | foreach([f], [([a], [(b], [c)])], [echo f
++# | ])
++#
++# it gives
++#
++#  => echo 1
++#  => echo (2,3)
++#
++# which is not what is expected.
++#
++# Of course the problem is that many quotes are missing.  So you add
++# plenty of quotes at random places, until you reach the expected
++# result.  Alternatively, if you are a quoting wizard, you directly
++# reach the following implementation (but if you really did, then
++# apply to the maintenance of libm4!).
++#
++# | # foreach(VAR, (LIST), STMT)
++# | define([foreach], [pushdef([$1])_foreach($@)popdef([$1])])
++# | define([_arg1], [[$1]])
++# | define([_foreach],
++# |  [ifelse($2, [()], ,
++# | 	     [define([$1], [_arg1$2])$3[]_foreach([$1],
++# |                                               [(shift$2)],
++# |                                               [$3])])])
++#
++# which this time answers
++#
++#  => echo a
++#  => echo (b
++#  => echo c)
++#
++# Bingo!
++#
++# Well, not quite.
++#
++# With a better look, you realize that the parens are more a pain than
++# a help: since anyway you need to quote properly the list, you end up
++# with always using an outermost pair of parens and an outermost pair
++# of quotes.  Rejecting the parens both eases the implementation, and
++# simplifies the use:
++#
++# | # foreach(VAR, (LIST), STMT)
++# | define([foreach], [pushdef([$1])_foreach($@)popdef([$1])])
++# | define([_arg1], [$1])
++# | define([_foreach],
++# |  [ifelse($2, [], ,
++# | 	     [define([$1], [_arg1($2)])$3[]_foreach([$1],
++# |                                                 [shift($2)],
++# |                                                 [$3])])])
++#
++#
++# Now, just replace the `$2' with `m4_quote($2)' in the outer `ifelse'
++# to improve robustness, and you come up with a quite satisfactory
++# implementation.
++
++
++# m4_foreach(VARIABLE, LIST, EXPRESSION)
++# --------------------------------------
++#
++# Expand EXPRESSION assigning each value of the LIST to VARIABLE.
++# LIST should have the form `item_1, item_2, ..., item_n', i.e. the
++# whole list must *quoted*.  Quote members too if you don't want them
++# to be expanded.
++#
++# This macro is robust to active symbols:
++#      | define(active, [ACT, IVE])
++#      | m4_foreach(Var, [active, active], [-Var-])
++#     => -ACT--IVE--ACT--IVE-
++#
++#      | m4_foreach(Var, [[active], [active]], [-Var-])
++#     => -ACT, IVE--ACT, IVE-
++#
++#      | m4_foreach(Var, [[[active]], [[active]]], [-Var-])
++#     => -active--active-
++define([m4_foreach],
++[pushdef([$1])_m4_foreach($@)popdef([$1])])
++
++# Low level macros used to define m4_foreach.
++define([m4_car], [$1])
++define([_m4_foreach],
++[ifelse(m4_quote($2), [], [],
++        [define([$1], [m4_car($2)])$3[]_m4_foreach([$1],
++                                                   [m4_shift($2)],
++                                                   [$3])])])
++
++
++## ----------------- ##
++## Text processing.  ##
++## ----------------- ##
++
++
++# m4_quote(STRING)
++# ----------------
++# Return STRING quoted.
++#
++# It is important to realize the difference between `quote(exp)' and
++# `[exp]': in the first case you obtain the quoted *result* of the
++# expansion of EXP, while in the latter you just obtain the string
++# `exp'.
++define([m4_quote], [[$*]])
++
++
++# m4_noquote(STRING)
++# ------------------
++# Return the result of ignoring all quotes in STRING and invoking the
++# macros it contains.  Amongst other things useful for enabling macro
++# invocations inside strings with [] blocks (for instance regexps and
++# help-strings).
++define([m4_noquote],
++[changequote(-=<{,}>=-)$1-=<{}>=-changequote([,])])
++
++
++# m4_split(STRING, [REGEXP])
++# --------------------------
++#
++# Split STRING into an m4 list of quoted elements.  The elements are
++# quoted with [ and ].  Beginning spaces and end spaces *are kept*.
++# Use m4_strip to remove them.
++#
++# REGEXP specifies where to split.  Default is [\t ]+.
++#
++# Pay attention to the changequotes.  Inner changequotes exist for
++# obvious reasons (we want to insert square brackets).  Outer
++# changequotes are needed because otherwise the m4 parser, when it
++# sees the closing bracket we add to the result, believes it is the
++# end of the body of the macro we define.
++#
++# Also, notice that $1 is quoted twice, since we want the result to
++# be quoted.  Then you should understand that the argument of
++# patsubst is ``STRING'' (i.e., with additional `` and '').
++#
++# This macro is safe on active symbols, i.e.:
++#   define(active, ACTIVE)
++#   m4_split([active active ])end
++#   => [active], [active], []end
++
++changequote(<<, >>)
++define(<<m4_split>>,
++<<changequote(``, '')dnl
++[dnl Can't use m4_default here instead of ifelse, because m4_default uses
++dnl [ and ] as quotes.
++patsubst(````$1'''',
++	  ifelse(``$2'',, ``[ 	]+'', ``$2''),
++	  ``], ['')]dnl
++changequote([, ])>>)
++changequote([, ])
++
++
++
++# m4_join(STRING)
++# ---------------
++# If STRING contains end of lines, replace them with spaces.  If there
++# are backslashed end of lines, remove them.  This macro is safe with
++# active symbols.
++#    define(active, ACTIVE)
++#    m4_join([active
++#    act\
++#    ive])end
++#    => active activeend
++define([m4_join],
++[translit(patsubst([[[$1]]], [\\
++]), [
++], [ ])])
++
++
++# m4_strip(STRING)
++# ----------------
++# Expands into STRING with tabs and spaces singled out into a single
++# space, and removing leading and trailing spaces.
++#
++# This macro is robust to active symbols.
++#    define(active, ACTIVE)
++#    m4_strip([  active  		active ])end
++#    => active activeend
++#
++# This macro is fun!  Because we want to preserve active symbols, STRING
++# must be quoted for each evaluation, which explains there are 4 levels
++# of brackets around $1 (don't forget that the result must be quoted
++# too, hence one more quoting than applications).
++#
++# Then notice the patsubst of the middle: it is in charge of removing
++# the leading space.  Why not just `patsubst(..., [^ ])'?  Because this
++# macro will receive the output of the preceding patsubst, i.e. more or
++# less [[STRING]].  So if there is a leading space in STRING, then it is
++# the *third* character, since there are two leading `['; Equally for
++# the outer patsubst.
++define([m4_strip],
++[patsubst(patsubst(patsubst([[[[$1]]]],
++                            [[ 	]+], [ ]),
++                   [^\(..\) ], [\1]),
++          [ \(.\)$], [\1])])
++
++
++
++# m4_append(MACRO-NAME, STRING)
++# -----------------------------
++# Redefine MACRO-NAME to hold its former content plus STRING at the
++# end.  It is valid to use this macro with MACRO-NAME undefined.
++#
++# This macro is robust to active symbols.  It can be used to grow
++# strings.
++#
++#    | define(active, ACTIVE)
++#    | m4_append([sentence], [This is an])
++#    | m4_append([sentence], [ active ])
++#    | m4_append([sentence], [symbol.])
++#    | sentence
++#    | undefine([active])dnl
++#    | sentence
++#    => This is an ACTIVE symbol.
++#    => This is an active symbol.
++#
++# It can be used to define hooks.
++#
++#    | define(active, ACTIVE)
++#    | m4_append([hooks], [define([act1], [act2])])
++#    | m4_append([hooks], [define([act2], [active])])
++#    | undefine([active])
++#    | act1
++#    | hooks
++#    | act1
++#    => act1
++#    =>
++#    => active
++define([m4_append],
++[define([$1],
++ifdef([$1], [defn([$1])])[$2])])
++
++
++# m4_list_append(MACRO-NAME, STRING)
++# ----------------------------------
++# Same as `m4_append', but each element is separated by `, '.
++define([m4_list_append],
++[define([$1],
++ifdef([$1], [defn([$1]), ])[$2])])
++
++
++
++
++## ----------------------------------- ##
++## Helping macros to display strings.  ##
++## ----------------------------------- ##
++
++# m4_foreach_quoted(VARIABLE, LIST, EXPRESSION)
++# ---------------------------------------------
++# FIXME: This macro should not exists.  Currently it's used only in
++# m4_wrap, which needs to be rewritten.  But it's godam hard.
++define([m4_foreach_quoted],
++[pushdef([$1], [])_m4_foreach_quoted($@)popdef([$1])])
++
++# Low level macros used to define m4_foreach.
++define([m4_car_quoted], [[$1]])
++define([_m4_foreach_quoted],
++[ifelse($2, [()], ,
++        [define([$1], [m4_car_quoted$2])$3[]_m4_foreach_quoted([$1],
++                                                               [(m4_shift$2)],
++                                                               [$3])])])
++
++
++# m4_wrap(STRING, [PREFIX], [FIRST-PREFIX], [WIDTH])
++# --------------------------------------------------
++# Expands into STRING wrapped to hold in WIDTH columns (default = 79).
++# If prefix is set, each line is prefixed with it.  If FIRST-PREFIX is
++# specified, then the first line is prefixed with it.  As a special
++# case, if the length of the first prefix is greater than that of
++# PREFIX, then FIRST-PREFIX will be left alone on the first line.
++#
++# Typical outputs are:
++#
++# m4_wrap([Short string */], [   ], [/* ], 20)
++#  => /* Short string */
++#
++# m4_wrap([Much longer string */], [   ], [/* ], 20)
++#  => /* Much longer
++#  =>    string */
++#
++# m4_wrap([Short doc.], [          ], [  --short ], 30)
++#  =>   --short Short doc.
++#
++# m4_wrap([Short doc.], [          ], [  --too-wide ], 30)
++#  =>   --too-wide
++#  =>           Short doc.
++#
++# m4_wrap([Super long documentation.], [          ], [  --too-wide ], 30)
++#  =>   --too-wide
++#  => 	  Super long
++#  => 	  documentation.
++#
++# FIXME: there is no checking of a longer PREFIX than WIDTH, but do
++# we really want to bother with people trying each single corner
++# of a software?
++#
++# This macro does not leave a trailing space behind the last word,
++# what complicates it a bit.  The algorithm is stupid simple: all the
++# words are preceded by m4_Separator which is defined to empty for the
++# first word, and then ` ' (single space) for all the others.
++define([m4_wrap],
++[pushdef([m4_Prefix], m4_default([$2], []))dnl
++pushdef([m4_Prefix1], m4_default([$3], [m4_Prefix]))dnl
++pushdef([m4_Width], m4_default([$4], 79))dnl
++pushdef([m4_Cursor], len(m4_Prefix1))dnl
++pushdef([m4_Separator], [])dnl
++m4_Prefix1[]dnl
++ifelse(m4_eval(m4_Cursor > len(m4_Prefix)),
++       1, [define([m4_Cursor], len(m4_Prefix))
++m4_Prefix])[]dnl
++m4_foreach_quoted([m4_Word], (m4_split(m4_strip(m4_join([$1])))),
++[define([m4_Cursor], m4_eval(m4_Cursor + len(m4_Word) + 1))dnl
++dnl New line if too long, else insert a space unless it is the first
++dnl of the words.
++ifelse(m4_eval(m4_Cursor > m4_Width),
++       1, [define([m4_Cursor], m4_eval(len(m4_Prefix) + len(m4_Word) + 1))]
++m4_Prefix,
++       [m4_Separator])[]dnl
++m4_Word[]dnl
++define([m4_Separator], [ ])])dnl
++popdef([m4_Separator])dnl
++popdef([m4_Cursor])dnl
++popdef([m4_Width])dnl
++popdef([m4_Prefix1])dnl
++popdef([m4_Prefix])dnl
++])
++
++
++
++## ------------------- ##
++## Number processing.  ##
++## ------------------- ##
++
++# m4_sign(A)
++# ----------
++#
++# The sign of the integer A.
++define([m4_sign],
++[m4_match([$1],
++          [^-], -1,
++          [^0+], 0,
++                 1)])
++
++# m4_cmp(A, B)
++# ------------
++#
++# Compare two integers.
++# A < B -> -1
++# A = B ->  0
++# A > B ->  1
++define([m4_cmp],
++[m4_sign(m4_eval([$1 - $2]))])
++
++
++# m4_list_cmp(A, B)
++# -----------------
++#
++# Compare the two lists of integers A and B.  For instance:
++#   m4_list_cmp((1, 0),     (1))    ->  0
++#   m4_list_cmp((1, 0),     (1, 0)) ->  0
++#   m4_list_cmp((1, 2),     (1, 0)) ->  1
++#   m4_list_cmp((1, 2, 3),  (1, 2)) ->  1
++#   m4_list_cmp((1, 2, -3), (1, 2)) -> -1
++#   m4_list_cmp((1, 0),     (1, 2)) -> -1
++#   m4_list_cmp((1),        (1, 2)) -> -1
++define([m4_list_cmp],
++[ifelse([$1$2], [()()], 0,
++        [$1], [()], [m4_list_cmp((0), [$2])],
++        [$2], [()], [m4_list_cmp([$1], (0))],
++        [m4_case(m4_cmp(m4_car$1, m4_car$2),
++                 -1, -1,
++                  1, 1,
++                  0, [m4_list_cmp((m4_shift$1), (m4_shift$2))])])])
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/ClickCounter.cpp.in
+@@ -0,0 +1,246 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/events/SoMouseButtonEvent.h>
++#include <Inventor/actions/SoHandleEventAction.h>
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoIndexedFaceSet.h>
++#include <Inventor/nodes/SoTexture2.h>
++#include <Inventor/nodes/SoCoordinate3.h>
++#include <Inventor/nodes/SoTextureCoordinate2.h>
++#include <Inventor/nodes/SoMaterial.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++#include <Inventor/SoPickedPoint.h>
++#include <Inventor/SoLists.h>
++
++#include <Inventor/SbColor.h>
++
++#include <Inventor/@Gui@/nodes/SoGuiClickCounter.h>
++#include <assert.h>
++
++//  SO_KIT_CATALOG_ENTRY_HEADER(topSeparator);
++//  SO_KIT_CATALOG_ENTRY_HEADER(surfaceMaterial);
++//  SO_KIT_CATALOG_ENTRY_HEADER(surfaceTexture);
++//  SO_KIT_CATALOG_ENTRY_HEADER(surfaceTexCoords);
++//  SO_KIT_CATALOG_ENTRY_HEADER(surfaceCoords);
++//  SO_KIT_CATALOG_ENTRY_HEADER(surfaceFaceSet);
++
++//  SoSFVec3f size;
++//  SoSFInt32 value;
++//  SoSFTrigger click;
++//  SoSFInt32 first;
++//  SoSFInt32 last;
++
++class ClickCounter {
++public:
++  SoGuiClickCounter * api;
++
++  SoFieldSensor * sizesensor;
++  static void sizeCB(void * closure, SoSensor * sensor);
++
++  SoFieldSensor * firstsensor;
++  static void firstCB(void * closure, SoSensor * sensor);
++
++  ClickCounter(void);
++  ~ClickCounter(void);
++};
++
++// *************************************************************************
++
++void
++SoGuiClickCounter::initClass(void)
++{
++  SO_KIT_INIT_CLASS(SoGuiClickCounter, SoBaseKit, "BaseKit");
++}
++
++SO_KIT_SOURCE(SoGuiClickCounter);
++
++#define PRIVATE(obj) ((ClickCounter *) this->internals)
++
++SoGuiClickCounter::SoGuiClickCounter(void)
++{
++  this->internals = new ClickCounter;
++  PRIVATE(this)->api = this;
++
++  SO_KIT_CONSTRUCTOR(SoGuiClickCounter);
++
++  SO_KIT_ADD_FIELD(size, (SbVec3f(1.0f, 1.0f, 0.0f)));
++  SO_KIT_ADD_FIELD(first, (0));
++  SO_KIT_ADD_FIELD(last, (0));
++  SO_KIT_ADD_FIELD(value, (0));
++  SO_KIT_ADD_FIELD(click, ());
++
++  SO_KIT_ADD_CATALOG_ENTRY(surfaceFaceSet, SoIndexedFaceSet, FALSE, topSeparator, "", FALSE);
++  SO_KIT_ADD_CATALOG_ENTRY(surfaceCoords, SoCoordinate3, FALSE, topSeparator, surfaceFaceSet, FALSE);
++  SO_KIT_ADD_CATALOG_ENTRY(surfaceTexCoords, SoTextureCoordinate2, FALSE, topSeparator, surfaceCoords, FALSE);
++  SO_KIT_ADD_CATALOG_ENTRY(surfaceTexture, SoTexture2, TRUE, topSeparator, surfaceTexCoords, TRUE);
++  SO_KIT_ADD_CATALOG_ENTRY(surfaceMaterial, SoMaterial, TRUE, topSeparator, surfaceTexture, TRUE);
++  SO_KIT_ADD_CATALOG_ENTRY(topSeparator, SoSeparator, FALSE, this, "", FALSE);
++
++  SO_KIT_INIT_INSTANCE();
++
++  static float surfacetexturecoordinates[][2] = { {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f} };
++  SoTextureCoordinate2 * surfacetexcoords = SO_GET_ANY_PART(this, "surfaceTexCoords", SoTextureCoordinate2);
++  assert(surfacetexcoords);
++  surfacetexcoords->point.setValues(0, 4, surfacetexturecoordinates);
++
++  static int32_t surfaceindices[] = { 0, 1, 2, -1, 0, 2, 3, -1 };
++  SoIndexedFaceSet * surfacefaceset = SO_GET_ANY_PART(this, "surfaceFaceSet", SoIndexedFaceSet);
++  assert(surfacefaceset);
++  surfacefaceset->textureCoordIndex.setValues(0, 8, surfaceindices);
++  surfacefaceset->coordIndex.setValues(0, 8, surfaceindices);
++
++  // SoMaterial * surfacematerial = SO_GET_ANY_PART(this, "surfaceMaterial", SoMaterial);
++  // surfacematerial->diffuseColor.setValue(SbColor(0.0f, 0.0f, 0.0f));
++
++  this->sizeUpdate();
++
++  PRIVATE(this)->sizesensor = new SoFieldSensor(ClickCounter::sizeCB, PRIVATE(this));
++  PRIVATE(this)->sizesensor->attach(&(this->size));
++  PRIVATE(this)->firstsensor = new SoFieldSensor(ClickCounter::firstCB, PRIVATE(this));
++  PRIVATE(this)->firstsensor->attach(&(this->first));
++}
++
++SoGuiClickCounter::~SoGuiClickCounter(void)
++{
++  ClickCounter * obj = PRIVATE(this);
++  delete obj;
++}
++
++void
++SoGuiClickCounter::handleEvent(SoHandleEventAction * action)
++{
++  const SoEvent * ev = action->getEvent();
++  if ( ev->isOfType(SoMouseButtonEvent::getClassTypeId()) ) {
++    const SoMouseButtonEvent * event = (SoMouseButtonEvent *) ev;
++    if ( event->getState() == SoButtonEvent::DOWN ) {
++      const SoPickedPointList & ppoints = action->getPickedPointList();
++      SbBool hit = FALSE;
++      int i = 0;
++      SoIndexedFaceSet * target = SO_GET_ANY_PART(this, "surfaceFaceSet", SoIndexedFaceSet);
++      assert(target);
++      for ( i = 0; !hit && i < ppoints.getLength(); i++ ) {
++        const SoPickedPoint * point = ppoints[i];
++        const SoFullPath * path = (const SoFullPath *) point->getPath();
++        assert(path);
++        SoNode * node = path->getTail();
++        if ( node == (SoNode *) target ) hit = TRUE;
++      }
++      if ( hit ) {
++        int32_t firstval = this->first.getValue();
++        int32_t lastval = this->last.getValue();
++        if ( firstval < lastval ) {
++          int32_t val = this->value.getValue() + 1;
++          if ( val > lastval ) val = firstval;
++          this->value.setValue(val);
++        } else if ( firstval > lastval ) {
++          int32_t val = this->value.getValue() - 1;
++          if ( val < lastval ) val = firstval;
++          this->value.setValue(val);
++        }
++        this->click.touch();
++      }
++    }
++  }
++}
++
++void
++SoGuiClickCounter::setSurfaceColor(const SbColor & valuearg)
++{
++}
++
++void
++SoGuiClickCounter::sizeUpdate(void)
++{
++  SbVec3f sizeval = this->size.getValue();
++  if ( sizeval[0] != 0.0f && sizeval[1] != 0.0f ) {
++    float coordinates[][3] = { {0.0f, 0.0f, 0.0f}, {sizeval[0], 0.0f, 0.0f}, {sizeval[0], sizeval[1], 0.0f}, {0.0f, sizeval[1], 0.0f} };
++    SoCoordinate3 * coords = SO_GET_ANY_PART(this, "surfaceCoords", SoCoordinate3);
++    assert(coords);
++    coords->point.setValues(0, sizeof(coordinates) / sizeof(coordinates[0]), coordinates);
++  }
++}
++
++void
++SoGuiClickCounter::firstUpdate(void)
++{
++  this->value.setValue(this->first.getValue());
++}
++
++SbBool
++SoGuiClickCounter::readInstance(SoInput * in, unsigned short flags)
++{
++  assert(PRIVATE(this)->firstsensor != NULL);
++  PRIVATE(this)->firstsensor->detach();
++  SbBool retval = inherited::readInstance(in, flags);
++  PRIVATE(this)->firstsensor->attach(&(this->first));
++  return retval;
++}
++
++// *************************************************************************
++
++ClickCounter::ClickCounter(void)
++{
++  this->api = NULL;
++  this->sizesensor = NULL;
++  this->firstsensor = NULL;
++}
++
++ClickCounter::~ClickCounter(void)
++{
++}
++
++void
++ClickCounter::sizeCB(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  ClickCounter * me = (ClickCounter *) closure;
++  assert(me->api);
++  me->api->sizeUpdate();
++}
++
++void
++ClickCounter::firstCB(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  ClickCounter * me = (ClickCounter *) closure;
++  assert(me->api);
++  me->api->firstUpdate();
++}
++
++// *************************************************************************
++
++#undef PRIVATE
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/ClickCounter.h.in
+@@ -0,0 +1,92 @@
++#ifndef COIN_SOGUICLICKCOUNTER_H
++#define COIN_SOGUICLICKCOUNTER_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/fields/SoSFTrigger.h>
++#include <Inventor/fields/SoSFInt32.h>
++#include <Inventor/fields/SoSFVec3f.h>
++
++#include <Inventor/nodekits/SoBaseKit.h>
++
++class SbColor;
++
++class SoGuiClickCounter : public SoBaseKit {
++  typedef SoBaseKit inherited;
++
++  SO_KIT_HEADER(SoGuiClickCounter);
++
++  SO_KIT_CATALOG_ENTRY_HEADER(topSeparator);
++  SO_KIT_CATALOG_ENTRY_HEADER(surfaceMaterial);
++  SO_KIT_CATALOG_ENTRY_HEADER(surfaceTexture);
++  SO_KIT_CATALOG_ENTRY_HEADER(surfaceTexCoords);
++  SO_KIT_CATALOG_ENTRY_HEADER(surfaceCoords);
++  SO_KIT_CATALOG_ENTRY_HEADER(surfaceFaceSet);
++
++public:
++  static void initClass(void);
++
++  SoGuiClickCounter(void);
++
++  SoSFVec3f size;
++
++  SoSFInt32 value;
++  SoSFTrigger click;
++
++  SoSFInt32 first;
++  SoSFInt32 last;
++
++  virtual void handleEvent(SoHandleEventAction * action);
++
++  virtual void setSurfaceColor(const SbColor & value);
++
++  void sizeUpdate(void);
++  void firstUpdate(void);
++
++protected:
++  virtual ~SoGuiClickCounter(void);
++
++  virtual SbBool readInstance(SoInput * in, unsigned short flags);
++
++private:
++  void * internals;
++
++};
++
++#endif // !COIN_SOGUICLICKCOUNTER_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/ColorEditor.cpp.in
+@@ -0,0 +1,890 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/SbPList.h>
++#include <Inventor/SoSceneManager.h>
++#include <Inventor/fields/SoSFColor.h>
++#include <Inventor/fields/SoMFColor.h>
++#include <Inventor/fields/SoMFUInt32.h>
++#include <Inventor/nodes/SoSwitch.h>
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoTexture2.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++#include <Inventor/actions/SoGLRenderAction.h>
++
++#include <Inventor/@Gui@/SoAny.h>
++
++#include <Inventor/@Gui@/nodes/SoGuiViewportFix.h>
++#include <Inventor/@Gui@/nodes/SoGuiPane.h>
++#include <Inventor/@Gui@/nodes/SoGuiClickCounter.h>
++#include <Inventor/@Gui@/nodes/SoGuiSlider1.h>
++#include <Inventor/@Gui@/nodes/SoGuiSlider2.h>
++
++#include <Inventor/@Gui@/nodes/SoGuiColorEditor.h>
++#include <assert.h>
++
++/*!
++  \class SoGuiColorEditor Inventor/@Gui@/editors/SoGuiColorEditor.h
++  \brief The SoGuiColorEditor class is a GUI component for interactively
++  editing color fields.
++*/
++
++/*!
++  \enum SoGuiColorEditor::Sliders
++*/
++
++/*!
++  \val SoGuiColorEditor::NONE
++*/
++
++/*!
++  \val SoGuiColorEditor::INTENSITY
++*/
++
++/*!
++  \val SoGuiColorEditor::RGB
++*/
++
++/*!
++  \val SoGuiColorEditor::HSV
++*/
++
++/*!
++  \val SoGuiColorEditor::RGB_V
++*/
++
++/*!
++  \val SoGuiColorEditor::RGB_HSV
++*/
++
++/*!
++  \enum SoGuiColorEditor::Update
++*/
++
++/*!
++  \val SoGuiColorEditor::CONTINUOUS
++*/
++
++/*!
++  \val SoGuiColorEditor::AFTER_ACCEPT
++*/
++
++// *************************************************************************
++
++class ColorEditor {
++public:
++  SoGuiColorEditor * api;
++
++  void colorChange(void);
++
++  SoFieldSensor * color_sensor;
++  static void color_update_cb(void * closure, SoSensor * sensor);
++
++  SoGuiPane * editor;
++  SoGuiClickCounter * switcher;
++  SoGuiSlider1 * slider_r; // red
++  SoGuiSlider1 * slider_g; // green
++  SoGuiSlider1 * slider_b; // blue
++  SoGuiSlider1 * slider_h; // hue
++  SoGuiSlider1 * slider_s; // saturation
++  SoGuiSlider1 * slider_v; // value
++  SoGuiSlider2 * slider_wheel;
++
++  SoFieldSensor * sensor_r;
++  SoFieldSensor * sensor_g;
++  SoFieldSensor * sensor_b;
++  SoFieldSensor * sensor_h;
++  SoFieldSensor * sensor_s;
++  SoFieldSensor * sensor_v;
++  SoFieldSensor * sensor_wheel;
++
++  static void update_r_cb(void * closure, SoSensor * sensor);
++  static void update_g_cb(void * closure, SoSensor * sensor);
++  static void update_b_cb(void * closure, SoSensor * sensor);
++  static void update_h_cb(void * closure, SoSensor * sensor);
++  static void update_s_cb(void * closure, SoSensor * sensor);
++  static void update_v_cb(void * closure, SoSensor * sensor);
++  static void update_wheel_cb(void * closure, SoSensor * sensor);
++
++  static const char * editorscene[];
++
++  static float calculateHue(float x, float y);
++  static SbVec2f calculateFromHue(float h, float s, float v);
++
++  void generateSliderTextureR(const SbColor & current, SbBool wysiwyg);
++  void generateSliderTextureG(const SbColor & current, SbBool wysiwyg);
++  void generateSliderTextureB(const SbColor & current, SbBool wysiwyg);
++  void generateSliderTextureH(const SbColor & current, SbBool wysiwyg);
++  void generateSliderTextureS(const SbColor & current, SbBool wysiwyg);
++  void generateSliderTextureV(const SbColor & current, SbBool wysiwyg);
++  void generateSliderTextureHSV(const SbColor & current, SbBool wysiwyg);
++};
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((ColorEditor *) ((SoGuiColorEditor *) obj)->internals)
++#define PUBLIC(obj) (((ColorEditor *) obj)->api)
++
++void
++SoGuiColorEditor::initClass(void)
++{
++  SO_KIT_INIT_CLASS(SoGuiColorEditor, SoBaseKit, "BaseKit");
++}
++
++SO_KIT_SOURCE(SoGuiColorEditor);
++
++SoGuiColorEditor::SoGuiColorEditor(void)
++{
++  this->internals = (void *) new ColorEditor;
++  PRIVATE(this)->api = this;
++
++  SO_KIT_CONSTRUCTOR(SoGuiColorEditor);
++
++  SO_KIT_ADD_FIELD(wysiwyg, (FALSE));
++  SO_KIT_ADD_FIELD(color, (SbColor(0.0f, 0.0f, 0.0f)));
++  SO_KIT_ADD_FIELD(sliders, (SoGuiColorEditor::RGB_V));
++  SO_KIT_ADD_FIELD(update, (SoGuiColorEditor::AFTER_ACCEPT));
++
++  SO_KIT_DEFINE_ENUM_VALUE(Sliders, NONE);
++  SO_KIT_DEFINE_ENUM_VALUE(Sliders, INTENSITY);
++  SO_KIT_DEFINE_ENUM_VALUE(Sliders, RGB);
++  SO_KIT_DEFINE_ENUM_VALUE(Sliders, HSV);
++  SO_KIT_DEFINE_ENUM_VALUE(Sliders, RGB_V);
++  SO_KIT_DEFINE_ENUM_VALUE(Sliders, RGB_HSV);
++
++  SO_KIT_DEFINE_ENUM_VALUE(Update, CONTINUOUS);
++  SO_KIT_DEFINE_ENUM_VALUE(Update, AFTER_ACCEPT);
++
++  SO_KIT_SET_SF_ENUM_TYPE(sliders, Sliders);
++  SO_KIT_SET_SF_ENUM_TYPE(update, Update);
++
++  SO_KIT_ADD_CATALOG_ENTRY(root, SoGuiPane, TRUE, this, "", FALSE);
++
++  SO_KIT_INIT_INSTANCE();
++
++  PRIVATE(this)->switcher = NULL;
++  PRIVATE(this)->sensor_r = NULL;
++  PRIVATE(this)->sensor_g = NULL;
++  PRIVATE(this)->sensor_b = NULL;
++  PRIVATE(this)->sensor_h = NULL;
++  PRIVATE(this)->sensor_s = NULL;
++  PRIVATE(this)->sensor_v = NULL;
++  PRIVATE(this)->sensor_wheel = NULL;
++
++  PRIVATE(this)->editor = NULL;
++
++  SoNode * scene = SoAny::loadSceneGraph(ColorEditor::editorscene);
++  assert(scene != NULL);
++  assert(scene->isOfType(SoGuiPane::getClassTypeId()));
++
++  PRIVATE(this)->editor = (SoGuiPane *) scene;
++  PRIVATE(this)->editor->ref();
++  PRIVATE(this)->switcher = (SoGuiClickCounter *) SoAny::scanSceneForName(PRIVATE(this)->editor, "switcher");
++  PRIVATE(this)->slider_r = (SoGuiSlider1 *) SoAny::scanSceneForName(PRIVATE(this)->editor, "slider_r", TRUE);
++  PRIVATE(this)->slider_g = (SoGuiSlider1 *) SoAny::scanSceneForName(PRIVATE(this)->editor, "slider_g", TRUE);
++  PRIVATE(this)->slider_b = (SoGuiSlider1 *) SoAny::scanSceneForName(PRIVATE(this)->editor, "slider_b", TRUE);
++  PRIVATE(this)->slider_h = (SoGuiSlider1 *) SoAny::scanSceneForName(PRIVATE(this)->editor, "slider_h", TRUE);
++  PRIVATE(this)->slider_s = (SoGuiSlider1 *) SoAny::scanSceneForName(PRIVATE(this)->editor, "slider_s", TRUE);
++  PRIVATE(this)->slider_v = (SoGuiSlider1 *) SoAny::scanSceneForName(PRIVATE(this)->editor, "slider_v", TRUE);
++  PRIVATE(this)->slider_wheel = (SoGuiSlider2 *) SoAny::scanSceneForName(PRIVATE(this)->editor, "colorwheel", TRUE);
++  if ( PRIVATE(this)->slider_r ) {
++    PRIVATE(this)->slider_r->ref();
++    PRIVATE(this)->sensor_r = new SoFieldSensor(ColorEditor::update_r_cb, PRIVATE(this));
++    PRIVATE(this)->sensor_r->attach(&(PRIVATE(this)->slider_r->value));
++    PRIVATE(this)->generateSliderTextureR(this->color.getValue(), FALSE);
++  }
++  if ( PRIVATE(this)->slider_g ) {
++    PRIVATE(this)->slider_g->ref();
++    PRIVATE(this)->sensor_g = new SoFieldSensor(ColorEditor::update_g_cb, PRIVATE(this));
++    PRIVATE(this)->sensor_g->attach(&(PRIVATE(this)->slider_g->value));
++    PRIVATE(this)->generateSliderTextureG(this->color.getValue(), FALSE);
++  }
++  if ( PRIVATE(this)->slider_b ) {
++    PRIVATE(this)->slider_b->ref();
++    PRIVATE(this)->sensor_b = new SoFieldSensor(ColorEditor::update_b_cb, PRIVATE(this));
++    PRIVATE(this)->sensor_b->attach(&(PRIVATE(this)->slider_b->value));
++    PRIVATE(this)->generateSliderTextureB(this->color.getValue(), FALSE);
++  }
++  if ( PRIVATE(this)->slider_h ) {
++    PRIVATE(this)->slider_h->ref();
++    PRIVATE(this)->sensor_h = new SoFieldSensor(ColorEditor::update_h_cb, PRIVATE(this));
++    PRIVATE(this)->sensor_h->attach(&(PRIVATE(this)->slider_h->value));
++    PRIVATE(this)->generateSliderTextureH(this->color.getValue(), FALSE);
++  }
++  if ( PRIVATE(this)->slider_s ) {
++    PRIVATE(this)->slider_s->ref();
++    PRIVATE(this)->sensor_s = new SoFieldSensor(ColorEditor::update_s_cb, PRIVATE(this));
++    PRIVATE(this)->sensor_s->attach(&(PRIVATE(this)->slider_s->value));
++    PRIVATE(this)->generateSliderTextureS(this->color.getValue(), FALSE);
++
++  }
++  if ( PRIVATE(this)->slider_v ) {
++    PRIVATE(this)->slider_v->ref();
++    PRIVATE(this)->sensor_v = new SoFieldSensor(ColorEditor::update_v_cb, PRIVATE(this));
++    PRIVATE(this)->sensor_v->attach(&(PRIVATE(this)->slider_v->value));
++    PRIVATE(this)->generateSliderTextureV(this->color.getValue(), FALSE);
++  }
++  if ( PRIVATE(this)->slider_wheel ) {
++    PRIVATE(this)->slider_wheel->ref();
++    PRIVATE(this)->sensor_wheel = new SoFieldSensor(ColorEditor::update_wheel_cb, PRIVATE(this));
++    PRIVATE(this)->sensor_wheel->attach(&(PRIVATE(this)->slider_wheel->value));
++    PRIVATE(this)->generateSliderTextureHSV(this->color.getValue(), FALSE);
++  }
++
++  PRIVATE(this)->editor->unrefNoDelete();
++  this->setAnyPart("root", scene);
++
++  PRIVATE(this)->color_sensor = new SoFieldSensor(ColorEditor::color_update_cb, PRIVATE(this));
++  PRIVATE(this)->color_sensor->attach(&(this->color));
++
++  // SoGuiViewportFix * viewportfix = (SoGuiViewportFix *) SoAny::scanSceneForName(inherited::getSceneGraph(), "viewportfix", FALSE);
++  // assert(viewportfix != NULL);
++  // PRIVATE(this)->editor->objectSize.connectFrom(&(viewportfix->viewportSize));
++}
++
++SoGuiColorEditor::~SoGuiColorEditor(void)
++{
++  ColorEditor * instance = PRIVATE(this);
++  delete instance;
++}
++
++// *************************************************************************
++
++// CAT_MOD BEGIN
++const char *
++ColorEditor::editorscene[] = {
++  "#Inventor V2.1 ascii",
++  "DEF pane SoGuiPane {",
++  "  worldSize 1 1 0",
++  "  objectSize 400 340 0",
++  //   Calculate positions
++  "  SoGuiPosition {",
++  "    position = DEF windowgeometry Calculator {",
++  "      A = USE pane.objectSize",
++  "      B 120 120 0",                               // colorwheel size
++  "      C 140 30 0",                                // clickcounter size
++  "      a 2",                                       // width of frame
++  "      expression [",
++  "        \"oA = vec3f(a, A[1] - C[1] - a, 0)\"",   // clickcounter pos
++  "        \"oB = vec3f(A[0] - B[0] - a, A[1] - B[1] - a, 0)\"",  // colorwheel pos
++  "      ]",
++  "    }.oA",
++  "  }",
++  //   Create a click counter
++  "  DEF switcher SoGuiClickCounter {",
++  "    size = USE windowgeometry.C",
++  "    first 2   # the INTENSITY sliders",
++  "    last 6    # the RGB_HSV sliders",
++  "    value 5   # start with the RGB_V group",
++  "  }",
++  //   Create a frame around the click counter area    
++  "  SoGuiFrame {",
++  "    size = USE windowgeometry.C",
++  "    width 2",
++  "    design EMBOSS",
++  "  }",
++  //   Create labels for the click counter
++  "  Separator {",
++  "    Scale {",
++  "      scaleFactor 2 2 2",
++  "    }",
++  "    DEF sliderlabel SoGuiLabel {",
++  "      which = USE switcher.value",
++  "      text [",
++  "        \"?\"",
++  "        \"NONE\"",
++  "        \"VALUE\"",
++  "        \"RGB\"",
++  "        \"HSV\"",
++  "        \"RGBV\"",
++  "        \"RGBHSV\"",
++  "      ]",
++  "    }",
++  "  }",
++  //   Create a frame around the color wheel
++  "  SoGuiPosition { position = USE windowgeometry.oB }",
++  "  SoGuiFrame {",
++  "    size = USE windowgeometry.B",
++  "    design EMBOSS",
++  "    width 2",
++  "    complement TRUE",
++  "  }",
++  //   Create the color wheel
++  "  DEF colorwheel SoGuiSlider2 {",
++  "    size = USE windowgeometry.B",
++  "  }",
++  //   Position the sliders
++  "  SoGuiPosition {",
++  "    position = DEF slidergeometry Calculator {",
++  "      A = USE pane.objectSize",
++  "      B = USE windowgeometry.B",                    // color wheel size
++  "      a = USE windowgeometry.a",                    // width of frame
++  "      b 10",                                        // space
++  "      c 30",                                        // width of text
++  "      expression [",
++  "        \"ta = (A[1] - (2*a + B[1]) -  7*b) / 6\"", // slider height
++  "        \"tb = A[0] - 2*b - c\"",                   // slider width
++  "        \"oA = vec3f(tb, ta, 0)\"",                 // slider size
++  "        \"oB = vec3f(c+b , b, 0)\"",                // slider pos
++  "        \"oC = vec3f(0, ta + b, 0)\"",              // slider translation
++  "        \"oD = vec3f(-c, 0, 0)\"",                  // slider label translation
++  "      ]",
++  "    }.oB",
++  "  }",
++  //   Create the sliders depending on the click count value
++  "  Switch {",
++  "    whichChild = USE switcher.value",
++  "    Group {", // never to be rendered...
++  "      DEF slider_r SoGuiSlider1 { size = USE slidergeometry.oA }",
++  "      DEF slider_g SoGuiSlider1 { size = USE slidergeometry.oA }",
++  "      DEF slider_b SoGuiSlider1 { size = USE slidergeometry.oA }",
++  "      DEF slider_h SoGuiSlider1 { size = USE slidergeometry.oA }",
++  "      DEF slider_s SoGuiSlider1 { size = USE slidergeometry.oA }",
++  "      DEF slider_v SoGuiSlider1 { size = USE slidergeometry.oA }",
++  "      DEF slider_translation SoGuiTranslation { translation = USE slidergeometry.oC }",
++  "      DEF slider_frame SoGuiFrame {",
++  "        size = USE slidergeometry.oA ",
++  "        design EMBOSS",
++  "        width 2",
++  "        complement TRUE",
++  "      }",
++  "      DEF label_translation SoGuiTranslation { translation = USE slidergeometry.oD }",
++  "      DEF label_scale Scale { scaleFactor 2 2 2 }",
++  "      DEF label_r Separator {",
++  "        USE label_translation",
++  "        USE label_scale",
++  "        SoGuiLabel { text \"R\" }",
++  "      }",
++  "      DEF label_g Separator {",
++  "        USE label_translation",
++  "        USE label_scale",
++  "        SoGuiLabel { text \"G\" }",
++  "      }",
++  "      DEF label_b Separator {",
++  "        USE label_translation",
++  "        USE label_scale",
++  "        SoGuiLabel { text \"B\" }",
++  "      }",
++  "      DEF label_h Separator {",
++  "        USE label_translation",
++  "        USE label_scale",
++  "        SoGuiLabel { text \"H\" }",
++  "      }",
++  "      DEF label_s Separator {",
++  "        USE label_translation",
++  "        USE label_scale",
++  "        SoGuiLabel { text \"S\" }",
++  "      }",
++  "      DEF label_v Separator {",
++  "        USE label_translation",
++  "        USE label_scale",
++  "        SoGuiLabel { text \"V\" }",
++  "      }",
++  "    }",
++  "    DEF sliders_NONE Group {", // in case we search for names once, instead of indexing
++  "    }",                        // children directly inside setCurrentSliders()
++  "    DEF sliders_INTENSITY Group {",
++  "      USE slider_frame",       // frames before sliders - the knobs must paint over frames
++  "      USE slider_v",
++  "      USE label_v",
++  "    }",
++  "    DEF sliders_RGB Group {",
++  "      USE slider_frame",
++  "      USE slider_b",
++  "      USE label_b",
++  "      USE slider_translation",
++  "      USE slider_frame",
++  "      USE slider_g",
++  "      USE label_g",
++  "      USE slider_translation",
++  "      USE slider_frame",
++  "      USE slider_r",
++  "      USE label_r",
++  "    }",
++  "    DEF sliders_HSV Group {",
++  "      USE slider_frame",
++  "      USE slider_v",
++  "      USE label_v",
++  "      USE slider_translation",
++  "      USE slider_frame",
++  "      USE slider_s",
++  "      USE label_s",
++  "      USE slider_translation",
++  "      USE slider_frame",
++  "      USE slider_h",
++  "      USE label_h",
++  "    }",
++  "    DEF sliders_RGB_V Group {",
++  "      USE sliders_INTENSITY",
++  "      USE slider_translation",
++  "      USE sliders_RGB",
++  "    }",
++  "    DEF sliders_RGB_HSV Group {",
++  "      USE sliders_HSV",
++  "      USE slider_translation",
++  "      USE sliders_RGB",
++  "    }",
++  "  } # Switch",
++  "} # Pane pane",
++  NULL
++};
++// CAT_MOD END
++
++// *************************************************************************
++
++void
++ColorEditor::colorChange(void)
++{
++  float r = 0.0f, g = 0.0f, b = 0.0f, h = 0.0f, s = 0.0f, v = 0.0f;
++  SbColor color(PUBLIC(this)->color.getValue());
++  color.getValue(r, g, b);
++  color.getHSVValue(h, s, v);
++
++  SbVec2f wheel(this->calculateFromHue(h, s, v));
++
++  this->sensor_r->detach();
++  this->sensor_g->detach();
++  this->sensor_b->detach();
++  this->sensor_h->detach();
++  this->sensor_s->detach();
++  this->sensor_v->detach();
++  this->sensor_wheel->detach();
++
++  if ( r != this->slider_r->value.getValue() ) this->slider_r->value.setValue(r);
++  if ( g != this->slider_g->value.getValue() ) this->slider_g->value.setValue(g);
++  if ( b != this->slider_b->value.getValue() ) this->slider_b->value.setValue(b);
++  if ( h != this->slider_h->value.getValue() ) this->slider_h->value.setValue(h);
++  if ( s != this->slider_s->value.getValue() ) this->slider_s->value.setValue(s);
++  if ( v != this->slider_v->value.getValue() ) this->slider_v->value.setValue(v);
++  if ( wheel != this->slider_wheel->value.getValue() ) this->slider_wheel->value.setValue(wheel);
++
++  assert(PUBLIC(this) != NULL);
++  if ( PUBLIC(this)->wysiwyg.getValue() ) {
++    this->generateSliderTextureR(color, TRUE);
++    this->generateSliderTextureG(color, TRUE);
++    this->generateSliderTextureB(color, TRUE);
++    this->generateSliderTextureH(color, TRUE);
++    this->generateSliderTextureS(color, TRUE);
++    this->generateSliderTextureV(color, TRUE);
++    this->generateSliderTextureHSV(color, TRUE);
++  }
++
++  this->sensor_r->attach(&(this->slider_r->value));
++  this->sensor_g->attach(&(this->slider_g->value));
++  this->sensor_b->attach(&(this->slider_b->value));
++  this->sensor_h->attach(&(this->slider_h->value));
++  this->sensor_s->attach(&(this->slider_s->value));
++  this->sensor_v->attach(&(this->slider_v->value));
++  this->sensor_wheel->attach(&(this->slider_wheel->value));
++}
++
++void
++ColorEditor::color_update_cb(void * closure, SoSensor * sensor)
++{
++  assert(closure != NULL);
++  ColorEditor * me = (ColorEditor *) closure;
++  me->colorChange();
++}
++
++// *************************************************************************
++
++void
++ColorEditor::update_r_cb(void * closure, SoSensor * sensor)
++{
++  ColorEditor * me = (ColorEditor *) closure;
++  float r, g, b;
++  SbColor color = PUBLIC(me)->color.getValue();
++  color.getValue(r, g, b);
++  r = me->slider_r->value.getValue();
++  color.setValue(r, g, b);
++  PUBLIC(me)->color.setValue(color);
++}
++
++void
++ColorEditor::update_g_cb(void * closure, SoSensor * sensor)
++{
++  ColorEditor * me = (ColorEditor *) closure;
++  float r, g, b;
++  SbColor color = PUBLIC(me)->color.getValue();
++  color.getValue(r, g, b);
++  g = me->slider_g->value.getValue();
++  color.setValue(r, g, b);
++  PUBLIC(me)->color.setValue(color);
++}
++
++void
++ColorEditor::update_b_cb(void * closure, SoSensor * sensor)
++{
++  ColorEditor * me = (ColorEditor *) closure;
++  float r, g, b;
++  SbColor color = PUBLIC(me)->color.getValue();
++  color.getValue(r, g, b);
++  b = me->slider_b->value.getValue();
++  color.setValue(r, g, b);
++  PUBLIC(me)->color.setValue(color);
++}
++
++void
++ColorEditor::update_h_cb(void * closure, SoSensor * sensor)
++{
++  ColorEditor * me = (ColorEditor *) closure;
++  float h, s, v;
++  SbColor color = PUBLIC(me)->color.getValue();
++  color.getHSVValue(h, s, v);
++  h = me->slider_h->value.getValue();
++  color.setHSVValue(h, s, v);
++  PUBLIC(me)->color.setValue(color);
++}
++
++void
++ColorEditor::update_s_cb(void * closure, SoSensor * sensor)
++{
++  ColorEditor * me = (ColorEditor *) closure;
++  float h, s, v;
++  SbColor color = PUBLIC(me)->color.getValue();
++  color.getHSVValue(h, s, v);
++  s = me->slider_s->value.getValue();
++  color.setHSVValue(h, s, v);
++  PUBLIC(me)->color.setValue(color);
++}
++
++void
++ColorEditor::update_v_cb(void * closure, SoSensor * sensor)
++{
++  ColorEditor * me = (ColorEditor *) closure;
++  float h, s, v;
++  SbColor color = PUBLIC(me)->color.getValue();
++  color.getHSVValue(h, s, v);
++  v = me->slider_v->value.getValue();
++  color.setHSVValue(h, s, v);
++  PUBLIC(me)->color.setValue(color);
++}
++
++void
++ColorEditor::update_wheel_cb(void * closure, SoSensor * sensor)
++{
++  ColorEditor * me = (ColorEditor *) closure;
++  SbVec2f value = me->slider_wheel->value.getValue();
++  value = value * 2.0f - SbVec2f(1.0f, 1.0f);
++  if ( value.length() > 1.0f ) {
++    value.normalize();
++    SbVec2f reverse = (value + SbVec2f(1.0f, 1.0f)) / 2.0f;
++    me->slider_wheel->value.setValue(reverse);
++  }
++  float h;
++  if ( value[0] == 0.0f ) h = ((value[1] < 0.0f) ? 3.0f : 1.0f) * float(M_PI) / 2.0f;
++  else h = (float) atan(value[1] / value[0]);
++  if ( value[0] < 0.0f ) h += float(M_PI); 
++  if ( h < 0.0f ) h += (2.0f * float(M_PI));
++  h /= 2.0f * float(M_PI); 
++  float s = So at Gui@Min(value.length(), 1.0f); // float precision bugfix
++
++  float a = 0.0f, b = 0.0f, v = 1.0f;
++  SbColor existing = PUBLIC(me)->color.getValue();
++  existing.getHSVValue(a, b, v);
++
++  SbColor color;
++  color.setHSVValue(h, s, v);
++  PUBLIC(me)->color.setValue(color);
++}
++
++// *************************************************************************
++
++float
++ColorEditor::calculateHue(float x, float y)
++{
++  float hue;
++  if ( x == 0.0f ) hue = ((y < 0.0f) ? 3.0f : 1.0f) * float(M_PI) / 2.0f;
++  else hue = (float) atan(y / x);
++  if ( x < 0.0f ) hue += float(M_PI); 
++  if ( hue < 0.0f ) hue += (2.0f * float(M_PI));
++  return hue / (2.0f * float(M_PI)); 
++}
++
++SbVec2f
++ColorEditor::calculateFromHue(float h, float s, float v)
++{
++  float hue = h * 2.0f * float(M_PI);
++  return SbVec2f(((float) cos(hue) * s + 1.0f) / 2.0f, ((float) sin(hue) * s + 1.0f) / 2.0f);
++}
++
++// *************************************************************************
++
++void
++ColorEditor::generateSliderTextureR(const SbColor & current, SbBool wysiwyg)
++{
++  assert(this->slider_r != NULL);
++  float red, green, blue;
++  current.getValue(red, green, blue);
++  if ( ! wysiwyg ) {
++    green = blue = 0.0f;
++  }
++  SoTexture2 * texture = SO_GET_PART(this->slider_r, "surfaceTexture", SoTexture2);
++  assert(texture);
++  texture->wrapS.setValue(SoTexture2::CLAMP);
++  texture->wrapT.setValue(SoTexture2::CLAMP);
++  SbVec2s size(256, 1);
++  int nc = 3;
++  texture->image.setValue(size, nc, NULL);
++  texture->model.setValue(SoTexture2::DECAL);
++  unsigned char * bytes = texture->image.startEditing(size, nc);
++  int x, y;
++  for ( x = 0; x < size[0]; x++ ) { 
++    red = (float) x / (float) (size[0] - 1);
++    for ( y = 0; y < size[1]; y++ ) { 
++      bytes[(size[0]*y+x)*nc+0] = (unsigned char) (red * 255.0f);
++      bytes[(size[0]*y+x)*nc+1] = (unsigned char) (green * 255.0f);
++      bytes[(size[0]*y+x)*nc+2] = (unsigned char) (blue * 255.0f);
++      // if ( nc > 3 ) bytes[(size[0]*y+x)*nc+4] = 255;
++    }
++  }
++  texture->image.finishEditing();
++}
++
++void
++ColorEditor::generateSliderTextureG(const SbColor & current, SbBool wysiwyg)
++{
++  assert(this->slider_g != NULL);
++  float red, green, blue;
++  current.getValue(red, green, blue);
++  if ( ! wysiwyg ) {
++    red = blue = 0.0f;
++  }
++  SoTexture2 * texture = SO_GET_PART(this->slider_g, "surfaceTexture", SoTexture2);
++  assert(texture);
++  texture->wrapS.setValue(SoTexture2::CLAMP);
++  texture->wrapT.setValue(SoTexture2::CLAMP);
++  SbVec2s size(256, 1);
++  int nc = 3;
++  texture->image.setValue(size, nc, NULL);
++  texture->model.setValue(SoTexture2::DECAL);
++  unsigned char * bytes = texture->image.startEditing(size, nc);
++  int x, y;
++  for ( x = 0; x < size[0]; x++ ) { 
++    green = (float) x / (float) (size[0] - 1);
++    for ( y = 0; y < size[1]; y++ ) { 
++      bytes[(size[0]*y+x)*nc+0] = (unsigned char) (red * 255.0f);
++      bytes[(size[0]*y+x)*nc+1] = (unsigned char) (green * 255.0f);
++      bytes[(size[0]*y+x)*nc+2] = (unsigned char) (blue * 255.0f);
++      // if ( nc > 3 ) bytes[(size[0]*y+x)*nc+4] = 255;
++    }
++  }
++  texture->image.finishEditing();
++}
++
++void
++ColorEditor::generateSliderTextureB(const SbColor & current, SbBool wysiwyg)
++{
++  assert(this->slider_b != NULL);
++  float red, green, blue;
++  current.getValue(red, green, blue);
++  if ( ! wysiwyg ) {
++    red = green = 0.0f;
++  }
++  SoTexture2 * texture = SO_GET_PART(this->slider_b, "surfaceTexture", SoTexture2);
++  assert(texture);
++  texture->wrapS.setValue(SoTexture2::CLAMP);
++  texture->wrapT.setValue(SoTexture2::CLAMP);
++  SbVec2s size(256, 1);
++  int nc = 3;
++  texture->image.setValue(size, nc, NULL);
++  texture->model.setValue(SoTexture2::DECAL);
++  unsigned char * bytes = texture->image.startEditing(size, nc);
++  int x, y;
++  for ( x = 0; x < size[0]; x++ ) { 
++    blue = (float) x / (float) (size[0] - 1);
++    for ( y = 0; y < size[1]; y++ ) { 
++      bytes[(size[0]*y+x)*nc+0] = (unsigned char) (red * 255.0f);
++      bytes[(size[0]*y+x)*nc+1] = (unsigned char) (green * 255.0f);
++      bytes[(size[0]*y+x)*nc+2] = (unsigned char) (blue * 255.0f);
++      // if ( nc > 3 ) bytes[(size[0]*y+x)*nc+4] = 255;
++    }
++  }
++  texture->image.finishEditing();
++}
++
++void
++ColorEditor::generateSliderTextureH(const SbColor & current, SbBool wysiwyg)
++{
++  assert(this->slider_h != NULL);
++  float hue, saturation, value;
++  current.getHSVValue(hue, saturation, value);
++  if ( ! wysiwyg ) {
++    saturation = 1.0f;
++    value = 1.0f;
++  }
++  SoTexture2 * texture = SO_GET_PART(this->slider_h, "surfaceTexture", SoTexture2);
++  assert(texture);
++  texture->wrapS.setValue(SoTexture2::CLAMP);
++  texture->wrapT.setValue(SoTexture2::CLAMP);
++  SbVec2s size(256, 1);
++  int nc = 3;
++  texture->image.setValue(size, nc, NULL);
++  texture->model.setValue(SoTexture2::DECAL);
++  unsigned char * bytes = texture->image.startEditing(size, nc);
++  int x, y;
++  for ( x = 0; x < size[0]; x++ ) { 
++    const float hue = (float) x / (float) (size[0] - 1);
++    for ( y = 0; y < size[1]; y++ ) { 
++      float r = 0.0f, g = 0.0f, b = 0.0f;
++      SbColor color(r, g, b); 
++      color.setHSVValue(hue, saturation, value);
++      color.getValue(r, g, b);
++      bytes[(size[0]*y+x)*nc+0] = (unsigned char) (r * 255.0f);
++      bytes[(size[0]*y+x)*nc+1] = (unsigned char) (g * 255.0f);
++      bytes[(size[0]*y+x)*nc+2] = (unsigned char) (b * 255.0f);
++      // if ( nc > 3 ) bytes[(size[0]*y+x)*nc+4] = 255;
++    }
++  }
++  texture->image.finishEditing();
++}
++
++void
++ColorEditor::generateSliderTextureS(const SbColor & current, SbBool wysiwyg)
++{
++  assert(this->slider_s != NULL);
++  float hue, saturation, value;
++  current.getHSVValue(hue, saturation, value);
++  if ( ! wysiwyg ) {
++    hue = 0.0f;
++    value = 1.0f;
++  }
++  SoTexture2 * texture = SO_GET_PART(this->slider_s, "surfaceTexture", SoTexture2);
++  assert(texture);
++  texture->wrapS.setValue(SoTexture2::CLAMP);
++  texture->wrapT.setValue(SoTexture2::CLAMP);
++  SbVec2s size(256, 1);
++  int nc = 3;
++  texture->image.setValue(size, nc, NULL);
++  texture->model.setValue(SoTexture2::DECAL);
++  unsigned char * bytes = texture->image.startEditing(size, nc);
++  int x, y;
++  for ( x = 0; x < size[0]; x++ ) { 
++    const float saturation = (float) x / (float) (size[0] - 1);
++    for ( y = 0; y < size[1]; y++ ) { 
++      float r = 0.0f, g = 0.0f, b = 0.0f;
++      SbColor color(r, g, b); 
++      color.setHSVValue(hue, saturation, value);
++      color.getValue(r, g, b);
++      bytes[(size[0]*y+x)*nc+0] = (unsigned char) (r * 255.0f);
++      bytes[(size[0]*y+x)*nc+1] = (unsigned char) (g * 255.0f);
++      bytes[(size[0]*y+x)*nc+2] = (unsigned char) (b * 255.0f);
++      // if ( nc > 3 ) bytes[(size[0]*y+x)*nc+4] = 255;
++    }
++  }
++  texture->image.finishEditing();
++}
++
++void
++ColorEditor::generateSliderTextureV(const SbColor & current, SbBool wysiwyg)
++{
++  assert(this->slider_v != NULL);
++  float hue, saturation, value;
++  current.getHSVValue(hue, saturation, value);
++  if ( ! wysiwyg ) {
++    hue = 0.0f;
++    saturation = 1.0f;
++  }
++  SoTexture2 * texture = SO_GET_PART(this->slider_v, "surfaceTexture", SoTexture2);
++  assert(texture);
++  texture->wrapS.setValue(SoTexture2::CLAMP);
++  texture->wrapT.setValue(SoTexture2::CLAMP);
++  SbVec2s size(256, 1);
++  int nc = 3;
++  texture->image.setValue(size, nc, NULL);
++  texture->model.setValue(SoTexture2::DECAL);
++  unsigned char * bytes = texture->image.startEditing(size, nc);
++  int x, y;
++  for ( x = 0; x < size[0]; x++ ) { 
++    const float value = (float) x / (float) (size[0] - 1);
++    for ( y = 0; y < size[1]; y++ ) { 
++      float r = 0.0f, g = 0.0f, b = 0.0f;
++      SbColor color(r, g, b); 
++      color.setHSVValue(hue, saturation, value);
++      color.getValue(r, g, b);
++      bytes[(size[0]*y+x)*nc+0] = (unsigned char) (r * 255.0f);
++      bytes[(size[0]*y+x)*nc+1] = (unsigned char) (g * 255.0f);
++      bytes[(size[0]*y+x)*nc+2] = (unsigned char) (b * 255.0f);
++      // if ( nc > 3 ) bytes[(size[0]*y+x)*nc+4] = 255;
++    }
++  }
++  texture->image.finishEditing();
++}
++
++void
++ColorEditor::generateSliderTextureHSV(const SbColor & current, SbBool wysiwyg)
++{
++  assert(this->slider_wheel != NULL);
++  float hue, saturation, value;
++  current.getHSVValue(hue, saturation, value);
++  if ( ! wysiwyg ) {
++    value = 1.0f;
++  }
++
++  SoTexture2 * texture = SO_GET_PART(this->slider_wheel, "surfaceTexture", SoTexture2);
++  assert(texture);
++  texture->wrapS.setValue(SoTexture2::CLAMP);
++  texture->wrapT.setValue(SoTexture2::CLAMP);
++  SbVec2s size(256, 256);
++  int nc = 3;
++  texture->image.setValue(size, nc, NULL);
++  texture->model.setValue(SoTexture2::DECAL);
++  unsigned char * bytes = texture->image.startEditing(size, nc);
++  int x, y;
++  const float halfx = (float) size[0] / 2.0f;
++  const float halfy = (float) size[1] / 2.0f;
++  for ( y = 0; y < size[1]; y++ ) { 
++    const float ypos = ((float) y - halfy) / halfy;
++    for ( x = 0; x < size[0]; x++ ) { 
++      const float xpos = ((float) x - halfx) / halfx; 
++      const float saturation = (float) sqrt(xpos * xpos + ypos * ypos);
++      float hue = ColorEditor::calculateHue(xpos, ypos);
++      float red = 0.0f, green = 0.0f, blue = 0.0f;
++      SbColor color(red, green, blue); 
++      if ( saturation <= 1.0f ) color.setHSVValue(hue, saturation, value);
++      color.getValue(red, green, blue);
++      bytes[(size[0]*y+x)*nc+0] = (unsigned char) (red * 255.0f);
++      bytes[(size[0]*y+x)*nc+1] = (unsigned char) (green * 255.0f);
++      bytes[(size[0]*y+x)*nc+2] = (unsigned char) (blue * 255.0f);
++      // if ( nc > 3 ) bytes[(size[0]*y+x)*nc+4] = 255;
++    }
++  }
++  texture->image.finishEditing();
++}
++
++// *************************************************************************
++
++#undef PUBLIC
++#undef PRIVATE
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/ColorEditor.h.in
+@@ -0,0 +1,79 @@
++#ifndef COIN_SOGUICOLOREDITOR_H
++#define COIN_SOGUICOLOREDITOR_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/fields/SoSFBool.h>
++#include <Inventor/fields/SoSFEnum.h>
++#include <Inventor/fields/SoSFColor.h>
++#include <Inventor/nodekits/SoBaseKit.h>
++
++class SoGuiColorEditor : public SoBaseKit {
++  typedef SoBaseKit inherited;
++  SO_KIT_HEADER(SoGuiColorEditor);
++  SO_KIT_CATALOG_ENTRY_HEADER(root);
++
++public:
++  static void initClass(void);
++  SoGuiColorEditor(void);
++
++  enum Sliders {
++    NONE,
++    INTENSITY,
++    RGB,
++    HSV,
++    RGB_V,
++    RGB_HSV
++  };
++
++  enum Update {
++    CONTINUOUS,
++    AFTER_ACCEPT
++  };
++
++  SoSFEnum sliders;
++  SoSFEnum update;
++  SoSFBool wysiwyg;
++  SoSFColor color;
++
++protected:
++  ~SoGuiColorEditor(void);
++
++private:
++  void * internals;
++
++};
++
++#endif // !COIN_SOGUICOLOREDITOR_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Frame.cpp.in
+@@ -0,0 +1,257 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/elements/SoLazyElement.h>
++#include <Inventor/misc/SoState.h>
++#include <Inventor/actions/SoGLRenderAction.h>
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoCoordinate3.h>
++#include <Inventor/nodes/SoMaterial.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++
++#include <Inventor/@Gui@/common/gl.h>
++#include <Inventor/@Gui@/SoAny.h>
++#include <Inventor/@Gui@/nodes/SoGuiFrame.h>
++#include <assert.h>
++
++// *************************************************************************
++
++class Frame {
++public:
++  SoGuiFrame * api;
++
++  SoCoordinate3 * coords;
++  SoMaterial * light;
++  SoMaterial * shade;
++
++  SoFieldSensor * size_sensor;
++  SoFieldSensor * width_sensor;
++  static void size_updated_cb(void * closure, SoSensor * sensor);
++
++  SoFieldSensor * design_sensor;
++  static void design_updated_cb(void * closure, SoSensor * sensor);
++  SoFieldSensor * complement_sensor;
++
++  static const char * scene[];
++};
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((Frame *)obj->internals)
++
++void
++SoGuiFrame::initClass(void)
++{
++  SO_KIT_INIT_CLASS(SoGuiFrame, SoBaseKit, "BaseKit");
++}
++
++SO_KIT_SOURCE(SoGuiFrame);
++
++SoGuiFrame::SoGuiFrame(void)
++{
++  this->internals = new Frame;
++  PRIVATE(this)->api = this;
++
++  SO_KIT_CONSTRUCTOR(SoGuiFrame);
++
++  SO_KIT_ADD_FIELD(size, (SbVec3f(0.0f, 0.0f, 0.0f)));
++  SO_KIT_ADD_FIELD(design, (SoGuiFrame::BLACK));
++  SO_KIT_ADD_FIELD(width, (1.0f));
++  SO_KIT_ADD_FIELD(complement, (FALSE));
++
++  SO_KIT_DEFINE_ENUM_VALUE(FrameDesign, BLACK);
++  SO_KIT_DEFINE_ENUM_VALUE(FrameDesign, COLOR);
++  SO_KIT_DEFINE_ENUM_VALUE(FrameDesign, EMBOSS);
++
++  SO_KIT_SET_SF_ENUM_TYPE(design, FrameDesign);
++
++  SO_KIT_ADD_CATALOG_ENTRY(scene, SoSeparator, TRUE, this, "", FALSE);
++
++  SO_KIT_INIT_INSTANCE();
++
++  SoNode * node = SoAny::loadSceneGraph(Frame::scene);
++  assert(node);
++
++  this->setAnyPart("scene", node);
++
++  PRIVATE(this)->coords = (SoCoordinate3 *) SoAny::scanSceneForName(node, "coordinates");
++  PRIVATE(this)->light = (SoMaterial *) SoAny::scanSceneForName(node, "light");
++  PRIVATE(this)->shade = (SoMaterial *) SoAny::scanSceneForName(node, "shade");
++
++  assert(PRIVATE(this)->coords);
++  assert(PRIVATE(this)->light);
++  assert(PRIVATE(this)->shade);
++  
++  PRIVATE(this)->coords->ref();
++  PRIVATE(this)->light->ref();
++  PRIVATE(this)->shade->ref();
++
++  PRIVATE(this)->size_sensor = new SoFieldSensor(Frame::size_updated_cb, PRIVATE(this));
++  PRIVATE(this)->size_sensor->attach(&(this->size));
++  PRIVATE(this)->width_sensor = new SoFieldSensor(Frame::size_updated_cb, PRIVATE(this));
++  PRIVATE(this)->width_sensor->attach(&(this->size));
++  PRIVATE(this)->design_sensor = new SoFieldSensor(Frame::design_updated_cb, PRIVATE(this));
++  PRIVATE(this)->design_sensor->attach(&(this->design));
++  PRIVATE(this)->complement_sensor = new SoFieldSensor(Frame::design_updated_cb, PRIVATE(this));
++  PRIVATE(this)->complement_sensor->attach(&(this->complement));
++  this->design.touch();
++}
++
++SoGuiFrame::~SoGuiFrame(void)
++{
++  PRIVATE(this)->coords->unref();
++  PRIVATE(this)->light->unref();
++  PRIVATE(this)->shade->unref();
++  delete PRIVATE(this)->size_sensor;
++  delete PRIVATE(this)->width_sensor;
++  delete PRIVATE(this)->design_sensor;
++  delete PRIVATE(this)->complement_sensor;
++  Frame * obj = PRIVATE(this);
++  delete obj;
++}
++
++#undef PRIVATE
++
++// *************************************************************************
++
++#define PUBLIC(obj) ((SoGuiFrame *)obj->api)
++
++const char *
++Frame::scene[] =
++{
++  "#Inventor V2.1 ascii",
++  "",
++  "Separator {",
++  "  DEF coordinates Coordinate3 {",
++  "    point [",
++  "      0 0 0,",
++  "      1 0 0,",
++  "      1 1 0,",
++  "      0 1 0,",
++  "      -1 -1 0,",
++  "      2 -1 0,",
++  "      2 2 0,",
++  "      -1 2 0",
++  "    ]",
++  "  }",
++  // shadow
++  "  DEF shade Material {",
++  "    diffuseColor 0.9 0.9 0.9",
++  "  }",
++  "  IndexedFaceSet {",
++  "    coordIndex [",
++  "      4 5 1 -1",
++  "      4 1 0 -1",
++  "      5 6 2 -1",
++  "      5 2 1 -1",
++  "    ]",
++  "  }",
++  // light
++  "  DEF light Material {",
++  "    diffuseColor 0.5 0.5 0.5",
++  "  }",
++  "  IndexedFaceSet {",
++  "    coordIndex [",
++  "      6 7 3 -1",
++  "      6 3 2 -1",
++  "      7 4 0 -1",
++  "      7 0 3 -1",
++  "    ]",
++  "  }",
++  "}",
++  NULL
++};
++
++void
++Frame::size_updated_cb(void * closure, SoSensor * sensor)
++{
++  assert(closure != NULL);
++  Frame * me = (Frame *) closure;
++  SoCoordinate3 * coords = me->coords;
++  assert(coords);
++  SbVec3f size = PUBLIC(me)->size.getValue();
++  float width = PUBLIC(me)->width.getValue();
++  SbBool save = coords->point.enableNotify(FALSE);
++  coords->point.set1Value(1, SbVec3f(size[0], 0.0f, 0.0f));
++  coords->point.set1Value(2, SbVec3f(size[0], size[1], 0.0f));
++  coords->point.set1Value(3, SbVec3f(0.0f, size[1], 0.0f));
++  coords->point.set1Value(4, SbVec3f(-width, -width, 0.0f));
++  coords->point.set1Value(5, SbVec3f(size[0]+width, -width, 0.0f));
++  coords->point.set1Value(6, SbVec3f(size[0]+width, size[1]+width, 0.0f));
++  coords->point.set1Value(7, SbVec3f(-width, size[1]+width, 0.0f));
++  coords->point.enableNotify(save);
++  if ( save ) coords->point.touch();
++}
++
++void
++Frame::design_updated_cb(void * closure, SoSensor * sensor)
++{
++  assert(closure != NULL);
++  Frame * me = (Frame *) closure;
++  SoMaterial * light = me->light;
++  SoMaterial * shade = me->shade;
++  assert(light);
++  assert(shade);
++  switch ( PUBLIC(me)->design.getValue() ) {
++  case SoGuiFrame::EMBOSS:
++    if ( PUBLIC(me)->complement.getValue() ) {
++      light->diffuseColor.setValue(SbColor(0.5f, 0.5f, 0.5f));
++      shade->diffuseColor.setValue(SbColor(0.9f, 0.9f, 0.9f));
++    } else {
++      light->diffuseColor.setValue(SbColor(0.9f, 0.9f, 0.9f));
++      shade->diffuseColor.setValue(SbColor(0.5f, 0.5f, 0.5f));
++    }
++    break;
++  case SoGuiFrame::BLACK:
++    if ( PUBLIC(me)->complement.getValue() ) {
++      light->diffuseColor.setValue(SbColor(1.0f, 0.0f, 0.0f));
++      shade->diffuseColor.setValue(SbColor(1.0f, 0.0f, 0.0f));
++    } else {
++      light->diffuseColor.setValue(SbColor(0.0f, 0.0f, 0.0f));
++      shade->diffuseColor.setValue(SbColor(0.0f, 0.0f, 0.0f));
++    }
++    break;
++  default:
++    break;
++  }
++}
++
++#undef PUBLIC
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Frame.h.in
+@@ -0,0 +1,80 @@
++#ifndef COIN_SOGUIFRAME_H
++#define COIN_SOGUIFRAME_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/fields/SoSFBool.h>
++#include <Inventor/fields/SoSFEnum.h>
++#include <Inventor/fields/SoSFFloat.h>
++#include <Inventor/fields/SoSFVec3f.h>
++
++#include <Inventor/nodekits/SoBaseKit.h>
++
++class SoGuiFrame : public SoBaseKit {
++  typedef SoBaseKit inherited;
++
++  SO_KIT_HEADER(SoGuiFrame);
++
++  SO_KIT_CATALOG_ENTRY_HEADER(scene);
++
++public:
++  static void initClass(void);
++
++  SoGuiFrame(void);
++
++  enum FrameDesign {
++    BLACK,
++    COLOR,
++    EMBOSS
++  };
++
++  SoSFVec3f size;
++  SoSFFloat width;
++  SoSFEnum design;
++  SoSFBool complement;
++
++protected:
++  virtual ~SoGuiFrame(void);
++
++private:
++  void * internals;
++
++};
++
++#endif // !COIN_SOGUIFRAME_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Image.cpp.in
+@@ -0,0 +1,164 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoTexture2.h>
++#include <Inventor/nodes/SoCoordinate3.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++
++#include <Inventor/@Gui@/SoAny.h>
++#include <Inventor/@Gui@/nodes/SoGuiImage.h>
++#include <assert.h>
++
++// *************************************************************************
++
++class Image {
++public:
++  Image(void);
++
++  SoGuiImage * api;
++
++  SoFieldSensor * size_sensor;
++  static void size_updated_cb(void * closure, SoSensor * sensor);
++
++  SoCoordinate3 * coords;
++
++  static const char * geometryscene[];
++};
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((Image *)obj->internals)
++
++void
++SoGuiImage::initClass(void)
++{
++  SO_KIT_INIT_CLASS(SoGuiImage, SoBaseKit, "BaseKit");
++}
++
++SO_KIT_SOURCE(SoGuiImage);
++
++SoGuiImage::SoGuiImage(void)
++{
++  this->internals = new Image;
++  PRIVATE(this)->api = this;
++
++  SO_KIT_CONSTRUCTOR(SoGuiImage);
++  SO_KIT_ADD_FIELD(size, (SbVec3f(1.0f, 1.0f, 0.0f)));
++
++  SO_KIT_ADD_CATALOG_ENTRY(geometry, SoGroup, FALSE, topSeparator, "", FALSE);
++  SO_KIT_ADD_CATALOG_ENTRY(texture, SoTexture2, FALSE, topSeparator, geometry, TRUE);
++  SO_KIT_ADD_CATALOG_ENTRY(topSeparator, SoSeparator, FALSE, this, "", FALSE);
++
++  SO_KIT_INIT_INSTANCE();
++
++  SoNode * geometryroot = SoAny::loadSceneGraph(Image::geometryscene);
++  assert(geometryroot);
++  geometryroot->ref();
++  geometryroot->isOfType(SoSeparator::getClassTypeId());
++  SoNode * realgeometry = ((SoSeparator *) geometryroot)->getChild(0);
++  assert(realgeometry);
++  realgeometry->ref();
++
++  PRIVATE(this)->coords = (SoCoordinate3 *) SoAny::scanSceneForName(realgeometry, "coords");
++  assert(PRIVATE(this)->coords);
++  assert(PRIVATE(this)->coords->isOfType(SoCoordinate3::getClassTypeId()));
++
++  realgeometry->unrefNoDelete();
++  SbBool ok = this->setAnyPart("geometry", realgeometry);
++  assert(ok);
++  geometryroot->unref();
++
++  PRIVATE(this)->size_sensor = new SoFieldSensor(Image::size_updated_cb, PRIVATE(this));
++  PRIVATE(this)->size_sensor->attach(&(this->size));
++}
++
++SoGuiImage::~SoGuiImage(void)
++{
++  delete PRIVATE(this)->size_sensor;
++  Image * obj = PRIVATE(this);
++  delete obj;
++}
++
++#undef PRIVATE
++
++// *************************************************************************
++
++#define PUBLIC(obj) (obj->api)
++
++const char *
++Image::geometryscene[] =
++{
++  "#Inventor V2.1 ascii",
++  "",
++  "Group {",
++  "  DEF coords Coordinate3 {",
++  "    point [ 0 0 0, 1 0 0, 1 1 0, 0 1 0 ]",
++  "  }",
++  "  TextureCoordinate2 {",
++  "    point [ 0 0, 1 0, 1 1, 0 1 ]",
++  "  }",
++  "  IndexedFaceSet {",
++  "    coordIndex [ 0 1 2 -1 0 2 3 -1 ]",
++  "    textureCoordIndex [ 0 1 2 -1 0 2 3 -1 ]",
++  "  }",
++  "}",
++  NULL
++};
++
++Image::Image(void)
++{
++  this->api = NULL;
++  this->size_sensor = NULL;
++  this->coords = NULL;
++}
++
++void
++Image::size_updated_cb(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  Image * me = (Image *) closure;
++  SbVec3f size = PUBLIC(me)->size.getValue();
++  SbBool save = me->coords->point.enableNotify(FALSE);
++  me->coords->point.set1Value(1, SbVec3f(size[0], 0.0f, 0.0f));
++  me->coords->point.set1Value(2, SbVec3f(size[0], size[1], 0.0f));
++  me->coords->point.set1Value(3, SbVec3f(0.0f, size[1], 0.0f));
++  me->coords->point.enableNotify(save);
++  if ( save ) me->coords->point.touch();
++}
++
++#undef PUBLIC
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Image.h.in
+@@ -0,0 +1,68 @@
++#ifndef COIN_SOGUIIMAGE_H
++#define COIN_SOGUIIMAGE_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/fields/SoSFVec3f.h>
++#include <Inventor/nodekits/SoBaseKit.h>
++
++class SoGuiImage : public SoBaseKit {
++  typedef SoBaseKit inherited;
++
++  SO_KIT_HEADER(SoGuiImage);
++
++  SO_KIT_CATALOG_ENTRY_HEADER(topSeparator);
++  SO_KIT_CATALOG_ENTRY_HEADER(texture);
++  SO_KIT_CATALOG_ENTRY_HEADER(geometry);
++
++public:
++  static void initClass(void);
++  SoGuiImage(void);
++
++  SoSFVec3f size;
++
++protected:
++  virtual ~SoGuiImage(void);
++
++private:
++  void * internals;
++
++};
++
++#endif // !COIN_SOGUIIMAGE_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Label.cpp.in
+@@ -0,0 +1,154 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <assert.h>
++
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoAsciiText.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++
++#include <Inventor/@Gui@/SoAny.h>
++#include <Inventor/@Gui@/nodes/SoGuiLabel.h>
++
++// *************************************************************************
++
++class Label {
++public:
++  Label(void);
++
++  SoGuiLabel * api;
++
++  SoAsciiText * text;
++
++  SoFieldSensor * text_sensor;
++  SoFieldSensor * which_sensor;
++  static void text_updated_cb(void * closure, SoSensor * sensor);
++
++  static const char * scene[];
++};
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((Label *)this->internals)
++
++void
++SoGuiLabel::initClass(void)
++{
++  SO_KIT_INIT_CLASS(SoGuiLabel, SoBaseKit, "BaseKit");
++}
++
++SO_KIT_SOURCE(SoGuiLabel);
++
++SoGuiLabel::SoGuiLabel(void)
++{
++  this->internals = new Label;
++  PRIVATE(this)->api = this;
++
++  SO_KIT_CONSTRUCTOR(SoGuiLabel);
++  SO_KIT_ADD_FIELD(text, (""));
++  SO_KIT_ADD_FIELD(which, (0));
++
++  SO_KIT_ADD_CATALOG_ENTRY(scene, SoSeparator, FALSE, this, "", FALSE);
++
++  SO_KIT_INIT_INSTANCE();
++
++  SoNode * thescene = SoAny::loadSceneGraph(Label::scene);
++  assert(thescene);
++  thescene->ref();
++
++  PRIVATE(this)->text = (SoAsciiText *) SoAny::scanSceneForName(thescene, "text");
++  assert(PRIVATE(this)->text);
++
++  thescene->unrefNoDelete();
++  SbBool ok = this->setAnyPart("scene", thescene);
++  assert(ok);
++
++  PRIVATE(this)->text_sensor = new SoFieldSensor(Label::text_updated_cb, PRIVATE(this));
++  PRIVATE(this)->text_sensor->attach(&(this->text));
++  PRIVATE(this)->which_sensor = new SoFieldSensor(Label::text_updated_cb, PRIVATE(this));
++  PRIVATE(this)->which_sensor->attach(&(this->which));
++  Label::text_updated_cb(PRIVATE(this), NULL);
++}
++
++SoGuiLabel::~SoGuiLabel(void)
++{
++  delete PRIVATE(this)->text_sensor;
++  delete PRIVATE(this)->which_sensor;
++  Label * obj = PRIVATE(this);
++  delete obj;
++}
++
++#undef PRIVATE
++
++// *************************************************************************
++
++#define PUBLIC(obj) (obj->api)
++
++const char *
++Label::scene[] =
++{
++  "#Inventor V2.1 ascii",
++  "",
++  "Separator {",
++  "  SoGuiTranslation { translation 1 1 0 }",
++  "  Scale { scaleFactor 1.5 1.5 1 }",
++  "  BaseColor { rgb 0 0 0 }",
++  "  DEF text AsciiText { }",
++  "}",
++  NULL
++};
++
++Label::Label(void)
++{
++  this->api = NULL;
++  this->text = NULL;
++  this->which_sensor = NULL;
++}
++
++void
++Label::text_updated_cb(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  Label * me = (Label *) closure;
++  assert(me->text);
++  int which = PUBLIC(me)->which.getValue();
++  // SbString string = PUBLIC(me)->text.getValue();
++  SbString string = PUBLIC(me)->text[which];
++  me->text->string.setValue(string);
++}
++
++#undef PUBLIC
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Label.h.in
+@@ -0,0 +1,66 @@
++#ifndef COIN_SOGUILABEL_H
++#define COIN_SOGUILABEL_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif // !SO at GUI@_INTERNAL
++
++#include <Inventor/fields/SoSFShort.h>
++#include <Inventor/fields/SoMFString.h>
++#include <Inventor/nodekits/SoBaseKit.h>
++
++class SoGuiLabel : public SoBaseKit {
++  typedef SoBaseKit inherited;
++  SO_KIT_HEADER(SoGuiLabel);
++  SO_KIT_CATALOG_ENTRY_HEADER(scene);
++
++public:
++  static void initClass(void);
++  SoGuiLabel(void);
++
++  SoMFString text;
++  SoSFShort which;
++
++protected:
++  ~SoGuiLabel(void);
++
++private:
++  void * internals;
++
++};
++
++#endif // !COIN_SOGUILABEL_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/MaterialEditor.cpp.in
+@@ -0,0 +1,898 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <assert.h>
++
++#include <Inventor/nodes/SoMaterial.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++#include <Inventor/sensors/SoNodeSensor.h>
++#ifdef HAVE_SOVRMLMATERIAL
++#include <Inventor/VRMLnodes/SoVRMLMaterial.h>
++#endif // HAVE_SOVRMLMATERIAL
++
++#include <Inventor/@Gui@/SoAny.h>
++#include <Inventor/@Gui@/nodes/SoGuiPane.h>
++#include <Inventor/@Gui@/nodes/SoGuiImage.h>
++#include <Inventor/@Gui@/nodes/SoGuiSceneTexture2.h>
++#include <Inventor/@Gui@/nodes/SoGuiSlider1.h>
++#include <Inventor/@Gui@/nodes/SoGuiToggleButton.h>
++#include <Inventor/@Gui@/nodes/SoGuiRadioButton.h>
++#include <Inventor/@Gui@/nodes/SoGuiColorEditor.h>
++
++#include <Inventor/@Gui@/nodes/SoGuiMaterialEditor.h>
++
++// *************************************************************************
++
++class MaterialEditor {
++public:
++  MaterialEditor(void);
++  ~MaterialEditor(void);
++
++  SoGuiMaterialEditor * api;
++
++  SoMaterial * material;
++  SoNodeSensor * material_sensor;
++  static void material_cb(void * closure, SoSensor * sensor);
++
++  SoFieldSensor * material_field_sensor;
++  static void material_field_cb(void * closure, SoSensor * sensor);
++
++  SoGuiToggleButton * button1;
++  SoGuiToggleButton * button2;
++  SoGuiToggleButton * button3;
++  SoGuiToggleButton * button4;
++  SoFieldSensor * button1_sensor;
++  SoFieldSensor * button2_sensor;
++  SoFieldSensor * button3_sensor;
++  SoFieldSensor * button4_sensor;
++  static void button1_cb(void * closure, SoSensor * sensor);
++  static void button2_cb(void * closure, SoSensor * sensor);
++  static void button3_cb(void * closure, SoSensor * sensor);
++  static void button4_cb(void * closure, SoSensor * sensor);
++  SoGuiRadioButton * radio1;
++  SoGuiRadioButton * radio2;
++  SoGuiRadioButton * radio3;
++  SoGuiRadioButton * radio4;
++
++  SoGuiSlider1 * slider1;
++  SoGuiSlider1 * slider2;
++  SoGuiSlider1 * slider3;
++  SoGuiSlider1 * slider4;
++  SoGuiSlider1 * slider5;
++  SoGuiSlider1 * slider6;
++  SoFieldSensor * ambient_slider_sensor;
++  SoFieldSensor * diffuse_slider_sensor;
++  SoFieldSensor * specular_slider_sensor;
++  SoFieldSensor * emissive_slider_sensor;
++  SoFieldSensor * shininess_slider_sensor;
++  SoFieldSensor * transparency_slider_sensor;
++  static void ambient_slider_cb(void * closure, SoSensor * sensor);
++  static void diffuse_slider_cb(void * closure, SoSensor * sensor);
++  static void specular_slider_cb(void * closure, SoSensor * sensor);
++  static void emissive_slider_cb(void * closure, SoSensor * sensor);
++  static void shininess_slider_cb(void * closure, SoSensor * sensor);
++  static void transparency_slider_cb(void * closure, SoSensor * sensor);
++
++  SoGuiColorEditorOpenCB * openeditorcb;
++  SoGuiColorEditorCloseCB * closeeditorcb;
++  void * cbclosure;
++
++  static SoGuiColorEditor * coloreditoropen_cb(void * closure);
++  static void coloreditorclose_cb(void * closure, SoGuiColorEditor * editor);
++
++  SbBool coloreditoropen;
++  SoGuiColorEditor * coloreditor;
++  SoFieldSensor * coloreditor_sensor;
++  static void coloreditor_cb(void * closure, SoSensor * sensor);
++
++  void checkColorEditorOpenStatus(void);
++
++  static const char * texturescene[];
++  static const char * editorscene[];
++};
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((MaterialEditor *) ((SoGuiMaterialEditor *) obj)->internals)
++
++void
++SoGuiMaterialEditor::initClass(void)
++{
++  SO_KIT_INIT_CLASS(SoGuiMaterialEditor, SoBaseKit, "BaseKit");
++}
++
++SO_KIT_SOURCE(SoGuiMaterialEditor);
++
++SoGuiMaterialEditor::SoGuiMaterialEditor(void)
++{
++  this->internals = new MaterialEditor;
++  PRIVATE(this)->api = this;
++
++  SO_KIT_CONSTRUCTOR(SoGuiMaterialEditor); 
++
++  SO_KIT_ADD_FIELD(material, (NULL));
++  SO_KIT_ADD_FIELD(index, (0));
++  SO_KIT_ADD_FIELD(update, (CONTINUOUS));
++      
++  SO_KIT_DEFINE_ENUM_VALUE(Update, CONTINUOUS);
++  SO_KIT_DEFINE_ENUM_VALUE(Update, AFTER_ACCEPT);
++
++  SO_KIT_SET_SF_ENUM_TYPE(update, Update);
++
++  SO_KIT_ADD_CATALOG_ENTRY(root, SoGuiPane, TRUE, this, "", FALSE);
++
++  SO_KIT_INIT_INSTANCE(); 
++
++  SoNode * scene = SoAny::loadSceneGraph(MaterialEditor::editorscene);
++  assert(scene != NULL);
++  assert(scene->isOfType(SoGuiPane::getClassTypeId()));
++  scene->ref();
++
++  SoGuiImage * sphereimage =
++    (SoGuiImage *) SoAny::scanSceneForName(scene, "image");
++  assert(sphereimage != NULL);
++  scene->unrefNoDelete();
++  SbBool ok = this->setAnyPart("root", scene);
++  assert(ok);
++
++  PRIVATE(this)->button1 = (SoGuiToggleButton *) SoAny::scanSceneForName(scene, "tbutton1");
++  PRIVATE(this)->button2 = (SoGuiToggleButton *) SoAny::scanSceneForName(scene, "tbutton2");
++  PRIVATE(this)->button3 = (SoGuiToggleButton *) SoAny::scanSceneForName(scene, "tbutton3");
++  PRIVATE(this)->button4 = (SoGuiToggleButton *) SoAny::scanSceneForName(scene, "tbutton4");
++  assert(PRIVATE(this)->button1);
++  assert(PRIVATE(this)->button2);
++  assert(PRIVATE(this)->button3);
++  assert(PRIVATE(this)->button4);
++  PRIVATE(this)->radio1 = (SoGuiRadioButton *) SoAny::scanSceneForName(scene, "rbutton1");
++  PRIVATE(this)->radio2 = (SoGuiRadioButton *) SoAny::scanSceneForName(scene, "rbutton2");
++  PRIVATE(this)->radio3 = (SoGuiRadioButton *) SoAny::scanSceneForName(scene, "rbutton3");
++  PRIVATE(this)->radio4 = (SoGuiRadioButton *) SoAny::scanSceneForName(scene, "rbutton4");
++  assert(PRIVATE(this)->radio1);
++  assert(PRIVATE(this)->radio2);
++  assert(PRIVATE(this)->radio3);
++  assert(PRIVATE(this)->radio4);
++
++  PRIVATE(this)->slider1 = (SoGuiSlider1 *) SoAny::scanSceneForName(scene, "slider1");
++  PRIVATE(this)->slider2 = (SoGuiSlider1 *) SoAny::scanSceneForName(scene, "slider2");
++  PRIVATE(this)->slider3 = (SoGuiSlider1 *) SoAny::scanSceneForName(scene, "slider3");
++  PRIVATE(this)->slider4 = (SoGuiSlider1 *) SoAny::scanSceneForName(scene, "slider4");
++  PRIVATE(this)->slider5 = (SoGuiSlider1 *) SoAny::scanSceneForName(scene, "slider5");
++  PRIVATE(this)->slider6 = (SoGuiSlider1 *) SoAny::scanSceneForName(scene, "slider6");
++  assert(PRIVATE(this)->slider1);
++  assert(PRIVATE(this)->slider2);
++  assert(PRIVATE(this)->slider3);
++  assert(PRIVATE(this)->slider4);
++  assert(PRIVATE(this)->slider5);
++  assert(PRIVATE(this)->slider6);
++  PRIVATE(this)->slider1->setSurfaceColor(SbColor(0,0,0), SbColor(1,1,1));
++  PRIVATE(this)->slider2->setSurfaceColor(SbColor(0,0,0), SbColor(1,1,1));
++  PRIVATE(this)->slider3->setSurfaceColor(SbColor(0,0,0), SbColor(1,1,1));
++  PRIVATE(this)->slider4->setSurfaceColor(SbColor(0,0,0), SbColor(1,1,1));
++  PRIVATE(this)->slider5->setSurfaceColor(SbColor(0,0,0), SbColor(1,1,1));
++  PRIVATE(this)->slider6->setSurfaceColor(SbColor(0,0,0), SbColor(1,1,1));
++
++  SoNode * textureroot = SoAny::loadSceneGraph(MaterialEditor::texturescene);
++  assert(textureroot != NULL);
++  assert(textureroot->isOfType(SoSeparator::getClassTypeId()));
++  SoNode * texture = ((SoSeparator *) textureroot)->getChild(0);
++  assert(texture != NULL);
++  assert(texture->isOfType(SoGuiSceneTexture2::getClassTypeId()));
++
++  SoNode * subscene = ((SoGuiSceneTexture2 *) texture)->scene.getValue();
++  assert(subscene);
++  subscene->ref();
++  PRIVATE(this)->material = (SoMaterial *) SoAny::scanSceneForName(subscene, "material");
++  subscene->unrefNoDelete();
++  assert(PRIVATE(this)->material);
++
++  ok = sphereimage->setPart("texture", texture);
++  assert(ok);
++
++  PRIVATE(this)->ambient_slider_sensor = new SoFieldSensor(MaterialEditor::ambient_slider_cb, PRIVATE(this));
++  PRIVATE(this)->diffuse_slider_sensor = new SoFieldSensor(MaterialEditor::diffuse_slider_cb, PRIVATE(this));
++  PRIVATE(this)->specular_slider_sensor = new SoFieldSensor(MaterialEditor::specular_slider_cb, PRIVATE(this));
++  PRIVATE(this)->emissive_slider_sensor = new SoFieldSensor(MaterialEditor::emissive_slider_cb, PRIVATE(this));
++  PRIVATE(this)->shininess_slider_sensor = new SoFieldSensor(MaterialEditor::shininess_slider_cb, PRIVATE(this));
++  PRIVATE(this)->transparency_slider_sensor = new SoFieldSensor(MaterialEditor::transparency_slider_cb, PRIVATE(this));
++  PRIVATE(this)->ambient_slider_sensor->attach(&(PRIVATE(this)->slider1->value));
++  PRIVATE(this)->diffuse_slider_sensor->attach(&(PRIVATE(this)->slider2->value));
++  PRIVATE(this)->specular_slider_sensor->attach(&(PRIVATE(this)->slider3->value));
++  PRIVATE(this)->emissive_slider_sensor->attach(&(PRIVATE(this)->slider4->value));
++  PRIVATE(this)->shininess_slider_sensor->attach(&(PRIVATE(this)->slider5->value));
++  PRIVATE(this)->transparency_slider_sensor->attach(&(PRIVATE(this)->slider6->value));
++
++  PRIVATE(this)->button1_sensor = new SoFieldSensor(MaterialEditor::button1_cb, PRIVATE(this));
++  PRIVATE(this)->button2_sensor = new SoFieldSensor(MaterialEditor::button2_cb, PRIVATE(this));
++  PRIVATE(this)->button3_sensor = new SoFieldSensor(MaterialEditor::button3_cb, PRIVATE(this));
++  PRIVATE(this)->button4_sensor = new SoFieldSensor(MaterialEditor::button4_cb, PRIVATE(this));
++  PRIVATE(this)->button1_sensor->attach(&(PRIVATE(this)->button1->on));
++  PRIVATE(this)->button2_sensor->attach(&(PRIVATE(this)->button2->on));
++  PRIVATE(this)->button3_sensor->attach(&(PRIVATE(this)->button3->on));
++  PRIVATE(this)->button4_sensor->attach(&(PRIVATE(this)->button4->on));
++
++  PRIVATE(this)->material_sensor = new SoNodeSensor(MaterialEditor::material_cb, PRIVATE(this));
++  PRIVATE(this)->material_sensor->attach(PRIVATE(this)->material);
++  PRIVATE(this)->material->touch();
++
++  PRIVATE(this)->material_field_sensor = new SoFieldSensor(MaterialEditor::material_field_cb, PRIVATE(this));
++  PRIVATE(this)->material_field_sensor->attach(&(this->material));
++
++  this->setColorEditorCallbacks(MaterialEditor::coloreditoropen_cb, MaterialEditor::coloreditorclose_cb, PRIVATE(this));
++}
++
++SoGuiMaterialEditor::~SoGuiMaterialEditor(void)
++{
++  MaterialEditor * obj = PRIVATE(this);
++  delete obj;
++}
++
++void
++SoGuiMaterialEditor::setColorEditorCallbacks(
++  SoGuiColorEditorOpenCB * open,
++  SoGuiColorEditorCloseCB * close,
++  void * closure)
++{
++  PRIVATE(this)->openeditorcb = open;
++  PRIVATE(this)->closeeditorcb = close;
++  PRIVATE(this)->cbclosure = closure;
++}
++
++SoMaterial *
++SoGuiMaterialEditor::getSphereMaterialNode(void) const
++{
++  return PRIVATE(this)->material;
++}
++
++// *************************************************************************
++// MaterialEditor
++// *************************************************************************
++
++#define PUBLIC(obj) (((MaterialEditor *) obj)->api)
++
++// +--------------------------------------------------------------------+
++// |                   |  o x  Ambient    |======================| 0.00 |
++// |                   |  o x  Diffuse    |======================| 0.00 |
++// |                   |  o x  Specular   |======================| 0.00 |
++// |                   |  o x  Emissive   |======================| 0.00 |
++// |                   |                                                |
++// |                   |       Shininess  |======================| 0.00 |
++// |                   |       Transp     |======================| 0.00 |
++// +--------------------------------------------------------------------+
++//                                                          [nice - Ed]
++
++const char *
++MaterialEditor::texturescene[] =
++{
++  "#Inventor V2.1 ascii",
++  "",
++  "SoGuiSceneTexture2 {",
++  "  scene",
++  "    Separator {",
++  "      OrthographicCamera {",
++  "        position 0 0 2",
++  "        nearDistance 1",
++  "        farDistance 3",
++  "        height 2",
++  "      }",
++  "      LightModel { model BASE_COLOR }",
++  "      BaseColor {",
++  "        rgb [ 0.3 0.3 0.3,  0.6 0.6 0.6,  0.6 0.6 0.6,  0.3 0.3 0.3 ]",
++  "      }",
++  "      MaterialBinding { value PER_FACE }",
++  "      Coordinate3 {",
++  "        point [",
++  "          -3  3  0,  0  3  0,  3  3  0,",
++  "          -3  0  0,  0  0  0,  3  0  0,",
++  "          -3 -3  0,  0 -3  0,  3 -3  0",
++  "        ]",
++  "      }",
++  "      QuadMesh {",
++  "        verticesPerColumn 3",
++  "        verticesPerRow 3",
++  "      }",
++  "      LightModel { model PHONG }",
++  "      DirectionalLight { direction  0.556 -0.623 -0.551 }",
++  "      DirectionalLight { direction -0.556 -0.623 -0.551 }",
++  "      DEF material Material { }",
++  "      Complexity { value 0.8 }",
++  "      ShapeHints { vertexOrdering COUNTERCLOCKWISE shapeType SOLID }",
++  "      Sphere { radius 0.85 }",
++  "    }",
++  "  }",
++  "}",
++  NULL
++};
++
++// FIXME: add labels
++// FIXME: adjust geometry
++
++const char *
++MaterialEditor::editorscene[] =
++{
++  "#Inventor V2.1 ascii",
++  "",
++  "DEF pane SoGuiPane {",
++  "  worldSize 1 1 0",
++  "  objectSize 550 300 0",
++  "  SoGuiPosition {",
++  "    position = DEF wm Calculator {",
++  "      A = USE pane.objectSize",
++  "      expression [",
++  "        \"ta = (A[0] / 2 < A[1]) ? (A[0]/2)-20 : A[1]-20\"",
++  "        \"tb = (A[1] - ta) / 2\"",
++  "        \"oA = vec3f(10, tb, 0)\"", // image position
++  "        \"oB = vec3f(ta, ta, 0)\"", // image size
++  "        \"oC = vec3f(ta + 30, A[1] - 25, 0)\"", // radio1 position
++  "        \"oD = vec3f(0, -30, 0)\"", // ratio translation
++  "      ]",
++  "    } . oA",
++  "  }",
++  "  DEF image SoGuiImage { size = USE wm.oB }",
++  "  SoGuiFrame {",
++  "    size = USE image.size",
++  "    design EMBOSS",
++  "    width 2",
++  "    complement TRUE",
++  "  }",
++  "  SoGuiPosition { position = USE wm.oC }",
++  "  DEF rbutton1 SoGuiRadioButton {",
++  "    size 10 10 0",
++  "    on = DEF rbuttons SoGuiRadioGroup {",
++  "      in0 = USE rbutton1.on",
++  "      in1 = DEF rbutton2 SoGuiRadioButton { size 10 10 0 on = USE rbuttons.out1 } . on",
++  "      in2 = DEF rbutton3 SoGuiRadioButton { size 10 10 0 on = USE rbuttons.out2 } . on",
++  "      in3 = DEF rbutton4 SoGuiRadioButton { size 10 10 0 on = USE rbuttons.out3 } . on",
++  "    } . out0",
++  "  }",
++  "  SoGuiFrame {",
++  "    size = USE rbutton1.size",
++  "    width 2",
++  "    complement = USE rbutton1.on",
++  "  }",
++  "  SoGuiTranslation { translation = USE wm.oD }",
++  "  USE rbutton2",
++  "  SoGuiFrame {",
++  "    size = USE rbutton2.size",
++  "    width 2",
++  "    complement = USE rbutton2.on",
++  "  }",
++  "  SoGuiTranslation { translation = USE wm.oD }",
++  "  USE rbutton3",
++  "  SoGuiFrame {",
++  "    size = USE rbutton3.size",
++  "    width 2",
++  "    complement = USE rbutton3.on",
++  "  }",
++  "  SoGuiTranslation { translation = USE wm.oD }",
++  "  USE rbutton4",
++  "  SoGuiFrame {",
++  "    size = USE rbutton4.size",
++  "    width 2",
++  "    complement = USE rbutton4.on",
++  "  }",
++  "  SoGuiPosition {",
++  "    position = DEF wm2 Calculator {",
++  "      A = USE pane.objectSize",
++  "      expression [",
++  "        \"ta = (A[0] / 2 < A[1]) ? (A[0]/2)-20 : A[1]-20\"",
++  "        \"oA = vec3f(ta + 60, A[1] - 25, 0)\"",
++  "        \"oB = vec3f(ta + 90, A[1] - 25, 0)\"",
++  "        \"oC = vec3f(ta - 100, 15, 0)\"",
++  "      ]",
++  "    } . oA",
++  "  }",
++  "  DEF tbutton1 SoGuiToggleButton {",
++  "    size 10 10 0"
++  "    on = USE rbuttons.out0",
++  "  }",
++  "  SoGuiFrame {",
++  "    size = USE tbutton1.size",
++  "    width 2",
++  "    complement = USE tbutton1.on",
++  "    design EMBOSS",
++  "  }",
++  "  SoGuiTranslation { translation = USE wm.oD }",
++  "  DEF tbutton2 SoGuiToggleButton {",
++  "    size 10 10 0"
++  "    on = USE rbuttons.out1",
++  "  }",
++  "  SoGuiFrame {",
++  "    size = USE tbutton2.size",
++  "    width 2",
++  "    complement = USE tbutton2.on",
++  "    design EMBOSS",
++  "  }",
++  "  SoGuiTranslation { translation = USE wm.oD }",
++  "  DEF tbutton3 SoGuiToggleButton {",
++  "    size 10 10 0"
++  "    on = USE rbuttons.out2",
++  "  }",
++  "  SoGuiFrame {",
++  "    size = USE tbutton3.size",
++  "    width 2",
++  "    complement = USE tbutton3.on",
++  "    design EMBOSS",
++  "  }",
++  "  SoGuiTranslation { translation = USE wm.oD }",
++  "  DEF tbutton4 SoGuiToggleButton {",
++  "    size 10 10 0"
++  "    on = USE rbuttons.out3",
++  "  }",
++  "  SoGuiFrame {",
++  "    size = USE tbutton4.size",
++  "    width 2",
++  "    complement = USE tbutton4.on",
++  "    design EMBOSS",
++  "  }",
++
++  "  SoGuiPosition { position = USE wm2.oB }",
++  "  DEF sliderframe SoGuiFrame {",
++  "    size = USE wm2.oC",
++  "    width 2",
++  "    complement TRUE",
++  "    design EMBOSS",
++  "  }",
++  "  DEF slider1 SoGuiSlider1 { size = USE sliderframe.size }",
++  "  SoGuiTranslation { translation = USE wm.oD }",
++  "  USE sliderframe",
++  "  DEF slider2 SoGuiSlider1 { size = USE sliderframe.size }",
++  "  SoGuiTranslation { translation = USE wm.oD }",
++  "  USE sliderframe",
++  "  DEF slider3 SoGuiSlider1 { size = USE sliderframe.size }",
++  "  SoGuiTranslation { translation = USE wm.oD }",
++  "  USE sliderframe",
++  "  DEF slider4 SoGuiSlider1 { size = USE sliderframe.size }",
++  "  SoGuiTranslation { translation = USE wm.oD }",
++  "  SoGuiTranslation { translation = USE wm.oD }",
++  "  USE sliderframe",
++  "  DEF slider5 SoGuiSlider1 { size = USE sliderframe.size }",
++  "  SoGuiTranslation { translation = USE wm.oD }",
++  "  USE sliderframe",
++  "  DEF slider6 SoGuiSlider1 { size = USE sliderframe.size }",
++
++  "  SoGuiPosition { position = USE pane.objectSize }",
++  "  SoGuiTranslation { translation -35 -25 0 }",
++  "  DEF labelframe SoGuiFrame { size 25 15 0 width 2 design EMBOSS complement TRUE }",
++  "  SoGuiLabel { text = SoGuiFormat { format \"%4.2f\" float1 = USE slider1.value } . output }",
++  "  SoGuiTranslation { translation = USE wm.oD }",
++  "  USE labelframe",
++  "  SoGuiLabel { text = SoGuiFormat { format \"%4.2f\" float1 = USE slider2.value } . output }",
++  "  SoGuiTranslation { translation = USE wm.oD }",
++  "  USE labelframe",
++  "  SoGuiLabel { text = SoGuiFormat { format \"%4.2f\" float1 = USE slider3.value } . output }",
++  "  SoGuiTranslation { translation = USE wm.oD }",
++  "  USE labelframe",
++  "  SoGuiLabel { text = SoGuiFormat { format \"%4.2f\" float1 = USE slider4.value } . output }",
++  "  SoGuiTranslation { translation = USE wm.oD }",
++  "  SoGuiTranslation { translation = USE wm.oD }",
++  "  USE labelframe",
++  "  SoGuiLabel { text = SoGuiFormat { format \"%4.2f\" float1 = USE slider5.value } . output }",
++  "  SoGuiTranslation { translation = USE wm.oD }",
++  "  USE labelframe",
++  "  SoGuiLabel { text = SoGuiFormat { format \"%4.2f\" float1 = USE slider6.value } . output }",
++  "}",
++  NULL
++};
++
++MaterialEditor::MaterialEditor(void)
++{
++  this->api = NULL;
++  this->material = NULL;
++  this->button1 = NULL;
++  this->button2 = NULL;
++  this->button3 = NULL;
++  this->button4 = NULL;
++  this->radio1 = NULL;
++  this->radio2 = NULL;
++  this->radio3 = NULL;
++  this->radio4 = NULL;
++  this->slider1 = NULL;
++  this->slider2 = NULL;
++  this->slider3 = NULL;
++  this->slider4 = NULL;
++  this->slider5 = NULL;
++  this->slider6 = NULL;
++  this->ambient_slider_sensor = NULL;
++  this->diffuse_slider_sensor = NULL;
++  this->specular_slider_sensor = NULL;
++  this->emissive_slider_sensor = NULL;
++  this->shininess_slider_sensor = NULL;
++  this->transparency_slider_sensor = NULL;
++  this->coloreditoropen = FALSE;
++  this->coloreditor = NULL;
++  this->coloreditor_sensor = NULL;
++}
++
++MaterialEditor::~MaterialEditor(void)
++{
++  if ( this->coloreditor_sensor ) delete this->coloreditor_sensor;
++}
++
++void
++MaterialEditor::ambient_slider_cb(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  MaterialEditor * me = (MaterialEditor *) closure;
++  assert(me->material);
++  assert(me->slider1);
++  SbColor ambient = me->material->ambientColor[0];
++  float h, s, v;
++  ambient.getHSVValue(h, s, v);
++  v = me->slider1->value.getValue();
++  ambient.setHSVValue(h, s, v);
++  if ( ambient != me->material->ambientColor[0] )
++    me->material->ambientColor.set1Value(0, ambient);
++}
++
++void
++MaterialEditor::diffuse_slider_cb(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  MaterialEditor * me = (MaterialEditor *) closure;
++  assert(me->material);
++  assert(me->slider2);
++  SbColor diffuse = me->material->diffuseColor[0];
++  float h, s, v;
++  diffuse.getHSVValue(h, s, v);
++  v = me->slider2->value.getValue();
++  diffuse.setHSVValue(h, s, v);
++  if ( diffuse != me->material->diffuseColor[0] )
++    me->material->diffuseColor.set1Value(0, diffuse);
++}
++
++void
++MaterialEditor::specular_slider_cb(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  MaterialEditor * me = (MaterialEditor *) closure;
++  assert(me->material);
++  assert(me->slider3);
++  SbColor specular = me->material->specularColor[0];
++  float h, s, v;
++  specular.getHSVValue(h, s, v);
++  v = me->slider3->value.getValue();
++  specular.setHSVValue(h, s, v);
++  if ( specular != me->material->specularColor[0] )
++    me->material->specularColor.set1Value(0, specular);
++}
++
++void
++MaterialEditor::emissive_slider_cb(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  MaterialEditor * me = (MaterialEditor *) closure;
++  assert(me->material);
++  assert(me->slider4);
++  SbColor emissive = me->material->emissiveColor[0];
++  float h, s, v;
++  emissive.getHSVValue(h, s, v);
++  v = me->slider4->value.getValue();
++  emissive.setHSVValue(h, s, v);
++  if ( emissive != me->material->emissiveColor[0] )
++    me->material->emissiveColor.set1Value(0, emissive);
++}
++
++void
++MaterialEditor::shininess_slider_cb(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  MaterialEditor * me = (MaterialEditor *) closure;
++  assert(me->material);
++  assert(me->slider5);
++  float shininess = me->slider5->value.getValue();
++  if ( shininess != me->material->shininess[0] )
++    me->material->shininess.set1Value(0, shininess);
++}
++
++void
++MaterialEditor::transparency_slider_cb(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  MaterialEditor * me = (MaterialEditor *) closure;
++  assert(me->material);
++  assert(me->slider6);
++  float transparency = me->slider6->value.getValue();
++  if ( transparency != me->material->transparency[0] )
++    me->material->transparency.set1Value(0, transparency);
++}
++
++void
++MaterialEditor::checkColorEditorOpenStatus(void)
++{
++  if ( this->button1->on.getValue() ||
++       this->button2->on.getValue() ||
++       this->button3->on.getValue() ||
++       this->button4->on.getValue() ) {
++    if ( !this->coloreditoropen && this->openeditorcb ) {
++      this->coloreditor = this->openeditorcb(this->cbclosure);
++      this->coloreditoropen = TRUE;
++      if ( this->coloreditor_sensor == NULL )
++        this->coloreditor_sensor = new SoFieldSensor(MaterialEditor::coloreditor_cb, this);
++      if ( this->coloreditor )
++        this->coloreditor_sensor->attach(&(this->coloreditor->color));
++    }
++  } else {
++    if ( this->coloreditoropen && this->closeeditorcb ) {
++      if ( this->coloreditor_sensor ) this->coloreditor_sensor->detach();
++      this->closeeditorcb(this->cbclosure, this->coloreditor);
++      this->coloreditor = NULL;
++      this->coloreditoropen = FALSE;
++    }
++  }
++}
++
++void
++MaterialEditor::button1_cb(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  MaterialEditor * me = (MaterialEditor *) closure;
++  SbBool down = me->button1->on.getValue();
++  if ( !down ) {
++    if ( me->radio1->on.getValue() ) me->radio1->on.setValue(FALSE);
++
++    if (  me->button2->on.getValue() &&
++         !me->button3->on.getValue() &&
++         !me->button4->on.getValue() &&
++         !me->radio2->on.getValue() ) me->radio2->on.setValue(TRUE);
++    if ( !me->button2->on.getValue() &&
++          me->button3->on.getValue() &&
++         !me->button4->on.getValue() &&
++         !me->radio3->on.getValue() ) me->radio3->on.setValue(TRUE);
++    if ( !me->button2->on.getValue() &&
++         !me->button3->on.getValue() &&
++          me->button4->on.getValue() &&
++         !me->radio4->on.getValue() ) me->radio4->on.setValue(TRUE);
++  } else {
++    if ( me->radio2->on.getValue() ) me->radio2->on.setValue(FALSE);
++    if ( me->radio3->on.getValue() ) me->radio3->on.setValue(FALSE);
++    if ( me->radio4->on.getValue() ) me->radio4->on.setValue(FALSE);
++    if ( !me->button2->on.getValue() &&
++         !me->button3->on.getValue() &&
++         !me->button4->on.getValue() &&
++         !me->radio1->on.getValue() ) me->radio1->on.setValue(TRUE);
++  }
++  me->checkColorEditorOpenStatus();
++}
++
++void
++MaterialEditor::button2_cb(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  MaterialEditor * me = (MaterialEditor *) closure;
++  SbBool down = me->button2->on.getValue();
++  if ( !down ) {
++    if ( me->radio2->on.getValue() ) me->radio2->on.setValue(FALSE);
++    if (  me->button1->on.getValue() &&
++         !me->button3->on.getValue() &&
++         !me->button4->on.getValue() &&
++         !me->radio1->on.getValue() ) me->radio1->on.setValue(TRUE);
++    if ( !me->button1->on.getValue() &&
++          me->button3->on.getValue() &&
++         !me->button4->on.getValue() &&
++         !me->radio3->on.getValue() ) me->radio3->on.setValue(TRUE);
++    if ( !me->button1->on.getValue() &&
++         !me->button3->on.getValue() &&
++          me->button4->on.getValue() &&
++         !me->radio4->on.getValue() ) me->radio4->on.setValue(TRUE);
++  } else {
++    if ( me->radio1->on.getValue() ) me->radio1->on.setValue(FALSE);
++    if ( me->radio3->on.getValue() ) me->radio3->on.setValue(FALSE);
++    if ( me->radio4->on.getValue() ) me->radio4->on.setValue(FALSE);
++    if ( !me->button1->on.getValue() &&
++         !me->button3->on.getValue() &&
++         !me->button4->on.getValue() &&
++         !me->radio2->on.getValue() ) me->radio2->on.setValue(TRUE);
++  }
++  me->checkColorEditorOpenStatus();
++}
++
++void
++MaterialEditor::button3_cb(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  assert(closure);
++  MaterialEditor * me = (MaterialEditor *) closure;
++  SbBool down = me->button3->on.getValue();
++  if ( !down ) {
++    if ( me->radio3->on.getValue() ) me->radio3->on.setValue(FALSE);
++    if (  me->button1->on.getValue() &&
++         !me->button2->on.getValue() &&
++         !me->button4->on.getValue() &&
++         !me->radio1->on.getValue() ) me->radio1->on.setValue(TRUE);
++    if ( !me->button1->on.getValue() &&
++          me->button2->on.getValue() &&
++         !me->button4->on.getValue() &&
++         !me->radio2->on.getValue() ) me->radio2->on.setValue(TRUE);
++    if ( !me->button1->on.getValue() &&
++         !me->button2->on.getValue() &&
++          me->button4->on.getValue() &&
++         !me->radio4->on.getValue() ) me->radio4->on.setValue(TRUE);
++  } else {
++    if ( me->radio1->on.getValue() ) me->radio1->on.setValue(FALSE);
++    if ( me->radio2->on.getValue() ) me->radio2->on.setValue(FALSE);
++    if ( me->radio4->on.getValue() ) me->radio4->on.setValue(FALSE);
++    if ( !me->button1->on.getValue() &&
++         !me->button2->on.getValue() &&
++         !me->button4->on.getValue() &&
++         !me->radio3->on.getValue() ) me->radio3->on.setValue(TRUE);
++  }
++  me->checkColorEditorOpenStatus();
++}
++
++void
++MaterialEditor::button4_cb(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  MaterialEditor * me = (MaterialEditor *) closure;
++  SbBool down = me->button4->on.getValue();
++  if ( !down ) {
++    if ( me->radio4->on.getValue() ) me->radio4->on.setValue(FALSE);
++    if (  me->button1->on.getValue() &&
++         !me->button2->on.getValue() &&
++         !me->button3->on.getValue() &&
++         !me->radio1->on.getValue() ) me->radio1->on.setValue(TRUE);
++    if ( !me->button1->on.getValue() &&
++          me->button2->on.getValue() &&
++         !me->button3->on.getValue() &&
++         !me->radio2->on.getValue()  ) me->radio2->on.setValue(TRUE);
++    if ( !me->button1->on.getValue() &&
++         !me->button2->on.getValue() &&
++          me->button3->on.getValue() &&
++         !me->radio3->on.getValue() ) me->radio3->on.setValue(TRUE);
++  } else {
++    if ( me->radio1->on.getValue() ) me->radio1->on.setValue(FALSE);
++    if ( me->radio2->on.getValue() ) me->radio2->on.setValue(FALSE);
++    if ( me->radio3->on.getValue() ) me->radio3->on.setValue(FALSE);
++    if ( !me->button1->on.getValue() &&
++         !me->button2->on.getValue() &&
++         !me->button3->on.getValue() &&
++         !me->radio4->on.getValue() ) me->radio4->on.setValue(TRUE);
++  }
++  me->checkColorEditorOpenStatus();
++}
++
++void
++MaterialEditor::coloreditor_cb(void * closure, SoSensor * sensor)
++{
++  // coloreditor is being interacted with - so update material editor sliders
++  assert(closure);
++  MaterialEditor * me = (MaterialEditor *) closure;
++  if ( me->button1->on.getValue() )
++    me->material->ambientColor.setValue(me->coloreditor->color.getValue());
++  if ( me->button2->on.getValue() )
++    me->material->diffuseColor.setValue(me->coloreditor->color.getValue());
++  if ( me->button3->on.getValue() )
++    me->material->specularColor.setValue(me->coloreditor->color.getValue());
++  if ( me->button4->on.getValue() )
++    me->material->emissiveColor.setValue(me->coloreditor->color.getValue());
++}
++  
++void
++MaterialEditor::material_cb(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  MaterialEditor * me = (MaterialEditor *) closure;
++  SoMaterial * mat = me->material;
++  if ( !mat ) return;
++  float h, s, v;
++  SbColor color = mat->ambientColor[0];
++  color.getHSVValue(h, s, v);
++  if ( v != me->slider1->value.getValue() ) me->slider1->value.setValue(v);
++  color = mat->diffuseColor[0];
++  color.getHSVValue(h, s, v);
++  if ( v != me->slider2->value.getValue() ) me->slider2->value.setValue(v);
++  color = mat->specularColor[0];
++  color.getHSVValue(h, s, v);
++  if ( v != me->slider3->value.getValue() ) me->slider3->value.setValue(v);
++  color = mat->emissiveColor[0];
++  color.getHSVValue(h, s, v);
++  if ( v != me->slider4->value.getValue() ) me->slider4->value.setValue(v);
++  v = mat->shininess[0];
++  if ( v != me->slider5->value.getValue() ) me->slider5->value.setValue(v);
++  v = mat->transparency[0];
++  if ( v != me->slider6->value.getValue() ) me->slider6->value.setValue(v);
++  SoNode * attachment = PUBLIC(me)->material.getValue();
++  if ( attachment ) {
++    if ( attachment->isOfType(SoMaterial::getClassTypeId()) ) {
++      SoMaterial * material = (SoMaterial *) attachment;
++      int index = PUBLIC(me)->index.getValue();
++      material->ambientColor.set1Value(index, mat->ambientColor[0]);
++      material->diffuseColor.set1Value(index, mat->diffuseColor[0]);
++      material->specularColor.set1Value(index, mat->specularColor[0]);
++      material->emissiveColor.set1Value(index, mat->emissiveColor[0]);
++      material->shininess.set1Value(index, mat->shininess[0]);
++      material->transparency.set1Value(index, mat->transparency[0]);
++#ifdef HAVE_SOVRMLMATERIAL
++    } else if ( attachment->isOfType(SoVRMLMaterial::getClassTypeId()) ) {
++      SoVRMLMaterial * material = (SoVRMLMaterial *) attachment;
++      SbColor ambient = mat->ambientColor[0];
++      float h, s, v;
++      ambient.getHSVValue(h, s, v);
++      material->ambientIntensity.setValue(v);
++      material->diffuseColor.setValue(mat->diffuseColor[0]);
++      material->specularColor.setValue(mat->specularColor[0]);
++      material->emissiveColor.setValue(mat->emissiveColor[0]);
++      material->shininess.setValue(mat->shininess[0]);
++      material->transparency.setValue(mat->transparency[0]);
++#endif // HAVE_SOVRMLMATERIAL
++    } else {
++    }
++  }
++}
++
++void
++MaterialEditor::material_field_cb(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  MaterialEditor * me = (MaterialEditor *) closure;
++  SoNode * node = PUBLIC(me)->material.getValue();
++  if ( !node ) return;
++  SoMaterial * mat1 = (SoMaterial *) node;
++  SoMaterial * mat2 = me->material;
++
++  if ( mat1->ambientColor[0] != mat2->ambientColor[0] )
++    mat2->ambientColor.set1Value(0, mat1->ambientColor[0]);
++  if ( mat1->diffuseColor[0] != mat2->diffuseColor[0] )
++    mat2->diffuseColor.set1Value(0, mat1->diffuseColor[0]);
++  if ( mat1->specularColor[0] != mat2->specularColor[0] )
++    mat2->specularColor.set1Value(0, mat1->specularColor[0]);
++  if ( mat1->emissiveColor[0] != mat2->emissiveColor[0] )
++    mat2->emissiveColor.set1Value(0, mat1->emissiveColor[0]);
++  if ( mat1->shininess[0] != mat2->shininess[0] )
++    mat2->shininess.set1Value(0, mat1->shininess[0]);
++  if ( mat1->transparency[0] != mat2->transparency[0] )
++    mat2->transparency.set1Value(0, mat1->transparency[0]);
++}
++
++SoGuiColorEditor *
++MaterialEditor::coloreditoropen_cb(void * closure)
++{
++  SoDebugError::postInfo("MaterialEditor::coloreditoropen_cb", "default callback invoked - not implemented yet");
++  return NULL;
++}
++
++void
++MaterialEditor::coloreditorclose_cb(void * closure, SoGuiColorEditor * editor)
++{
++  SoDebugError::postInfo("MaterialEditor::coloreditorclose_cb", "default callback invoked - not implemented yet");
++}
++
++#undef PRIVATE
++#undef PUBLIC
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/MaterialEditor.h.in
+@@ -0,0 +1,78 @@
++#ifndef COIN_SOGUIMATERIALEDITOR_H
++#define COIN_SOGUIMATERIALEDITOR_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/fields/SoSFEnum.h>
++#include <Inventor/fields/SoSFShort.h>
++#include <Inventor/fields/SoSFNode.h>
++#include <Inventor/nodekits/SoBaseKit.h>
++
++class SoMaterial;
++class SoGuiColorEditor;
++
++typedef SoGuiColorEditor * SoGuiColorEditorOpenCB(void * closure);
++typedef void SoGuiColorEditorCloseCB(void * closure, SoGuiColorEditor * editor);
++
++class SoGuiMaterialEditor : public SoBaseKit {
++  typedef SoBaseKit inherited;
++  SO_KIT_HEADER(SoGuiMaterialEditor);
++  SO_KIT_CATALOG_ENTRY_HEADER(root);
++
++public:
++  static void initClass(void);
++  SoGuiMaterialEditor(void);
++  
++  enum UpdateFrequency {
++    CONTINUOUS,
++    AFTER_ACCEPT
++  };
++
++  SoSFNode material;
++  SoSFShort index;
++  SoSFEnum update;
++
++  void setColorEditorCallbacks(SoGuiColorEditorOpenCB * open, SoGuiColorEditorCloseCB * close, void * closure);
++  SoMaterial * getSphereMaterialNode(void) const;
++
++protected:
++  ~SoGuiMaterialEditor(void);
++
++private:
++  void * internals;
++
++};
++
++#endif // !COIN_SOGUIMATERIALEDITOR_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Nodes.cpp.in
+@@ -0,0 +1,60 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/nodes/SoGuiNodes.h>
++
++// *************************************************************************
++
++void
++SoGuiNodes::initClasses(void)
++{
++  SoGuiSceneTexture2::initClass();
++  SoGuiViewportFix::initClass();
++  SoGuiPane::initClass();
++  SoGuiPosition::initClass();
++  SoGuiTranslation::initClass();
++  SoGuiFrame::initClass();
++  SoGuiImage::initClass();
++  SoGuiLabel::initClass();
++  SoGuiToggleButton::initClass();
++  SoGuiRadioButton::initClass();
++  SoGuiClickCounter::initClass();
++  SoGuiSlider1::initClass();
++  SoGuiSlider2::initClass();
++  SoGuiColorEditor::initClass();
++  SoGuiMaterialEditor::initClass();
++  SoGuiViewpointWrapper::initClass();
++}
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Nodes.h.in
+@@ -0,0 +1,65 @@
++#ifndef COIN_SOGUINODES_H
++#define COIN_SOGUINODES_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/@Gui@/nodes/SoGuiSceneTexture2.h>
++#include <Inventor/@Gui@/nodes/SoGuiViewportFix.h>
++#include <Inventor/@Gui@/nodes/SoGuiPane.h>
++#include <Inventor/@Gui@/nodes/SoGuiPosition.h>
++#include <Inventor/@Gui@/nodes/SoGuiTranslation.h>
++#include <Inventor/@Gui@/nodes/SoGuiFrame.h>
++#include <Inventor/@Gui@/nodes/SoGuiImage.h>
++#include <Inventor/@Gui@/nodes/SoGuiLabel.h>
++#include <Inventor/@Gui@/nodes/SoGuiToggleButton.h>
++#include <Inventor/@Gui@/nodes/SoGuiRadioButton.h>
++#include <Inventor/@Gui@/nodes/SoGuiClickCounter.h>
++#include <Inventor/@Gui@/nodes/SoGuiSlider1.h>
++#include <Inventor/@Gui@/nodes/SoGuiSlider2.h>
++#include <Inventor/@Gui@/nodes/SoGuiColorEditor.h>
++#include <Inventor/@Gui@/nodes/SoGuiMaterialEditor.h>
++#include <Inventor/@Gui@/nodes/SoGuiViewpointWrapper.h>
++
++class SoGuiNodes {
++public:
++  static void initClasses(void);
++
++};
++
++#endif // !COIN_SOGUINODES_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Pane.cpp.in
+@@ -0,0 +1,371 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/SbLinear.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/bundles/SoMaterialBundle.h>
++#include <Inventor/actions/SoGLRenderAction.h>
++#include <Inventor/actions/SoRayPickAction.h>
++#include <Inventor/actions/SoGetMatrixAction.h>
++#include <Inventor/actions/SoGetBoundingBoxAction.h>
++#include <Inventor/actions/SoHandleEventAction.h>
++#include <Inventor/elements/SoModelMatrixElement.h>
++#include <Inventor/elements/SoViewVolumeElement.h>
++#include <Inventor/misc/SoState.h>
++#include <Inventor/misc/SoChildList.h>
++
++#include <Inventor/@Gui@/common/gl.h>
++
++#include <Inventor/@Gui@/nodes/SoGuiPane.h>
++
++#define ZSCALE (1.0f)
++
++// *************************************************************************
++
++// FIXME: can't cache model matrix like this - use in multiple scene
++// graphs doesn't work then...
++
++class Pane {
++public:
++  SbMatrix modelmatrix;
++  SbVec3f position;
++  SbVec2f raypickpos;
++
++};
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((Pane *) obj->internals)
++
++SO_NODE_SOURCE(SoGuiPane);
++
++void
++SoGuiPane::initClass(void)
++{
++  SO_NODE_INIT_CLASS(SoGuiPane, SoSeparator, "Separator");
++}
++
++SoGuiPane::SoGuiPane(void)
++{
++  this->internals = (void *) new Pane;
++  SO_NODE_CONSTRUCTOR(SoGuiPane);
++  SO_NODE_ADD_FIELD(worldSize, (SbVec3f(1.0f, 1.0f, 0.0f)));
++  SO_NODE_ADD_FIELD(objectSize, (SbVec3f(100.0f, 100.0f, 0.0f)));
++}
++
++SoGuiPane::~SoGuiPane(void)
++{
++  Pane * obj = PRIVATE(this);
++  delete obj;
++  this->internals = NULL;
++}
++
++void
++SoGuiPane::doAction(SoAction * action)
++{
++  SoState * state = action->getState();
++
++  state->push();
++
++  if ( state->isElementEnabled(SoModelMatrixElement::getClassStackIndex()) ) {
++    SbVec3f world = this->worldSize.getValue();
++    SbVec3f object = this->objectSize.getValue();
++    SbVec3f scalefactor(world[0] / object[0], world[1] / object[1], ZSCALE);
++    SoModelMatrixElement::scaleBy(state, this, scalefactor);
++    PRIVATE(this)->modelmatrix = SoModelMatrixElement::get(state);
++  }
++
++  SbBool backface = FALSE;
++  if ( state->isElementEnabled(SoViewVolumeElement::getClassStackIndex()) ) {
++    SbVec3f normal(0.0f, 0.0f, 1.0f);
++    PRIVATE(this)->modelmatrix.multDirMatrix(normal, normal);
++    normal.normalize();
++    SbVec3f campos = SoViewVolumeElement::get(state).getProjectionPoint();
++    SbVec3f center = (SbVec3f(0.0f, 0.0f, 0.0f) + this->objectSize.getValue()) / 2.0f;
++    PRIVATE(this)->modelmatrix.multVecMatrix(center, center);
++    SbVec3f camdir = center - campos;
++    camdir.normalize();
++    backface = (normal.dot(camdir) >= 0.0f) ? TRUE : FALSE;
++  }
++
++  if ( action->isOfType(SoHandleEventAction::getClassTypeId()) ) {
++    if ( backface ) {
++      // we don't react to events when facing away
++      goto culled;
++    }
++  }
++
++  if ( action->isOfType(SoRayPickAction::getClassTypeId()) ) {
++    SoRayPickAction * rpaction = (SoRayPickAction *) action;
++    rpaction->setObjectSpace();
++
++    SbPlane plane(SbVec3f(0.0f, 0.0f, 1.0f), 0.0f);
++    SbLine line(rpaction->getLine());
++    // find intersection with SbPlane
++    SbVec3f point;
++    PRIVATE(this)->raypickpos.setValue(-1.0f, -1.0f);
++    if ( plane.intersect(line, point) ) {
++      SbVec3f object = this->objectSize.getValue();
++      SbVec2f pos(point[0], point[1]);
++      if ( pos[0] < 0.0f || pos[1] < 0.0f || pos[0] > object[0] || pos[1] > object[1] ) {
++        goto culled;
++      } else {
++        PRIVATE(this)->raypickpos = pos;
++      }
++    }
++    else goto culled;
++  }
++  inherited::doAction(action);
++culled:
++  state->pop();
++}
++
++void
++SoGuiPane::GLRenderBelowPath(SoGLRenderAction * action)
++{
++  SoState * state = action->getState();
++  state->push();
++
++  SbVec3f world = this->worldSize.getValue();
++  SbVec3f object = this->objectSize.getValue();
++
++  // adjust scale for new object space
++  SbVec3f scalefactor(world[0] / object[0], world[1] / object[1], ZSCALE);
++  SoModelMatrixElement::scaleBy(state, this, scalefactor);
++
++  // store current model matrix
++  PRIVATE(this)->modelmatrix = SoModelMatrixElement::get(state);
++  PRIVATE(this)->position = SbVec3f(0.0f, 0.0f, 0.0f);
++
++
++  SbVec3f normal(0.0f, 0.0f, 1.0f);
++  PRIVATE(this)->modelmatrix.multDirMatrix(normal, normal);
++  normal.normalize();
++
++  SbVec3f campos = SoViewVolumeElement::get(state).getProjectionPoint();
++  SbVec3f center = (SbVec3f(0.0f, 0.0f, 0.0f) + this->objectSize.getValue()) / 2.0f;
++  PRIVATE(this)->modelmatrix.multVecMatrix(center, center);
++
++  SbVec3f camdir = SoViewVolumeElement::get(state).getProjectionDirection();
++  camdir = center - campos;
++  camdir.normalize();
++
++  const float dot = normal.dot(camdir);
++
++  const SbBool backface = (dot >= 0.0f) ? TRUE : FALSE;
++
++  SoMaterialBundle mb(action);
++  mb.sendFirst();
++
++  if ( object[0] != 0.0f && object[1] != 0.0f ) { // draw pane
++    if ( backface ) glNormal3f(0.0f, 0.0f, -1.0f);
++    else glNormal3f(0.0f, 0.0f, 1.0f);
++    glBegin(GL_QUADS);
++    glVertex3f(0.0f, 0.0f, 0.0f);
++    glVertex3f(0.0f, object[1], 0.0f);
++    glVertex3f(object[0], object[1], 0.0f);
++    glVertex3f(object[0], 0.0f, 0.0f);
++    glEnd(); // GL_QUADS
++  }
++
++  if ( backface ) goto finish;
++
++  glDisable(GL_DEPTH_TEST);
++  glDepthMask(FALSE);
++
++  // TODO: it would probably be a good idea to set up clipping around the pane
++  inherited::GLRenderBelowPath(action);
++
++  glDepthMask(TRUE);
++  glEnable(GL_DEPTH_TEST);
++
++finish:
++  state->pop();
++}
++
++void
++SoGuiPane::GLRenderInPath(SoGLRenderAction * action)
++{
++  SoDebugError::postInfo("SoGuiPane::GLRenderInPath", "implementation is out of date");
++  SoState * state = action->getState();
++  state->push();
++
++  SbVec3f world = this->worldSize.getValue();
++  SbVec3f object = this->objectSize.getValue();
++
++  SoMaterialBundle mb(action);
++  mb.sendFirst();
++
++  // draw pane
++  glBegin(GL_QUADS);
++  glVertex3f(0.0f, 0.0f, 0.0f);
++  glVertex3f(0.0f, world[1], 0.0f);
++  glVertex3f(world[0], world[1], 0.0f);
++  glVertex3f(world[0], 0.0f, 0.0f);
++  glEnd(); // GL_QUADS
++
++  // adjust scale for new object space
++  SbVec3f scalefactor(world[0] / object[0], world[1] / object[1], ZSCALE);
++  SoModelMatrixElement::scaleBy(state, this, scalefactor);
++
++  // store current model matrix
++  PRIVATE(this)->modelmatrix = SoModelMatrixElement::get(state);
++  PRIVATE(this)->position = SbVec3f(0.0f, 0.0f, 0.0f);
++
++  GLint olddepthfunc = 0;
++  glGetIntegerv(GL_DEPTH_FUNC, &olddepthfunc);
++  glDepthFunc(GL_LEQUAL);
++
++  // FIXME: set up clipping around pane
++  inherited::GLRenderInPath(action);
++
++  glDepthFunc((GLenum) olddepthfunc);
++  state->pop();
++}
++
++void
++SoGuiPane::GLRenderOffPath(SoGLRenderAction * action)
++{
++  // is this one ever invoked?
++  SoDebugError::postInfo("SoGuiPane::GLRenderOffPath", "no implementation yet");
++  inherited::GLRenderOffPath(action);
++}
++
++void
++SoGuiPane::pick(SoPickAction * action)
++{
++  this->doAction(action);
++}
++
++void
++SoGuiPane::rayPick(SoRayPickAction * action)
++{
++  this->doAction(action);
++}
++
++void
++SoGuiPane::getMatrix(SoGetMatrixAction * action)
++{
++  SoDebugError::postInfo("SoGuiPane::getMatrix", "invoked");
++  SbVec3f world = this->worldSize.getValue();
++  SbVec3f object = this->objectSize.getValue();
++  SbVec3f scalefactor(world[0] / object[0], world[1] / object[1], ZSCALE);
++  SbMatrix matrix = SbMatrix::identity();
++  matrix.setScale(scalefactor);
++  action->getMatrix().multLeft(matrix);
++  // FIXME: update inverse matrix
++  inherited::getMatrix(action);
++}
++
++void
++SoGuiPane::handleEvent(SoHandleEventAction * action)
++{
++  this->doAction(action);
++}
++
++void
++SoGuiPane::getBoundingBox(SoGetBoundingBoxAction * action)
++{
++  SbVec3f min = SbVec3f(0.0f, 0.0f, 0.0f);
++  SbVec3f max = this->worldSize.getValue();
++  min[2] = 0.0f; // -0.001f;
++  max[2] = 0.0f; // 0.001f;
++  SbBox3f box(min, max);
++  action->extendBy(box);
++}
++
++SbVec2f
++SoGuiPane::getRayPickIntersectionPoint(void) const
++{
++  return PRIVATE(this)->raypickpos;
++}
++
++void
++SoGuiPane::moveTo(SoState * state, SbVec3f position)
++{
++  SbVec3f object = this->objectSize.getValue();
++  if ( position[0] < 0.0f ) position[0] = object[0] + position[0];
++  if ( position[1] < 0.0f ) position[1] = object[1] + position[1];
++  PRIVATE(this)->position = position;
++  SbVec3f translation(0.0f, 0.0f, 0.0f);
++  translation[0] = PRIVATE(this)->position[0];
++  translation[1] = PRIVATE(this)->position[1];
++  SoModelMatrixElement::set(state, this, PRIVATE(this)->modelmatrix);
++  // SoDebugError::postInfo("SoGuiPane::moveTo", "origo in %g %g", translation[0], translation[1]);
++  SoModelMatrixElement::translateBy(state, this, translation);
++}
++
++void
++SoGuiPane::applyMoveTo(SoGetMatrixAction * action, SbVec3f position)
++{
++  // FIXME: support negative coordinates
++  SoDebugError::postInfo("SoGuiPane::applyMoveTo", "target %g %g", position[0], position[1]);
++  action->getMatrix() = PRIVATE(this)->modelmatrix;
++  SbMatrix matrix = SbMatrix::identity();
++  matrix.setTranslate(position);
++  action->getMatrix().multLeft(matrix);
++  // FIXME: update inverse matrix
++}
++
++void
++SoGuiPane::moveBy(SoState * state, SbVec3f offset)
++{
++  PRIVATE(this)->position += offset;
++  SbVec3f translation(0.0f, 0.0f, 0.0f);
++  translation[0] = PRIVATE(this)->position[0];
++  translation[1] = PRIVATE(this)->position[1];
++  SoModelMatrixElement::set(state, this, PRIVATE(this)->modelmatrix);
++  // SoDebugError::postInfo("SoGuiPane::moveBy", "origo in %g %g", translation[0], translation[1]);
++  SoModelMatrixElement::translateBy(state, this, translation);
++}
++
++void
++SoGuiPane::applyMoveBy(SoGetMatrixAction * action, SbVec3f offset)
++{
++  SoDebugError::postInfo("SoGuiPane::applyMoveBy", "offset %g %g", offset[0], offset[1]);
++  action->getMatrix() = PRIVATE(this)->modelmatrix;
++  SbMatrix matrix = SbMatrix::identity();
++  SbVec3f position = PRIVATE(this)->position + offset;
++  matrix.setTranslate(position);
++  action->getMatrix().multLeft(matrix);
++  // FIXME: update inverse matrix
++}
++
++#undef ZSCALE
++#undef PRIVATE
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Pane.h.in
+@@ -0,0 +1,89 @@
++#ifndef COIN_SOGUIPANE_H
++#define COIN_SOGUIPANE_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/SbLinear.h>
++#include <Inventor/fields/SoSFVec3f.h>
++#include <Inventor/nodes/SoSeparator.h>
++
++class SoState;
++
++class SoGuiPane : public SoSeparator {
++  typedef SoSeparator inherited;
++  SO_NODE_HEADER(SoGuiPane);
++
++public:
++  static void initClass(void);
++
++  SoGuiPane(void);
++
++  SoSFVec3f worldSize;
++  SoSFVec3f objectSize;
++
++  virtual void doAction(SoAction * action);
++
++  virtual void GLRenderBelowPath(SoGLRenderAction * action);
++  virtual void GLRenderInPath(SoGLRenderAction * action);
++  virtual void GLRenderOffPath(SoGLRenderAction * action);
++  virtual void pick(SoPickAction * action);
++  virtual void rayPick(SoRayPickAction * action);
++  virtual void getMatrix(SoGetMatrixAction * action);
++  virtual void getBoundingBox(SoGetBoundingBoxAction * action);
++  virtual void handleEvent(SoHandleEventAction * action);
++
++  SbVec2f getRayPickIntersectionPoint(void) const;
++
++protected:
++  friend class SoGuiPosition;
++  friend class SoGuiTranslation;
++
++  virtual ~SoGuiPane(void);
++
++  void moveTo(SoState * state, SbVec3f position);
++  void applyMoveTo(SoGetMatrixAction * action, SbVec3f position);
++  void moveBy(SoState * state, SbVec3f translation);
++  void applyMoveBy(SoGetMatrixAction * action, SbVec3f translation);
++
++private:
++  void * internals;
++
++};
++
++#endif // !COIN_SOGUIPANE_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Position.cpp.in
+@@ -0,0 +1,123 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <assert.h>
++
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/actions/SoGLRenderAction.h>
++#include <Inventor/actions/SoPickAction.h>
++#include <Inventor/actions/SoRayPickAction.h>
++#include <Inventor/actions/SoGetMatrixAction.h>
++#include <Inventor/elements/SoModelMatrixElement.h>
++#include <Inventor/SoPath.h>
++
++#include <Inventor/@Gui@/nodes/SoGuiPane.h>
++#include <Inventor/@Gui@/nodes/SoGuiPosition.h>
++
++// *************************************************************************
++
++SO_NODE_SOURCE(SoGuiPosition);
++
++void
++SoGuiPosition::initClass(void)
++{
++  SO_NODE_INIT_CLASS(SoGuiPosition, SoTransformation, "Transformation");
++}
++
++SoGuiPosition::SoGuiPosition(void)
++{
++  SO_NODE_CONSTRUCTOR(SoGuiPosition);
++  SO_NODE_ADD_FIELD(position, (SbVec3f(0.0f, 0.0f, 0.0f)));
++}
++
++SoGuiPosition::~SoGuiPosition(void)
++{
++}
++
++void
++SoGuiPosition::doAction(SoAction * action)
++{
++  int i;
++  // SoDebugError::postInfo("SoGuiPosition::doAction", "invoked by %s", action->getTypeId().getName().getString());
++  SoGuiPane * pane = NULL;
++  const SoFullPath * path = (const SoFullPath *) action->getCurPath();
++  for ( i = path->getLength() - 1; (i >= 0) && (pane == NULL); i-- ) {
++    SoNode * node = path->getNode(i);
++    assert(node);
++    if ( node->isOfType(SoGuiPane::getClassTypeId()) ) pane = (SoGuiPane *) node;
++  }
++  if ( pane == NULL ) {
++    SoDebugError::postInfo("SoGuiPosition::GLRender", "SoGuiPosition only works below an SoGuiPane node");
++    return;
++  }
++  pane->moveTo(action->getState(), this->position.getValue());
++}
++
++void
++SoGuiPosition::GLRender(SoGLRenderAction * action)
++{
++  this->doAction(action);
++}
++
++void
++SoGuiPosition::pick(SoPickAction * action)
++{
++  this->doAction(action);
++}
++
++void
++SoGuiPosition::rayPick(SoRayPickAction * action)
++{
++  this->doAction(action);
++}
++
++void
++SoGuiPosition::getMatrix(SoGetMatrixAction * action)
++{
++  SoDebugError::postInfo("SoGuiPosition::getMatrix", "invoked");
++  int i;
++  SoGuiPane * pane = NULL;
++  const SoFullPath * path = (const SoFullPath *) action->getCurPath();
++  for ( i = path->getLength() - 1; (i >= 0) && (pane == NULL); i-- ) {
++    SoNode * node = path->getNode(i);
++    assert(node);
++    if ( node->isOfType(SoGuiPane::getClassTypeId()) ) pane = (SoGuiPane *) node;
++  }
++  if ( pane == NULL ) {
++    SoDebugError::postInfo("SoGuiPosition::getMatrix", "SoGuiPosition only works below an SoGuiPane node");
++    return;
++  }
++  pane->applyMoveTo(action, this->position.getValue());
++}
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Position.h.in
+@@ -0,0 +1,70 @@
++#ifndef COIN_SOGUIPOSITION_H
++#define COIN_SOGUIPOSITION_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/fields/SoSFVec3f.h>
++#include <Inventor/nodes/SoTransformation.h>
++
++class SoGuiPosition : public SoTransformation {
++  typedef SoTransformation inherited;
++  SO_NODE_HEADER(SoGuiPosition);
++
++public:
++  static void initClass(void);
++
++  SoGuiPosition(void);
++
++  SoSFVec3f position;
++
++  virtual void doAction(SoAction * action);
++  virtual void GLRender(SoGLRenderAction * action);
++  virtual void pick(SoPickAction * action);
++  virtual void rayPick(SoRayPickAction * action);
++  virtual void getMatrix(SoGetMatrixAction * action);
++
++protected:
++  virtual ~SoGuiPosition(void);
++
++private:
++  void * internals;
++
++};
++
++#endif // !COIN_SOGUIPOSITION_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/README
+@@ -0,0 +1,40 @@
++NODES
++
++  SoGuiViewportFix - fix origo to a corner of the viewport
++
++  SoGuiPosition - set 2D position on pane
++
++  SoGuiTranslation - accumulate 2D translation on pane
++
++  SoGuiPane - group node for containing a 2D interface
++    - for enabling special translation/position nodes
++    - for enabling special scaling nodes
++
++NODEKITS
++
++  SoGuiFrame - a 2d-rect emboss / frame renderer
++
++  SoGuiClickCounter - a button-like widget that reacts to mouse presses
++
++  SoGuiToggleButton - a button-like widget that can be turned on/off with the mouse
++
++  SoGuiRadioButton - a button-like widget that can be turned on with the mouse
++
++  SoGuiSlider1 - an interactive slider for a one-dimensional value space
++
++  SoGuiSlider2 - an interactive slider for a two-dimensional value space
++
++  SoGuiColorEditor - the machinery of the color editor component
++
++  SoGuiMaterialEditor - the machinery of the material editor component
++
++ENGINES
++
++  SoGuiRadioGroup - an engine that will make sure only one SoSFBool is enabled
++
++  SoGuiFormat - a string formatting engine (very ad-hoc design for now)
++
++DRAGGERS
++
++  [SoGuiWindowDragger]
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/RadioButton.cpp.in
+@@ -0,0 +1,204 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/actions/SoHandleEventAction.h>
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoCoordinate3.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++#include <Inventor/events/SoMouseButtonEvent.h>
++#include <Inventor/SoPickedPoint.h>
++
++#include <Inventor/@Gui@/SoAny.h>
++#include <Inventor/@Gui@/nodes/SoGuiRadioButton.h>
++#include <assert.h>
++
++// *************************************************************************
++
++class RadioButton {
++public:
++  RadioButton(void);
++
++  SoGuiRadioButton * api;
++
++  SoCoordinate3 * coords;
++  SoNode * faceset;
++  SoFieldSensor * size_sensor;
++  static void size_updated_cb(void * closure, SoSensor * sensor);
++
++  static const char * scene[];
++};
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((RadioButton *)obj->internals)
++
++void
++SoGuiRadioButton::initClass(void)
++{
++  SO_KIT_INIT_CLASS(SoGuiRadioButton, SoBaseKit, "BaseKit");
++}
++
++SO_KIT_SOURCE(SoGuiRadioButton);
++
++SoGuiRadioButton::SoGuiRadioButton(void)
++{
++  this->internals = new RadioButton;
++  PRIVATE(this)->api = this;
++
++  SO_KIT_CONSTRUCTOR(SoGuiRadioButton);
++
++  SO_KIT_ADD_FIELD(size, (SbVec3f(1.0f, 1.0f, 0.0f)));
++  SO_KIT_ADD_FIELD(on, (FALSE));
++
++  SO_KIT_ADD_CATALOG_ENTRY(root, SoSeparator, FALSE, this, "", FALSE);
++
++  SO_KIT_INIT_INSTANCE();
++
++  SoNode * scene = SoAny::loadSceneGraph(RadioButton::scene);
++  assert(scene);
++  assert(scene->isOfType(SoSeparator::getClassTypeId()));
++  scene->ref();
++
++  PRIVATE(this)->coords = (SoCoordinate3 *) SoAny::scanSceneForName(scene, "coords");
++  assert(PRIVATE(this)->coords);
++  assert(PRIVATE(this)->coords->isOfType(SoCoordinate3::getClassTypeId()));
++  PRIVATE(this)->faceset = SoAny::scanSceneForName(scene, "faceset");
++  assert(PRIVATE(this)->faceset);
++
++  scene->unrefNoDelete();
++  this->setAnyPart("root", scene);
++
++  PRIVATE(this)->size_sensor = new SoFieldSensor(RadioButton::size_updated_cb, PRIVATE(this));
++  PRIVATE(this)->size_sensor->attach(&(this->size));
++}
++
++
++SoGuiRadioButton::~SoGuiRadioButton(void)
++{
++  delete PRIVATE(this)->size_sensor;
++  RadioButton * obj = PRIVATE(this);
++  delete obj;
++}
++
++void
++SoGuiRadioButton::handleEvent(SoHandleEventAction * action)
++{
++  const SoEvent * ev = action->getEvent();
++  if ( ev->isOfType(SoMouseButtonEvent::getClassTypeId()) ) {
++    SbBool hit = FALSE;
++    const SoPickedPointList & ppoints = action->getPickedPointList();
++    assert(PRIVATE(this)->faceset);
++    int i = 0;
++    for ( i = 0; !hit && i < ppoints.getLength(); i++ ) {
++      const SoPickedPoint * point = ppoints[i];
++      const SoFullPath * path = (const SoFullPath *) point->getPath();
++      assert(path);
++      SoNode * node = path->getTail();
++      if ( node == PRIVATE(this)->faceset ) hit = TRUE;
++    }
++    if ( hit ) {
++      const SoMouseButtonEvent * event = (SoMouseButtonEvent *) ev;
++      if ( event->getState() == SoButtonEvent::DOWN ) {
++        this->on.setValue(TRUE);
++        action->setHandled();
++      }
++    }
++  }
++  if ( !action->isHandled() ) {
++    inherited::handleEvent(action);
++  }
++}
++
++#undef PRIVATE
++
++// *************************************************************************
++// RadioButton
++// *************************************************************************
++
++#define PUBLIC(obj) (obj->api)
++
++const char *
++RadioButton::scene[] =
++{
++  "#Inventor V2.1 ascii",
++  "",
++  "Separator {",
++  "  DEF coords Coordinate3 {",
++  "    point [",
++  "      0 0 0,",
++  "      1 0 0,",
++  "      1 1 0,",
++  "      0 1 0",
++  "    ]",
++  "  }",
++  "  DEF faceset IndexedFaceSet {",
++  "    coordIndex [",
++  "      0 1 2 -1",
++  "      0 2 3 -1",
++  "    ]",
++  "  }",
++  "}",
++  NULL
++};
++
++RadioButton::RadioButton(void)
++{
++  this->api = NULL;
++  this->coords = NULL;
++  this->size_sensor = NULL;
++}
++
++void
++RadioButton::size_updated_cb(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  RadioButton * me = (RadioButton *) closure;
++  assert(PUBLIC(me));
++  SbVec3f size = PUBLIC(me)->size.getValue();
++  assert(me->size_sensor);
++  me->size_sensor->detach();
++  assert(me->coords);
++  SbBool save = me->coords->point.enableNotify(FALSE);
++  me->coords->point.set1Value(0, SbVec3f(0.0f, 0.0f, 0.0f));
++  me->coords->point.set1Value(1, SbVec3f(size[0], 0.0f, 0.0f));
++  me->coords->point.set1Value(2, SbVec3f(size[0], size[1], 0.0f));
++  me->coords->point.set1Value(3, SbVec3f(0.0f, size[1], 0.0f));
++  me->coords->enableNotify(save);
++  if ( save ) me->coords->point.touch();
++  me->size_sensor->attach(&(PUBLIC(me)->size));
++}
++
++#undef PUBLIC
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/RadioButton.h.in
+@@ -0,0 +1,68 @@
++#ifndef COIN_SOGUIRADIOBUTTON_H
++#define COIN_SOGUIRADIOBUTTON_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/fields/SoSFBool.h>
++#include <Inventor/fields/SoSFVec3f.h>
++#include <Inventor/nodekits/SoBaseKit.h>
++
++class SoGuiRadioButton : public SoBaseKit {
++  typedef SoBaseKit inherited;
++  SO_KIT_HEADER(SoGuiRadioButton);
++  SO_KIT_CATALOG_ENTRY_HEADER(root);
++public:
++  static void initClass(void);
++
++  SoGuiRadioButton(void);
++
++  SoSFVec3f size;
++  SoSFBool on;
++
++  virtual void handleEvent(SoHandleEventAction * action);
++
++protected:
++  virtual ~SoGuiRadioButton(void);
++
++private:
++  void * internals;
++
++};
++
++#endif // !COIN_SOGUIRADIOBUTTON_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/SceneTexture2.cpp.in
+@@ -0,0 +1,205 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/*
++ * TODO
++ * - field "SoSFFloat delay" for making node wait a certain time after
++ *   last scene change before re-rendering the texture
++ * - field "SoSFBool dirty" for making texture show itself as dirty
++ *   (stippled?) until it has been rerendered (in case it takes time to
++ *   rerender scene).
++ */
++
++#include <assert.h>
++#include <string.h>
++
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++#include <Inventor/sensors/SoOneShotSensor.h>
++#include <Inventor/actions/SoGLRenderAction.h>
++#include <Inventor/SoOffscreenRenderer.h>
++#include <Inventor/misc/SoNotification.h>
++
++#include <Inventor/@Gui@/nodes/SoGuiSceneTexture2.h>
++
++// *************************************************************************
++
++class SceneTexture2 {
++public:
++  SceneTexture2(void);
++
++  SoGuiSceneTexture2 * api;
++
++  SbVec2s prevsize;
++  SoOffscreenRenderer * renderer;
++
++  SoFieldSensor * size_sensor;
++  static void size_updated_cb(void * closure, SoSensor * sensor);
++
++  SoOneShotSensor * render_sensor;
++  static void render_cb(void * closure, SoSensor * sensor);
++};
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((SceneTexture2 *) obj->internals)
++
++void
++SoGuiSceneTexture2::initClass(void)
++{
++  SO_NODE_INIT_CLASS(SoGuiSceneTexture2, SoTexture2, "Texture2");
++}
++
++SO_NODE_SOURCE(SoGuiSceneTexture2);
++
++SoGuiSceneTexture2::SoGuiSceneTexture2(void)
++{
++  this->internals = new SceneTexture2;
++  PRIVATE(this)->api = this;
++
++  SO_NODE_CONSTRUCTOR(SoGuiSceneTexture2);
++  SO_NODE_ADD_FIELD(size, (SbVec2f(256.0f, 256.0f)));
++  SO_NODE_ADD_FIELD(scene, (NULL));
++
++  PRIVATE(this)->size_sensor = new SoFieldSensor(SceneTexture2::size_updated_cb, PRIVATE(this));
++  PRIVATE(this)->size_sensor->attach(&(this->size));
++  PRIVATE(this)->render_sensor = new SoOneShotSensor(SceneTexture2::render_cb, PRIVATE(this));
++}
++
++SoGuiSceneTexture2::~SoGuiSceneTexture2(void)
++{
++  delete PRIVATE(this)->size_sensor;
++  delete PRIVATE(this)->render_sensor;
++  if ( PRIVATE(this)->renderer != NULL ) {
++    delete PRIVATE(this)->renderer;
++  }
++}
++
++// We overload notify() because we need to know when the scene graph has
++// been updated, but want to stop that notification from propagating
++// through the external scene graph.  We only want the texture update to
++// trigger re-rendering.
++void
++SoGuiSceneTexture2::notify(SoNotList * list)
++{
++  if ( list->getLastField() == &(this->scene) ) {
++    PRIVATE(this)->render_sensor->schedule();
++    return;
++  }
++  inherited::notify(list);
++}
++
++//
++// we don't want to write out the image and filename fields.
++//
++void
++SoGuiSceneTexture2::write(SoWriteAction * action)
++{
++  this->image.setDefault(TRUE);
++  this->filename.setDefault(TRUE);
++  inherited::write(action);
++}
++
++
++#undef PRIVATE
++
++// *************************************************************************
++
++#define PUBLIC(obj) (((SceneTexture2 *) obj)->api)
++
++SceneTexture2::SceneTexture2(void)
++{
++  this->api = NULL;
++  this->prevsize = SbVec2s(-1, -1);
++  this->renderer = NULL;
++  this->size_sensor = NULL;
++  this->render_sensor = NULL;
++}
++
++void
++SceneTexture2::size_updated_cb(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  SceneTexture2 * me = (SceneTexture2 *) closure;
++  SbVec2f tempsize = PUBLIC(me)->size.getValue();
++  SbVec2s size;
++  size[0] = (short) tempsize[0];
++  size[1] = (short) tempsize[1];
++  if ( size != me->prevsize ) {
++    if ( me->renderer != NULL ) {
++      me->renderer->setViewportRegion(SbViewportRegion(size));
++      PUBLIC(me)->image.setValue(size, 3, NULL);
++      me->render_sensor->schedule();
++    }
++    me->prevsize = size;
++  }
++}
++
++void
++SceneTexture2::render_cb(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  SceneTexture2 * me = (SceneTexture2 *) closure;
++  SbVec2f tempsize = PUBLIC(me)->size.getValue();
++  SbVec2s size;
++  size[0] = (short) tempsize[0];
++  size[1] = (short) tempsize[1];
++  int nc = 3;
++  SoNode * scene = PUBLIC(me)->scene.getValue();
++  SbBool save = PUBLIC(me)->image.enableNotify(FALSE);
++  if ( scene != NULL ) {
++    if ( me->renderer == NULL ) {
++      me->renderer = new SoOffscreenRenderer(SbViewportRegion(size));
++      me->renderer->setComponents(SoOffscreenRenderer::RGB);
++      me->renderer->getGLRenderAction()->setTransparencyType(SoGLRenderAction::BLEND);
++      me->prevsize = size;
++      PUBLIC(me)->image.setValue(size, nc, NULL);
++    }
++    me->renderer->render(scene);
++    unsigned char * renderbuffer = me->renderer->getBuffer();
++    unsigned char * imagebytes = PUBLIC(me)->image.startEditing(size, nc);
++    memcpy(imagebytes, renderbuffer, size[0] * size[1] * nc);
++    PUBLIC(me)->image.finishEditing();
++  } else {
++    unsigned char * imagebytes = PUBLIC(me)->image.startEditing(size, nc);
++    memset(imagebytes, 0, size[0] * size[1] * nc);
++    PUBLIC(me)->image.finishEditing();
++  }
++  PUBLIC(me)->image.enableNotify(save);
++  if ( save ) PUBLIC(me)->image.touch();
++}
++
++#undef PUBLIC
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/SceneTexture2.h.in
+@@ -0,0 +1,67 @@
++#ifndef COIN_SOGUISCENETEXTURE2_H
++#define COIN_SOGUISCENETEXTURE2_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif // !SO at GUI@_INTERNAL
++
++#include <Inventor/fields/SoSFVec2f.h>
++#include <Inventor/fields/SoSFNode.h>
++#include <Inventor/nodes/SoTexture2.h>
++
++class SoGuiSceneTexture2 : public SoTexture2 {
++  typedef SoTexture2 inherited;
++  SO_NODE_HEADER(SoGuiSceneTexture2);
++public:
++  static void initClass(void);
++  SoGuiSceneTexture2(void);
++
++  SoSFVec2f size;
++  SoSFNode scene;
++
++  virtual void notify(SoNotList * list);
++  virtual void write(SoWriteAction * action);
++
++protected:
++  virtual ~SoGuiSceneTexture2(void);
++
++private:
++  void * internals;
++
++};
++
++#endif // !COIN_SOGUISCENETEXTURE2_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Slider1.cpp.in
+@@ -0,0 +1,558 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif /* HAVE_CONFIG_H */
++
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/actions/SoGLRenderAction.h>
++#include <Inventor/actions/SoHandleEventAction.h>
++#include <Inventor/misc/SoState.h>
++#include <Inventor/elements/SoLazyElement.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++#include <Inventor/events/SoMouseButtonEvent.h>
++#include <Inventor/events/SoLocation2Event.h>
++#include <Inventor/SoPickedPoint.h>
++#include <Inventor/SoLists.h>
++
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoMaterial.h>
++#include <Inventor/nodes/SoTexture2.h>
++#include <Inventor/nodes/SoCoordinate3.h>
++#include <Inventor/nodes/SoTextureCoordinate2.h>
++#include <Inventor/nodes/SoIndexedFaceSet.h>
++#include <Inventor/nodes/SoIndexedLineSet.h>
++
++#include <Inventor/@Gui@/common/gl.h>
++#include <Inventor/@Gui@/So at Gui@Basic.h>
++
++#include <Inventor/@Gui@/nodes/SoGuiPane.h>
++#include <Inventor/@Gui@/nodes/SoGuiSlider1.h>
++#include <assert.h>
++
++// *************************************************************************
++
++/*!
++  \class SoGuiSlider1 Inventor/@Gui@/nodes/SoGuiSlider1.h
++  \brief A GUI component for a 1-dimensional slider.
++
++  The SoGuiSlider1 node is for creating 2D user interfaces with
++  sliders.
++
++  fields:
++    min
++    max
++    value
++    orientation - not supported yet
++    size
++*/
++
++// *************************************************************************
++
++class Slider1 {
++public:
++  SoGuiSlider1 * kit;
++  SoFieldSensor * sizeSensor;
++  SoFieldSensor * valueSensor;
++  SoFieldSensor * minSensor;
++  SoFieldSensor * maxSensor;
++
++  SbBool grabbing;
++  float grabpos;
++  float grabval;
++  float graboffset;
++  float pickpos;
++  SoGuiPane * pane;
++
++  Slider1(void);
++  ~Slider1(void);
++
++  SbColor mincolor, maxcolor;
++
++  // sensors callbacks
++  static void sizeChangeCB(void * closure, SoSensor * sensor);
++  static void valueChangeCB(void * closure, SoSensor * sensor);
++  static void minChangeCB(void * closure, SoSensor * sensor);
++  static void maxChangeCB(void * closure, SoSensor * sensor);
++};
++
++Slider1::Slider1(void)
++{
++  this->kit = NULL;
++  this->sizeSensor = NULL;
++  this->valueSensor = NULL;
++  this->minSensor = NULL;
++  this->maxSensor = NULL;
++  this->grabbing = FALSE;
++  this->pane = NULL;
++}
++
++#define DELETE_SENSOR(sensor) \
++  if ( (sensor) != NULL ) { \
++    (sensor)->detach(); \
++    delete (sensor); \
++    (sensor) = NULL; \
++  }
++
++Slider1::~Slider1(void)
++{
++  DELETE_SENSOR(this->sizeSensor);
++  DELETE_SENSOR(this->valueSensor);
++  DELETE_SENSOR(this->minSensor);
++  DELETE_SENSOR(this->maxSensor);
++  this->kit = NULL;
++}
++
++#undef DELETE_SENSOR
++
++void
++Slider1::sizeChangeCB(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  Slider1 * internals = (Slider1 *) closure;
++  assert(internals->kit);
++  internals->kit->sizeUpdate();
++}
++
++void
++Slider1::valueChangeCB(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  Slider1 * internals = (Slider1 *) closure;
++  assert(internals->kit);
++  internals->kit->valueUpdate();
++}
++
++void
++Slider1::minChangeCB(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  Slider1 * internals = (Slider1 *) closure;
++  assert(internals->kit);
++  internals->kit->minUpdate();
++}
++
++void
++Slider1::maxChangeCB(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  Slider1 * internals = (Slider1 *) closure;
++  assert(internals->kit);
++  internals->kit->maxUpdate();
++}
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((Slider1 *) obj->internals)
++
++void
++SoGuiSlider1::initClass(void)
++{
++  SO_KIT_INIT_CLASS(SoGuiSlider1, SoBaseKit, "BaseKit");
++}
++
++SO_KIT_SOURCE(SoGuiSlider1);
++
++SoGuiSlider1::SoGuiSlider1(void)
++{
++  this->internals = (void *) new Slider1;
++  PRIVATE(this)->kit = this;
++
++  SO_KIT_CONSTRUCTOR(SoGuiSlider1);
++
++  SO_KIT_ADD_FIELD(size, (SbVec3f(1.0f, 1.0f, 0.0f)));
++  SO_KIT_ADD_FIELD(orientation, (SoGuiSlider1::X));
++  SO_KIT_ADD_FIELD(min, (0.0f));
++  SO_KIT_ADD_FIELD(max, (1.0f));
++  SO_KIT_ADD_FIELD(value, (0.0f));
++  SO_KIT_ADD_FIELD(alwaysHook, (TRUE));
++
++  SO_KIT_DEFINE_ENUM_VALUE(Orientation, X);
++  SO_KIT_DEFINE_ENUM_VALUE(Orientation, Y);
++
++  SO_KIT_SET_SF_ENUM_TYPE(orientation, Orientation);
++
++  SO_KIT_ADD_CATALOG_ENTRY(knobLightLineSet, SoIndexedLineSet, FALSE, knobGeometry, "", FALSE);
++  SO_KIT_ADD_CATALOG_ENTRY(knobLightMaterial, SoMaterial, FALSE, knobGeometry, knobLightLineSet, TRUE);
++  SO_KIT_ADD_CATALOG_ENTRY(knobShadeLineSet, SoIndexedLineSet, FALSE, knobGeometry, knobLightMaterial, FALSE);
++  SO_KIT_ADD_CATALOG_ENTRY(knobShadeMaterial, SoMaterial, FALSE, knobGeometry, knobShadeLineSet, TRUE);
++  SO_KIT_ADD_CATALOG_ENTRY(knobFaceSet, SoIndexedFaceSet, FALSE, knobGeometry, knobShadeMaterial, FALSE);
++  SO_KIT_ADD_CATALOG_ENTRY(knobMaterial, SoMaterial, FALSE, knobGeometry, knobFaceSet, TRUE);
++  SO_KIT_ADD_CATALOG_ENTRY(knobCoords, SoCoordinate3, FALSE, knobGeometry, knobMaterial, FALSE);
++
++  SO_KIT_ADD_CATALOG_ENTRY(knobGeometry, SoSeparator, FALSE, topSeparator, "", FALSE);
++  SO_KIT_ADD_CATALOG_ENTRY(surfaceFaceSet, SoIndexedFaceSet, FALSE, surfaceGeometry, "", FALSE);
++  SO_KIT_ADD_CATALOG_ENTRY(surfaceCoords, SoCoordinate3, FALSE, surfaceGeometry, surfaceFaceSet, FALSE);
++  SO_KIT_ADD_CATALOG_ENTRY(surfaceTexCoords, SoTextureCoordinate2, FALSE, surfaceGeometry, surfaceCoords, FALSE);
++  SO_KIT_ADD_CATALOG_ENTRY(surfaceTexture, SoTexture2, TRUE, surfaceGeometry, surfaceTexCoords, TRUE);
++  SO_KIT_ADD_CATALOG_ENTRY(surfaceMaterial, SoMaterial, TRUE, surfaceGeometry, surfaceTexture, TRUE);
++  SO_KIT_ADD_CATALOG_ENTRY(surfaceGeometry, SoSeparator, FALSE, topSeparator, knobGeometry, FALSE);
++  SO_KIT_ADD_CATALOG_ENTRY(topSeparator, SoSeparator, FALSE, this, "", FALSE);
++
++  SO_KIT_INIT_INSTANCE();
++
++  static float surfacetexturecoordinates[][2] = { {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 0.0f} };
++  SoTextureCoordinate2 * surfacetexcoords = SO_GET_ANY_PART(this, "surfaceTexCoords", SoTextureCoordinate2);
++  assert(surfacetexcoords);
++  surfacetexcoords->point.setValues(0, 4, surfacetexturecoordinates);
++
++  static int32_t surfaceindices[] = { 0, 1, 2, -1, 0, 2, 3, -1 };
++  SoIndexedFaceSet * surfacefaceset = SO_GET_ANY_PART(this, "surfaceFaceSet", SoIndexedFaceSet);
++  assert(surfacefaceset);
++  surfacefaceset->textureCoordIndex.setValues(0, 8, surfaceindices);
++  surfacefaceset->coordIndex.setValues(0, 8, surfaceindices);
++ 
++  static int32_t knobindices[] = {
++    0, 1, 2, -1, 0, 2, 3, -1,
++    4, 5, 6, -1, 4, 6, 7, -1,
++    8, 2, 5, -1, 8, 5, 9, -1,
++    3, 11, 10, -1, 3, 10, 4, -1
++  };
++  SoIndexedFaceSet * knobfaceset = SO_GET_ANY_PART(this, "knobFaceSet", SoIndexedFaceSet);
++  assert(knobfaceset);
++  knobfaceset->coordIndex.setValues(0, sizeof(knobindices)/sizeof(knobindices[0]), knobindices);
++
++  this->sizeUpdate();
++
++  SoMaterial * knobmaterial = SO_GET_ANY_PART(this, "knobMaterial", SoMaterial);
++  assert(knobmaterial);
++  knobmaterial->ambientColor.setValue(0.6f, 0.6f, 0.6f);
++  knobmaterial->diffuseColor.setValue(0.6f, 0.6f, 0.6f);
++  knobmaterial->emissiveColor.setValue(0.6f, 0.6f, 0.6f);
++
++  SoMaterial * knoblightmaterial = SO_GET_ANY_PART(this, "knobLightMaterial", SoMaterial);
++  assert(knoblightmaterial);
++  knoblightmaterial->ambientColor.setValue(0.75f, 0.75f, 0.75f);
++  knoblightmaterial->diffuseColor.setValue(0.75f, 0.75f, 0.75f);
++  knoblightmaterial->emissiveColor.setValue(0.75f, 0.75f, 0.75f);
++
++  SoMaterial * knobshadowmaterial = SO_GET_ANY_PART(this, "knobShadeMaterial", SoMaterial);
++  assert(knobshadowmaterial);
++  knobshadowmaterial->ambientColor.setValue(0.4f, 0.4f, 0.4f);
++  knobshadowmaterial->diffuseColor.setValue(0.4f, 0.4f, 0.4f);
++  knobshadowmaterial->emissiveColor.setValue(0.4f, 0.4f, 0.4f);
++
++  // FIXME: move these to correct coordinates
++  SoIndexedLineSet * lightlineset = SO_GET_ANY_PART(this, "knobLightLineSet", SoIndexedLineSet);
++  assert(lightlineset);
++  static int32_t lightindices[] = { 16, 17, 18, -1, 12, 15, 14, -1 };
++  lightlineset->coordIndex.setValues(0, sizeof(lightindices) / sizeof(lightindices[0]), lightindices);
++
++  SoIndexedLineSet * shadelineset = SO_GET_ANY_PART(this, "knobShadeLineSet", SoIndexedLineSet);
++  assert(shadelineset);
++  static int32_t shadeindices[] = { 12, 13, 14, -1, 16, 19, 18, -1 };
++  shadelineset->coordIndex.setValues(0, sizeof(shadeindices) / sizeof(shadeindices[0]), shadeindices);
++
++  // set up sensors
++  PRIVATE(this)->sizeSensor = new SoFieldSensor(Slider1::sizeChangeCB, PRIVATE(this));
++  PRIVATE(this)->sizeSensor->attach(&(this->size));
++  PRIVATE(this)->valueSensor = new SoFieldSensor(Slider1::valueChangeCB, PRIVATE(this));
++  PRIVATE(this)->valueSensor->attach(&(this->value));
++  PRIVATE(this)->minSensor = new SoFieldSensor(Slider1::minChangeCB, PRIVATE(this));
++  PRIVATE(this)->minSensor->attach(&(this->min));
++  PRIVATE(this)->maxSensor = new SoFieldSensor(Slider1::maxChangeCB, PRIVATE(this));
++  PRIVATE(this)->maxSensor->attach(&(this->max));
++}
++
++SoGuiSlider1::~SoGuiSlider1(void)
++{
++  Slider1 * obj = PRIVATE(this);
++  delete obj;
++  this->internals = NULL;
++}
++
++void
++SoGuiSlider1::setSurfaceColor(const SbColor & valuearg)
++{
++  // FIXME: use Material or basecolor instead of texture
++  this->setSurfaceColor(valuearg, valuearg);
++#if 0
++  PRIVATE(this)->mincolor = valuearg;
++  PRIVATE(this)->maxcolor = valuearg;
++  this->setPart("surfaceTexture", NULL);
++#endif
++}
++
++void
++SoGuiSlider1::setSurfaceColor(const SbColor & minvalue, const SbColor & maxvalue)
++{
++  PRIVATE(this)->mincolor = minvalue;
++  PRIVATE(this)->maxcolor = maxvalue;
++
++  this->setPart("surfaceMaterial", NULL);
++  SoTexture2 * texturenode = SO_GET_ANY_PART(this, "surfaceTexture", SoTexture2);
++  assert(texturenode);
++
++  texturenode->image.setValue(SbVec2s(256, 1), 3, NULL);
++  texturenode->model.setValue(SoTexture2::DECAL);
++
++  SbVec2s sizeval;
++  int nc;
++  unsigned char * buf = texturenode->image.startEditing(sizeval, nc);
++  float rmin = minvalue[0];
++  float gmin = minvalue[1];
++  float bmin = minvalue[2];
++  float rmax = maxvalue[0];
++  float gmax = maxvalue[1];
++  float bmax = maxvalue[2];
++  for ( int x = 0; x < sizeval[0]; x += 1 ) {
++    buf[x*nc+0] = (unsigned char) ((rmin + ((float) x / (float) (sizeval[0]-1)) * (rmax - rmin)) * 255.0f);
++    buf[x*nc+1] = (unsigned char) ((gmin + ((float) x / (float) (sizeval[0]-1)) * (gmax - gmin)) * 255.0f);
++    buf[x*nc+2] = (unsigned char) ((bmin + ((float) x / (float) (sizeval[0]-1)) * (bmax - bmin)) * 255.0f);
++    for ( int y = 1; y < sizeval[1]; y += 1 ) {
++      buf[(y*sizeval[0]+x)*nc+0] = buf[x*nc+0];
++      buf[(y*sizeval[0]+x)*nc+1] = buf[x*nc+1];
++      buf[(y*sizeval[0]+x)*nc+2] = buf[x*nc+2];
++    }
++  }
++  texturenode->image.finishEditing();
++}
++
++SbColor
++SoGuiSlider1::getValueAsColor(void) const
++{
++  // FIXME: support custom textures
++  float val = this->value.getValue();
++  float minval = this->min.getValue();
++  float maxval = this->max.getValue();
++  float factor = (maxval - minval) / (val - minval);
++  float r = So at Gui@Clamp(PRIVATE(this)->mincolor[0] + (PRIVATE(this)->maxcolor[0] - PRIVATE(this)->mincolor[0]) * factor, 0.0f, 1.0f);
++  float g = So at Gui@Clamp(PRIVATE(this)->mincolor[1] + (PRIVATE(this)->maxcolor[1] - PRIVATE(this)->mincolor[1]) * factor, 0.0f, 1.0f);
++  float b = So at Gui@Clamp(PRIVATE(this)->mincolor[2] + (PRIVATE(this)->maxcolor[2] - PRIVATE(this)->mincolor[2]) * factor, 0.0f, 1.0f);
++  return SbColor(r, g, b);
++}
++
++void
++SoGuiSlider1::sizeUpdate(void)
++{
++  SbVec3f sizeval = this->size.getValue();
++  if ( sizeval[0] != 0.0f && sizeval[1] != 0.0f ) {
++    float coordinates[][3] = { {0.0f, 0.0f, 0.0f}, {sizeval[0], 0.0f, 0.0f}, {sizeval[0], sizeval[1], 0.0f}, {0.0f, sizeval[1], 0.0f} };
++    SoCoordinate3 * coords = SO_GET_ANY_PART(this, "surfaceCoords", SoCoordinate3);
++    assert(coords);
++    coords->point.setValues(0, sizeof(coordinates) / sizeof(coordinates[0]), coordinates);
++    this->valueUpdate();
++  }
++}
++
++void
++SoGuiSlider1::valueUpdate(void)
++{
++  SbVec3f sizeval = this->size.getValue();
++  float val = this->value.getValue();
++  float minval = this->min.getValue();
++  float maxval = this->max.getValue();
++  if ( minval < maxval ) {
++    if ( val < minval ) {
++      this->value.setValue(minval);
++      val = minval;
++    } else if ( val > maxval ) {
++      this->value.setValue(maxval);
++      val = maxval;
++    }
++  } else {
++    // we also support inverse sliders where min > max
++    if ( val > minval ) {
++      this->value.setValue(minval);
++      val = minval;
++    } else if ( val < maxval ) {
++      this->value.setValue(maxval);
++      val = maxval;
++    }
++  }
++  // store previous height & value to avoid redundant updates
++  float voff = (float) floor(((val - minval) / (maxval - minval)) * sizeval[0]);
++  float knobcoordinates[][3] = {
++    // faces
++    {-7.0f+voff, -4.0f, 0.0f}, {8.0f+voff, -4.0f, 0.0f}, {8.0f+voff, -1.0f, 0.0f}, {-7.0f+voff, -1.0f, 0.0f}, 
++    {-7.0f+voff, sizeval[1]+1.0f, 0.0f}, {8.0f+voff, sizeval[1]+1.0f, 0.0f}, {8.0f+voff, sizeval[1]+4.0f, 0.0f}, {-7.0f+voff, sizeval[1]+4.0f, 0.0f}, 
++    {3.0f+voff, -1.0f, 0.0f}, {3.0f+voff, sizeval[1]+1.0f, 0.0f}, {-2.0f+voff, sizeval[1]+1.0f, 0.0f}, {-2.0f+voff, -1.0f, 0.0f},
++    // outside lines
++    // also used in handleEvent() so don't change their significance based on index
++    {-8.0f+voff, -5.0f, 0.0f}, {8.0f+voff, -5.0f, 0.0f}, {8.0f+voff, sizeval[1]+4.0f, 0.0f}, {-8.0f+voff, sizeval[1]+4.0f, 0.0f},
++    // inside lines
++    {-2.0f+voff, -1.0f, 0.0f}, {2.0f+voff, -1.0f, 0.0f}, {2.0f+voff, sizeval[1], 0.0f}, {-2.0f+voff, sizeval[1], 0.0f}
++  };
++  SoCoordinate3 * knobcoords = SO_GET_ANY_PART(this, "knobCoords", SoCoordinate3);
++  assert(knobcoords);
++  knobcoords->point.setValues(0, sizeof(knobcoordinates) / sizeof(knobcoordinates[0]), knobcoordinates);
++}
++
++void
++SoGuiSlider1::minUpdate(void)
++{
++  float minval = this->min.getValue();
++  float maxval = this->max.getValue();
++  float val = this->value.getValue();
++  if ( minval < maxval ) {
++    if ( val < minval ) this->value.setValue(minval);
++  } else {
++    if ( val > minval ) this->value.setValue(minval);
++  }
++}
++
++void
++SoGuiSlider1::maxUpdate(void)
++{
++  float minval = this->min.getValue();
++  float maxval = this->max.getValue();
++  float val = this->value.getValue();
++  if ( minval < maxval ) {
++    if ( val > maxval ) this->value.setValue(maxval);
++  } else {
++    if ( val < maxval ) this->value.setValue(maxval);
++  }
++}
++
++void
++SoGuiSlider1::handleEvent(SoHandleEventAction * action)
++{
++  if ( action->isHandled() ) return;
++  const SoEvent * event = action->getEvent();
++
++  if ( PRIVATE(this)->grabbing ) { // click-and-drag
++    if ( event->isOfType(SoLocation2Event::getClassTypeId()) ) {
++      assert(PRIVATE(this)->pane != NULL);
++      // although the return value is discarded, we need to make this call to make
++      // sure the raypick action is run over the scene graph so the pane can return
++      // a useful value...
++      action->getPickedPoint();
++      SbVec2f raypos = PRIVATE(this)->pane->getRayPickIntersectionPoint();
++      if ( raypos[0] != -1.0f ) {
++        float imagpos = raypos[0] + PRIVATE(this)->graboffset;
++        float minval = this->min.getValue();
++        float maxval = this->max.getValue();
++        float imagval;
++        if ( minval < maxval ) imagval = So at Gui@Clamp(imagpos / this->size.getValue()[0], minval, maxval);
++        else imagval = So at Gui@Clamp(imagpos / this->size.getValue()[0], maxval, minval);
++        this->value.setValue(imagval);
++      }
++      action->setHandled();
++    }
++    else if ( event->isOfType(SoMouseButtonEvent::getClassTypeId()) ) {
++      SoMouseButtonEvent * mbevent = (SoMouseButtonEvent *) event;
++      if ( (mbevent->getButton() == SoMouseButtonEvent::BUTTON1) &&
++           (mbevent->getState() == SoButtonEvent::UP) ) {
++        PRIVATE(this)->grabbing = FALSE;
++        PRIVATE(this)->pane = NULL;
++        action->setHandled();
++      }
++    }
++  }
++  else if ( event->isOfType(SoMouseButtonEvent::getClassTypeId()) ) {
++    SoMouseButtonEvent * mbevent = (SoMouseButtonEvent *) event;
++    if ( (mbevent->getButton() == SoMouseButtonEvent::BUTTON1) &&
++         (mbevent->getState() == SoButtonEvent::DOWN) ) {
++      action->setPickRadius(0);
++      const SoPickedPointList & pplist = action->getPickedPointList();
++      if ( pplist.getLength() > 0 ) {
++        int i;
++        for ( i = 0; i < pplist.getLength(); i++ ) {
++          if ( action->isHandled() ) break;
++          const SoPickedPoint * pp = pplist[i];
++          const SoPath * path = pp->getPath();
++          SoNode * node = ((SoFullPath *) path)->getTail();
++          if ( node == ((SoNode *) SO_GET_ANY_PART(this, "knobFaceSet", SoIndexedFaceSet)) ) {
++            SbVec3f point = pp->getObjectPoint();
++            SbVec3f sizeval = this->size.getValue();
++            SoCoordinate3 * knobcoords = SO_GET_ANY_PART(this, "knobCoords", SoCoordinate3);
++            assert(knobcoords);
++            SbVec3f knobmin = knobcoords->point[12];
++            SbVec3f knobmax = knobcoords->point[14];
++            if ( point[0] >= knobmin[0] && point[0] <= knobmax[0] &&
++                 point[1] >= knobmin[1] && point[1] <= knobmax[1] ) {
++              PRIVATE(this)->grabbing = TRUE;
++              action->setHandled();
++  
++              const SoFullPath * path = (const SoFullPath *) action->getCurPath();
++              int i = path->getLength() - 1;
++              SoNode * node = NULL;
++              for ( ; i >= 0; i-- ) {
++                node = path->getNode(i);
++                if ( node->isOfType(SoGuiPane::getClassTypeId()) ) break;
++                node = NULL;
++              }
++              assert(node != NULL);
++              PRIVATE(this)->pane = (SoGuiPane *) node;
++              PRIVATE(this)->grabval = this->value.getValue();
++              PRIVATE(this)->pickpos = point[0];
++  
++              SbVec2f raypos = PRIVATE(this)->pane->getRayPickIntersectionPoint();
++              PRIVATE(this)->grabpos = raypos[0];
++              float realval = ((this->value.getValue() - this->min.getValue()) /
++                (this->max.getValue() - this->min.getValue())) * this->size.getValue()[0];
++              PRIVATE(this)->graboffset = realval - raypos[0];
++            }
++          }
++        }
++        for ( i = 0; i < pplist.getLength(); i++ ) {
++          if ( action->isHandled() ) break;
++          const SoPickedPoint * pp = pplist[i];
++          const SoPath * path = pp->getPath();
++          SoNode * node = ((SoFullPath *) path)->getTail();
++          if ( node == ((SoNode *) SO_GET_ANY_PART(this, "surfaceFaceSet", SoIndexedFaceSet)) ) {
++            SbVec3f point = pp->getObjectPoint();
++            SbVec3f sizeval = this->size.getValue();
++            this->value = this->min.getValue() + ((point[0] / sizeval[0]) * (this->max.getValue() - this->min.getValue()));
++            action->setHandled();
++            if ( this->alwaysHook.getValue() ) {
++              PRIVATE(this)->grabbing = TRUE;
++              const SoFullPath * path = (const SoFullPath *) action->getCurPath();
++              int i = path->getLength() - 1;
++              SoNode * node = NULL;
++              for ( ; i >= 0; i-- ) {
++                node = path->getNode(i);
++                if ( node->isOfType(SoGuiPane::getClassTypeId()) ) break;
++                node = NULL;
++              }
++              assert(node != NULL);
++              PRIVATE(this)->pane = (SoGuiPane *) node;
++              PRIVATE(this)->grabval = this->value.getValue();
++              PRIVATE(this)->pickpos = point[0];
++              SbVec2f raypos = PRIVATE(this)->pane->getRayPickIntersectionPoint();
++                PRIVATE(this)->grabpos = raypos[0];
++              float realval = ((this->value.getValue() - this->min.getValue()) /
++                (this->max.getValue() - this->min.getValue())) * this->size.getValue()[0];
++              PRIVATE(this)->graboffset = realval - raypos[0];
++            }
++          }
++        }
++      }
++    }
++  }
++}
++
++#undef PRIVATE
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Slider1.h.in
+@@ -0,0 +1,108 @@
++#ifndef COIN_SOGUISLIDER1_H
++#define COIN_SOGUISLIDER1_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/fields/SoSFBool.h>
++#include <Inventor/fields/SoSFEnum.h>
++#include <Inventor/fields/SoSFFloat.h>
++#include <Inventor/fields/SoSFVec3f.h>
++
++#include <Inventor/nodekits/SoBaseKit.h>
++
++class SoGuiSlider1 : public SoBaseKit {
++  typedef SoBaseKit inherited;
++
++  SO_KIT_HEADER(SoGuiSlider1);
++
++  SO_KIT_CATALOG_ENTRY_HEADER(topSeparator);
++  SO_KIT_CATALOG_ENTRY_HEADER(surfaceGeometry);
++  SO_KIT_CATALOG_ENTRY_HEADER(surfaceTexture);
++  SO_KIT_CATALOG_ENTRY_HEADER(surfaceMaterial);
++  SO_KIT_CATALOG_ENTRY_HEADER(surfaceTexCoords);
++  SO_KIT_CATALOG_ENTRY_HEADER(surfaceCoords);
++  SO_KIT_CATALOG_ENTRY_HEADER(surfaceFaceSet);
++  SO_KIT_CATALOG_ENTRY_HEADER(knobGeometry);
++  SO_KIT_CATALOG_ENTRY_HEADER(knobMaterial);
++  SO_KIT_CATALOG_ENTRY_HEADER(knobCoords);
++  SO_KIT_CATALOG_ENTRY_HEADER(knobFaceSet);
++  SO_KIT_CATALOG_ENTRY_HEADER(knobShadeMaterial);
++  SO_KIT_CATALOG_ENTRY_HEADER(knobShadeLineSet);
++  SO_KIT_CATALOG_ENTRY_HEADER(knobLightMaterial);
++  SO_KIT_CATALOG_ENTRY_HEADER(knobLightLineSet);
++
++public:
++  static void initClass(void);
++
++  SoGuiSlider1(void);
++
++  enum Orientation {
++    X, Y
++  };
++
++  SoSFVec3f size;
++  SoSFEnum orientation; // not implemented
++
++  SoSFFloat min;
++  SoSFFloat max;
++  SoSFFloat value;
++
++  SoSFBool alwaysHook;
++
++  virtual void handleEvent(SoHandleEventAction * action);
++
++  virtual void setSurfaceColor(const SbColor & value);
++  virtual void setSurfaceColor(const SbColor & minvalue, const SbColor & maxvalue);
++  virtual SbColor getValueAsColor(void) const;
++
++  // FIXME: move to something non-public
++  void sizeUpdate(void);
++  void valueUpdate(void);
++  void minUpdate(void);
++  void maxUpdate(void);
++
++protected:
++  virtual ~SoGuiSlider1(void);
++
++private:
++  void * internals;
++
++};
++
++#endif // !COIN_SOGUISLIDER1_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Slider2.cpp.in
+@@ -0,0 +1,483 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif /* HAVE_CONFIG_H */
++
++#include <math.h>
++
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/actions/SoGLRenderAction.h>
++#include <Inventor/actions/SoHandleEventAction.h>
++#include <Inventor/misc/SoState.h>
++#include <Inventor/elements/SoLazyElement.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++#include <Inventor/events/SoMouseButtonEvent.h>
++#include <Inventor/events/SoLocation2Event.h>
++#include <Inventor/SoPickedPoint.h>
++#include <Inventor/SoLists.h>
++
++#include <Inventor/SbColor.h>
++
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoMaterial.h>
++#include <Inventor/nodes/SoTexture2.h>
++#include <Inventor/nodes/SoCoordinate3.h>
++#include <Inventor/nodes/SoTextureCoordinate2.h>
++#include <Inventor/nodes/SoIndexedFaceSet.h>
++#include <Inventor/nodes/SoTranslation.h>
++
++#include <Inventor/@Gui@/common/gl.h>
++#include <Inventor/@Gui@/SoAny.h>
++
++#include <Inventor/@Gui@/nodes/SoGuiPane.h>
++#include <Inventor/@Gui@/nodes/SoGuiSlider2.h>
++#include <assert.h>
++
++// *************************************************************************
++
++/*!
++  \class SoGuiSlider2 Inventor/@Gui@/nodes/SoGuiSlider2.h
++  \brief A GUI component for a 2-dimensional slider.
++
++  The SoGuiSlider2 node is for creating 2D user interfaces with
++  sliders.
++
++*/
++
++// *************************************************************************
++
++class Slider2 {
++public:
++  SoGuiSlider2 * kit;
++  SoFieldSensor * sizeSensor;
++  SoFieldSensor * valueSensor;
++
++  Slider2(void);
++  ~Slider2(void);
++
++  // sensors callbacks
++  static void sizeChangeCB(void * closure, SoSensor * sensor);
++  static void valueChangeCB(void * closure, SoSensor * sensor);
++
++  static const char * knobgeometry[];
++  SoTranslation * knobtranslation;
++
++  SoGuiPane * pane;
++
++  SbBool grabbing;
++
++  SbVec2f graboffset;
++  SbVec2f grabval;
++
++  SbVec2f pickpos;
++  SbVec2f grabpos;
++};
++
++Slider2::Slider2(void)
++{
++  this->kit = NULL;
++  this->sizeSensor = NULL;
++  this->valueSensor = NULL;
++  this->grabbing = FALSE;
++  this->pane = NULL;
++}
++
++Slider2::~Slider2(void)
++{
++  if ( this->sizeSensor ) {
++    this->sizeSensor->detach();
++    delete this->sizeSensor;
++    this->sizeSensor = NULL;
++  }
++  if ( this->valueSensor ) {
++    this->valueSensor->detach();
++    delete this->valueSensor;
++    this->valueSensor = NULL;
++  }
++  this->kit = NULL;
++}
++
++void
++Slider2::sizeChangeCB(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  Slider2 * internals = (Slider2 *) closure;
++  assert(internals->kit);
++  internals->kit->sizeUpdate();
++}
++
++void
++Slider2::valueChangeCB(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  Slider2 * internals = (Slider2 *) closure;
++  assert(internals->kit);
++  internals->kit->valueUpdate();
++}
++
++const char *
++Slider2::knobgeometry[] =
++{
++  "# Inventor V2.1 ascii",
++  "",
++  "Separator {",
++  "  DEF knobtranslation Translation {}",
++  "  Coordinate3 {",
++  "    point [",
++  // inner loop
++  "      0 0 0,",
++  "      1 0 0,",
++  "      1 1 0,",
++  "      0 1 0,",
++  // middle inner
++  "      -1 -1 0,",
++  "      2 -1 0,",
++  "      2 2 0,",
++  "      -1 2 0,",
++  // middle outer
++  "      -2 -2 0,",
++  "      3 -2 0,",
++  "      3 3 0,",
++  "      -2 3 0,",
++  // outer loop
++  "      -3 -3 0,",
++  "      4 -3 0,",
++  "      4 4 0,",
++  "      -3 4 0",
++  "    ]",
++  "  }",
++  "  Material {",
++  "    diffuseColor 0.7 0.7 0.7",
++  "  }",
++  "  IndexedFaceSet {",
++  "    coordIndex [",
++  // middle
++  "      8 9 5 8 -1",
++  "      8 5 4 8 -1",
++  "      9 10 6 9 -1",
++  "      9 6 5 9 -1",
++  "      10 11 7 10 -1",
++  "      10 7 6 10 -1",
++  "      11 8 4 11 -1",
++  "      11 4 7 11 -1",
++  "    ]",
++  "  }",
++  "  Material {",
++  "    diffuseColor 0.5 0.5 0.5",
++  "  }",
++  "  IndexedFaceSet {",
++  "    coordIndex [",
++  // inner shade
++  "      6 7 3 6 -1",
++  "      6 3 2 6 -1",
++  "      7 4 0 7 -1",
++  "      7 0 3 7 -1",
++  // outer shade
++  "      12 13 9 12 -1",
++  "      12 9 8 12 -1",
++  "      13 14 10 13 -1",
++  "      13 10 9 13 -1",
++  "    ]",
++  "  }",
++  "  Material {",
++  "    diffuseColor 0.9 0.9 0.9",
++  "  }",
++  "  IndexedFaceSet {",
++  "    coordIndex [",
++  // inner light
++  "      4 5 1 4 -1",
++  "      4 1 0 4 -1",
++  "      5 6 2 5 -1",
++  "      5 2 1 5 -1",
++  // outer light
++  "      14 15 11 14 -1",
++  "      14 11 10 14 -1",
++  "      15 12 8 15 -1",
++  "      15 8 11 15 -1",
++  "    ]",
++  "  }",
++  "}",
++  NULL
++};
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((Slider2 *) obj->internals)
++
++void
++SoGuiSlider2::initClass(void)
++{
++  SO_KIT_INIT_CLASS(SoGuiSlider2, SoBaseKit, "BaseKit");
++}
++
++SO_KIT_SOURCE(SoGuiSlider2);
++
++SoGuiSlider2::SoGuiSlider2(void)
++{
++  this->internals = (void *) new Slider2;
++  PRIVATE(this)->kit = this;
++
++  SO_KIT_CONSTRUCTOR(SoGuiSlider2);
++
++  SO_KIT_ADD_FIELD(size, (SbVec3f(1.0f, 1.0f, 0.0f)));
++
++  SO_KIT_ADD_FIELD(min, (SbVec2f(0.0f, 0.0f)));
++  SO_KIT_ADD_FIELD(max, (SbVec2f(1.0f, 1.0f)));
++  SO_KIT_ADD_FIELD(value, (SbVec2f(0.0f, 0.0f)));
++
++  SO_KIT_ADD_FIELD(alwaysHook, (TRUE));
++
++  SO_KIT_ADD_CATALOG_ENTRY(knobGeometry, SoSeparator, FALSE, topSeparator, "", TRUE);
++  SO_KIT_ADD_CATALOG_ENTRY(surfaceFaceSet, SoIndexedFaceSet, FALSE, surfaceGeometry, "", FALSE);
++  SO_KIT_ADD_CATALOG_ENTRY(surfaceCoords, SoCoordinate3, FALSE, surfaceGeometry, surfaceFaceSet, FALSE);
++  SO_KIT_ADD_CATALOG_ENTRY(surfaceTexCoords, SoTextureCoordinate2, FALSE, surfaceGeometry, surfaceCoords, FALSE);
++  SO_KIT_ADD_CATALOG_ENTRY(surfaceTexture, SoTexture2, TRUE, surfaceGeometry, surfaceTexCoords, TRUE);
++  SO_KIT_ADD_CATALOG_ENTRY(surfaceMaterial, SoMaterial, TRUE, surfaceGeometry, surfaceTexture, TRUE);
++  SO_KIT_ADD_CATALOG_ENTRY(surfaceGeometry, SoSeparator, FALSE, topSeparator, knobGeometry, FALSE);
++  SO_KIT_ADD_CATALOG_ENTRY(topSeparator, SoSeparator, FALSE, this, "", FALSE);
++
++  SO_KIT_INIT_INSTANCE();
++
++  static float surfacetexturecoordinates[][2] = { {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f} };
++  SoTextureCoordinate2 * surfacetexcoords = SO_GET_ANY_PART(this, "surfaceTexCoords", SoTextureCoordinate2);
++  assert(surfacetexcoords);
++  surfacetexcoords->point.setValues(0, 4, surfacetexturecoordinates);
++
++  static int32_t surfaceindices[] = { 0, 1, 2, -1, 0, 2, 3, -1 };
++  SoIndexedFaceSet * surfacefaceset = SO_GET_ANY_PART(this, "surfaceFaceSet", SoIndexedFaceSet);
++  assert(surfacefaceset);
++  surfacefaceset->textureCoordIndex.setValues(0, 8, surfaceindices);
++  surfacefaceset->coordIndex.setValues(0, 8, surfaceindices);
++ 
++  SoNode * knob = (SoSeparator *) SoAny::loadSceneGraph(Slider2::knobgeometry);
++  assert(knob != NULL && knob->isOfType(SoSeparator::getClassTypeId()));
++  this->setPart("knobGeometry", knob);
++
++  SoNode * node = SoAny::scanSceneForName(knob, "knobtranslation", FALSE);
++  assert(node != NULL && node->isOfType(SoTranslation::getClassTypeId()));
++  PRIVATE(this)->knobtranslation = (SoTranslation *) node;
++
++  this->sizeUpdate();
++  
++  // set up sensors
++  PRIVATE(this)->sizeSensor = new SoFieldSensor(Slider2::sizeChangeCB, PRIVATE(this));
++  PRIVATE(this)->sizeSensor->attach(&(this->size));
++  PRIVATE(this)->valueSensor = new SoFieldSensor(Slider2::valueChangeCB, PRIVATE(this));
++  PRIVATE(this)->valueSensor->attach(&(this->value));
++}
++
++SoGuiSlider2::~SoGuiSlider2(void)
++{
++  Slider2 * obj = PRIVATE(this);
++  delete obj;
++  this->internals = NULL;
++}
++
++void
++SoGuiSlider2::sizeUpdate(void)
++{
++  SbVec3f sizeval = this->size.getValue();
++  if ( sizeval[0] != 0.0f && sizeval[1] != 0.0f ) {
++    float coordinates[][3] = { {0.0f, 0.0f, 0.0f}, {sizeval[0], 0.0f, 0.0f}, {sizeval[0], sizeval[1], 0.0f}, {0.0f, sizeval[1], 0.0f} };
++    SoCoordinate3 * coords = SO_GET_ANY_PART(this, "surfaceCoords", SoCoordinate3);
++    assert(coords);
++    coords->point.setValues(0, sizeof(coordinates) / sizeof(coordinates[0]), coordinates);
++    this->valueUpdate();
++  }
++}
++
++void
++SoGuiSlider2::valueUpdate(void)
++{
++  assert(PRIVATE(this)->knobtranslation != NULL);
++  SbVec2f val = this->value.getValue();
++  SbVec2f minval = this->min.getValue();
++  SbVec2f maxval = this->max.getValue();
++  SbVec3f sizeval = this->size.getValue();
++
++  SbVec2f nval;
++  nval[0] = (val[0] - minval[0]) / (maxval[0] - minval[0]);
++  nval[1] = (val[1] - minval[1]) / (maxval[1] - minval[1]);
++
++  SbVec3f translation;
++  translation[0] = nval[0] * sizeval[0];
++  translation[1] = nval[1] * sizeval[1];
++  translation[2] = 0.0f;
++
++  PRIVATE(this)->knobtranslation->translation.setValue(translation);
++}
++
++void
++SoGuiSlider2::handleEvent(SoHandleEventAction * action)
++{
++  if ( action->isHandled() ) return;
++
++  const SoEvent * event = action->getEvent();
++
++  if ( PRIVATE(this)->grabbing ) { // click-and-drag
++    if ( event->isOfType(SoLocation2Event::getClassTypeId()) ) {
++      assert(PRIVATE(this)->pane != NULL);
++
++      // although the return value is discarded, we need to make this call to make
++      // sure the raypick action is run over the scene graph so the pane can return
++      // a useful value...
++      action->getPickedPoint();
++
++      SbVec2f raypos = PRIVATE(this)->pane->getRayPickIntersectionPoint();
++      if ( raypos[0] != -1.0f ) {
++        SbVec2f imagpos = SbVec2f(raypos[0], raypos[1]) + PRIVATE(this)->graboffset;
++        SbVec2f minval = this->min.getValue();
++        SbVec2f maxval = this->max.getValue();
++        SbVec3f sizeval = this->size.getValue();
++        SbVec2f imagval;
++        imagval[0] = minval[0] + (maxval[0] - minval[0]) * So at Gui@Clamp(imagpos[0] / sizeval[0], 0.0f, 1.0f);
++        imagval[1] = minval[1] + (maxval[1] - minval[1]) * So at Gui@Clamp(imagpos[1] / sizeval[1], 0.0f, 1.0f);
++        this->value.setValue(imagval);
++      }
++      action->setHandled();
++    }
++    else if ( event->isOfType(SoMouseButtonEvent::getClassTypeId()) ) {
++      SoMouseButtonEvent * mbevent = (SoMouseButtonEvent *) event;
++      if ( (mbevent->getButton() == SoMouseButtonEvent::BUTTON1) &&
++           (mbevent->getState() == SoButtonEvent::UP) ) {
++        PRIVATE(this)->grabbing = FALSE;
++        PRIVATE(this)->pane = NULL;
++        action->setHandled();
++      }
++    }
++  }
++  else if ( event->isOfType(SoMouseButtonEvent::getClassTypeId()) ) {
++    SoMouseButtonEvent * mbevent = (SoMouseButtonEvent *) event;
++    if ( (mbevent->getButton() == SoMouseButtonEvent::BUTTON1) &&
++         (mbevent->getState() == SoButtonEvent::DOWN) ) {
++      action->setPickRadius(0);
++      const SoPickedPointList & pplist = action->getPickedPointList();
++      if ( pplist.getLength() > 0 ) {
++        int i;
++        for ( i = 0; i < pplist.getLength(); i++ ) {
++          if ( action->isHandled() ) break;
++          const SoPickedPoint * pp = pplist[i];
++          const SoFullPath * path = (const SoFullPath *) pp->getPath();
++          SoNode * node = NULL;
++          SoNode * knob = SO_GET_ANY_PART(this, "knobGeometry", SoSeparator);
++          int j = path->getLength() - 1;
++          for ( ; j >= 0; j-- ) {
++            SoNode * node = path->getNode(j);
++            if ( node == knob ) break;
++            node = NULL;
++          }
++
++          if ( node != NULL ) {
++            PRIVATE(this)->grabbing = TRUE;
++            action->setHandled();
++
++            SbVec3f point = pp->getObjectPoint();
++            SbVec2f sizeval = SbVec2f(this->size.getValue()[0], this->size.getValue()[1]);
++
++            const SoFullPath * path = (const SoFullPath *) action->getCurPath();
++            int i = path->getLength() - 1;
++            SoNode * node = NULL;
++            for ( ; i >= 0; i-- ) {
++              node = path->getNode(i);
++              if ( node->isOfType(SoGuiPane::getClassTypeId()) ) break;
++              node = NULL;
++            }
++            assert(node != NULL);
++            PRIVATE(this)->pane = (SoGuiPane *) node;
++            PRIVATE(this)->grabval = this->value.getValue();
++            PRIVATE(this)->pickpos = SbVec2f(point[0], point[1]);
++
++            SbVec2f raypos = PRIVATE(this)->pane->getRayPickIntersectionPoint();
++            PRIVATE(this)->grabpos = raypos;
++            SbVec2f upper = this->value.getValue() - this->min.getValue();
++            SbVec2f lower = this->max.getValue() - this->min.getValue();
++
++            SbVec2f realval;
++            realval[0] = (upper[0] / lower[0]) * sizeval[0];
++            realval[1] = (upper[1] / lower[1]) * sizeval[1];
++            PRIVATE(this)->graboffset = realval - raypos;
++          }
++        }
++        for ( i = 0; i < pplist.getLength(); i++ ) {
++          if ( action->isHandled() ) break;
++          const SoPickedPoint * pp = pplist[i];
++          const SoPath * path = pp->getPath();
++          SoNode * node = ((SoFullPath *) path)->getTail();
++          if ( node == ((SoNode *) SO_GET_ANY_PART(this, "surfaceFaceSet", SoIndexedFaceSet)) ) {
++            SbVec3f point = pp->getObjectPoint();
++            SbVec3f sizeval = this->size.getValue();
++            SbVec2f minval = this->min.getValue();
++            SbVec2f maxval = this->max.getValue();
++            SbVec2f val;
++            val[0] = minval[0] + (point[0] / sizeval[0]) * (maxval[0] - minval[0]);
++            val[1] = minval[1] + (point[1] / sizeval[1]) * (maxval[1] - minval[1]);
++            this->value.setValue(val);
++            action->setHandled();
++            if ( this->alwaysHook.getValue() ) {
++              PRIVATE(this)->grabbing = TRUE;
++              const SoFullPath * path = (const SoFullPath *) action->getCurPath();
++              SoNode * node = NULL;
++              int j = path->getLength() - 1;
++              for ( ; j >= 0; j-- ) {
++                node = path->getNode(j);
++                if ( node->isOfType(SoGuiPane::getClassTypeId()) ) break;
++                node = NULL;
++              }
++              assert(node != NULL);
++              PRIVATE(this)->pane = (SoGuiPane *) node;
++              PRIVATE(this)->grabval = this->value.getValue();
++              PRIVATE(this)->pickpos = SbVec2f(point[0], point[1]);
++
++              SbVec2f raypos = PRIVATE(this)->pane->getRayPickIntersectionPoint();
++              PRIVATE(this)->grabpos = raypos;
++              SbVec2f upper = this->value.getValue() - this->min.getValue();
++              SbVec2f lower = this->max.getValue() - this->min.getValue();
++              SbVec2f sizeval = SbVec2f(this->size.getValue()[0], this->size.getValue()[1]);
++
++              SbVec2f realval;
++              realval[0] = (upper[0] / lower[0]) * sizeval[0];
++              realval[1] = (upper[1] / lower[1]) * sizeval[1];
++              PRIVATE(this)->graboffset = realval - raypos;
++            }
++          }
++        }
++      }
++    }
++  }
++}
++
++#undef PRIVATE
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Slider2.h.in
+@@ -0,0 +1,88 @@
++#ifndef COIN_SOGUISLIDER2_H
++#define COIN_SOGUISLIDER2_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/fields/SoSFBool.h>
++#include <Inventor/fields/SoSFVec2f.h>
++#include <Inventor/fields/SoSFVec3f.h>
++
++#include <Inventor/nodekits/SoBaseKit.h>
++
++class SoGuiSlider2 : public SoBaseKit {
++  typedef SoBaseKit inherited;
++
++  SO_KIT_HEADER(SoGuiSlider2);
++
++  SO_KIT_CATALOG_ENTRY_HEADER(topSeparator);
++  SO_KIT_CATALOG_ENTRY_HEADER(surfaceGeometry);
++  SO_KIT_CATALOG_ENTRY_HEADER(surfaceTexture);
++  SO_KIT_CATALOG_ENTRY_HEADER(surfaceMaterial);
++  SO_KIT_CATALOG_ENTRY_HEADER(surfaceTexCoords);
++  SO_KIT_CATALOG_ENTRY_HEADER(surfaceCoords);
++  SO_KIT_CATALOG_ENTRY_HEADER(surfaceFaceSet);
++  SO_KIT_CATALOG_ENTRY_HEADER(knobGeometry);
++
++public:
++  static void initClass(void);
++
++  SoGuiSlider2(void);
++
++  SoSFVec3f size;
++
++  SoSFVec2f min;
++  SoSFVec2f max;
++  SoSFVec2f value;
++
++  SoSFBool alwaysHook;
++
++  virtual void handleEvent(SoHandleEventAction * action);
++
++  void sizeUpdate(void);
++  void valueUpdate(void);
++
++protected:
++  virtual ~SoGuiSlider2(void);
++
++private:
++  void * internals;
++
++};
++
++#endif // !COIN_SOGUISLIDER2_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/ToggleButton.cpp.in
+@@ -0,0 +1,208 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/actions/SoHandleEventAction.h>
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoCoordinate3.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++#include <Inventor/events/SoMouseButtonEvent.h>
++#include <Inventor/SoPickedPoint.h>
++
++#include <Inventor/@Gui@/SoAny.h>
++#include <Inventor/@Gui@/nodes/SoGuiToggleButton.h>
++#include <assert.h>
++
++// *************************************************************************
++
++class ToggleButton {
++public:
++  ToggleButton(void);
++
++  SoGuiToggleButton * api;
++
++  SoCoordinate3 * coords;
++  SoNode * faceset;
++  SoFieldSensor * size_sensor;
++  static void size_updated_cb(void * closure, SoSensor * sensor);
++
++  static const char * scene[];
++};
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((ToggleButton *)obj->internals)
++
++void
++SoGuiToggleButton::initClass(void)
++{
++  SO_KIT_INIT_CLASS(SoGuiToggleButton, SoBaseKit, "BaseKit");
++}
++
++SO_KIT_SOURCE(SoGuiToggleButton);
++
++SoGuiToggleButton::SoGuiToggleButton(void)
++{
++  this->internals = new ToggleButton;
++  PRIVATE(this)->api = this;
++
++  SO_KIT_CONSTRUCTOR(SoGuiToggleButton);
++
++  SO_KIT_ADD_FIELD(size, (SbVec3f(1.0f, 1.0f, 0.0f)));
++  SO_KIT_ADD_FIELD(on, (FALSE));
++
++  SO_KIT_ADD_CATALOG_ENTRY(root, SoSeparator, FALSE, this, "", FALSE);
++
++  SO_KIT_INIT_INSTANCE();
++
++  SoNode * scene = SoAny::loadSceneGraph(ToggleButton::scene);
++  assert(scene);
++  assert(scene->isOfType(SoSeparator::getClassTypeId()));
++  scene->ref();
++
++  PRIVATE(this)->coords = (SoCoordinate3 *) SoAny::scanSceneForName(scene, "coords");
++  assert(PRIVATE(this)->coords);
++  assert(PRIVATE(this)->coords->isOfType(SoCoordinate3::getClassTypeId()));
++  PRIVATE(this)->faceset = SoAny::scanSceneForName(scene, "faceset");
++  assert(PRIVATE(this)->faceset);
++
++  scene->unrefNoDelete();
++  this->setAnyPart("root", scene);
++
++  PRIVATE(this)->size_sensor = new SoFieldSensor(ToggleButton::size_updated_cb, PRIVATE(this));
++  PRIVATE(this)->size_sensor->attach(&(this->size));
++}
++
++
++SoGuiToggleButton::~SoGuiToggleButton(void)
++{
++  delete PRIVATE(this)->size_sensor;
++  ToggleButton * obj = PRIVATE(this);
++  delete obj;
++}
++
++void
++SoGuiToggleButton::handleEvent(SoHandleEventAction * action)
++{
++  const SoEvent * ev = action->getEvent();
++  if ( ev->isOfType(SoMouseButtonEvent::getClassTypeId()) ) {
++    SbBool hit = FALSE;
++    const SoPickedPointList & ppoints = action->getPickedPointList();
++    assert(PRIVATE(this)->faceset);
++    int i = 0;
++    for ( i = 0; !hit && i < ppoints.getLength(); i++ ) {
++      const SoPickedPoint * point = ppoints[i];
++      const SoFullPath * path = (const SoFullPath *) point->getPath();
++      assert(path);
++      SoNode * node = path->getTail();
++      if ( node == PRIVATE(this)->faceset ) hit = TRUE;
++    }
++    if ( hit ) {
++      const SoMouseButtonEvent * event = (SoMouseButtonEvent *) ev;
++      if ( event->getState() == SoButtonEvent::DOWN ) {
++        if ( this->on.getValue() ) {
++          this->on.setValue(FALSE);
++        } else {
++          this->on.setValue(TRUE);
++        }
++        action->setHandled();
++      }
++    }
++  }
++  if ( !action->isHandled() ) {
++    inherited::handleEvent(action);
++  }
++}
++
++#undef PRIVATE
++
++// *************************************************************************
++// ToggleButton
++// *************************************************************************
++
++#define PUBLIC(obj) (obj->api)
++
++const char *
++ToggleButton::scene[] =
++{
++  "#Inventor V2.1 ascii",
++  "",
++  "Separator {",
++  "  DEF coords Coordinate3 {",
++  "    point [",
++  "      0 0 0,",
++  "      1 0 0,",
++  "      1 1 0,",
++  "      0 1 0",
++  "    ]",
++  "  }",
++  "  DEF faceset IndexedFaceSet {",
++  "    coordIndex [",
++  "      0 1 2 -1",
++  "      0 2 3 -1",
++  "    ]",
++  "  }",
++  "}",
++  NULL
++};
++
++ToggleButton::ToggleButton(void)
++{
++  this->api = NULL;
++  this->coords = NULL;
++  this->size_sensor = NULL;
++}
++
++void
++ToggleButton::size_updated_cb(void * closure, SoSensor * sensor)
++{
++  assert(closure);
++  ToggleButton * me = (ToggleButton *) closure;
++  assert(PUBLIC(me));
++  SbVec3f size = PUBLIC(me)->size.getValue();
++  assert(me->size_sensor);
++  me->size_sensor->detach();
++  assert(me->coords);
++  SbBool save = me->coords->point.enableNotify(FALSE);
++  me->coords->point.set1Value(0, SbVec3f(0.0f, 0.0f, 0.0f));
++  me->coords->point.set1Value(1, SbVec3f(size[0], 0.0f, 0.0f));
++  me->coords->point.set1Value(2, SbVec3f(size[0], size[1], 0.0f));
++  me->coords->point.set1Value(3, SbVec3f(0.0f, size[1], 0.0f));
++  me->coords->enableNotify(save);
++  if ( save ) me->coords->point.touch();
++  me->size_sensor->attach(&(PUBLIC(me)->size));
++}
++
++#undef PUBLIC
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/ToggleButton.h.in
+@@ -0,0 +1,68 @@
++#ifndef COIN_SOGUITOGGLEBUTTON_H
++#define COIN_SOGUITOGGLEBUTTON_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/fields/SoSFBool.h>
++#include <Inventor/fields/SoSFVec3f.h>
++#include <Inventor/nodekits/SoBaseKit.h>
++
++class SoGuiToggleButton : public SoBaseKit {
++  typedef SoBaseKit inherited;
++  SO_KIT_HEADER(SoGuiToggleButton);
++  SO_KIT_CATALOG_ENTRY_HEADER(root);
++public:
++  static void initClass(void);
++
++  SoGuiToggleButton(void);
++
++  SoSFVec3f size;
++  SoSFBool on;
++
++  virtual void handleEvent(SoHandleEventAction * action);
++
++protected:
++  virtual ~SoGuiToggleButton(void);
++
++private:
++  void * internals;
++
++};
++
++#endif // !COIN_SOGUITOGGLEBUTTON_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Translation.cpp.in
+@@ -0,0 +1,126 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <assert.h>
++
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/actions/SoGLRenderAction.h>
++#include <Inventor/actions/SoPickAction.h>
++#include <Inventor/actions/SoRayPickAction.h>
++#include <Inventor/actions/SoGetMatrixAction.h>
++#include <Inventor/elements/SoModelMatrixElement.h>
++#include <Inventor/SoPath.h>
++
++#include <Inventor/@Gui@/nodes/SoGuiPane.h>
++#include <Inventor/@Gui@/nodes/SoGuiTranslation.h>
++
++// *************************************************************************
++
++SO_NODE_SOURCE(SoGuiTranslation);
++
++void
++SoGuiTranslation::initClass(void)
++{
++  SO_NODE_INIT_CLASS(SoGuiTranslation, SoTransformation, "Transformation");
++}
++
++SoGuiTranslation::SoGuiTranslation(void)
++{
++  SO_NODE_CONSTRUCTOR(SoGuiTranslation);
++  SO_NODE_ADD_FIELD(translation, (SbVec3f(0.0f, 0.0f, 0.0f)));
++}
++
++SoGuiTranslation::~SoGuiTranslation(void)
++{
++}
++
++void
++SoGuiTranslation::doAction(SoAction * action)
++{
++  // SoDebugError::postInfo("SoGuiTranslation::doAction", "invoked by %s", action->getTypeId().getName().getString());
++  int i;
++  SoGuiPane * pane = NULL;
++  const SoFullPath * path = (const SoFullPath *) action->getCurPath();
++  for ( i = path->getLength() - 1; (i >= 0) && (pane == NULL); i-- ) {
++    SoNode * node = path->getNode(i);
++    assert(node);
++    if ( node->isOfType(SoGuiPane::getClassTypeId()) ) pane = (SoGuiPane *) node;
++  }
++  if ( pane == NULL ) {
++    SoDebugError::postInfo("SoGuiTranslation::doAction", "SoGuiTranslation only works below an SoGuiPane node");
++    return;
++  }
++  SoModelMatrixElement::translateBy(action->getState(), this,
++                                    this->translation.getValue());
++
++//  pane->moveBy(action->getState(), this->translation.getValue());
++}
++
++void
++SoGuiTranslation::GLRender(SoGLRenderAction * action)
++{
++  this->doAction(action);
++}
++
++void
++SoGuiTranslation::pick(SoPickAction * action)
++{
++  this->doAction(action);
++}
++
++void
++SoGuiTranslation::rayPick(SoRayPickAction * action)
++{
++  this->doAction(action);
++}
++
++void
++SoGuiTranslation::getMatrix(SoGetMatrixAction * action)
++{
++  SoDebugError::postInfo("SoGuiTranslation::getMatrix", "invoked");
++  int i;
++  SoGuiPane * pane = NULL;
++  const SoFullPath * path = (const SoFullPath *) action->getCurPath();
++  for ( i = path->getLength() - 1; (i >= 0) && (pane == NULL); i-- ) {
++    SoNode * node = path->getNode(i);
++    assert(node);
++    if ( node->isOfType(SoGuiPane::getClassTypeId()) ) pane = (SoGuiPane *) node;
++  }
++  if ( pane == NULL ) {
++    SoDebugError::postInfo("SoGuiTranslation::getMatrix", "SoGuiTranslation only works below an SoGuiPane node");
++    return;
++  }
++  pane->applyMoveBy(action, this->translation.getValue());
++}
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Translation.h.in
+@@ -0,0 +1,70 @@
++#ifndef COIN_SOGUITRANSLATION_H
++#define COIN_SOGUITRANSLATION_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/fields/SoSFVec3f.h>
++#include <Inventor/nodes/SoTransformation.h>
++
++class SoGuiTranslation : public SoTransformation {
++  typedef SoTransformation inherited;
++  SO_NODE_HEADER(SoGuiTranslation);
++
++public:
++  static void initClass(void);
++
++  SoGuiTranslation(void);
++
++  SoSFVec3f translation;
++
++  virtual void doAction(SoAction * action);
++  virtual void GLRender(SoGLRenderAction * action);
++  virtual void pick(SoPickAction * action);
++  virtual void rayPick(SoRayPickAction * action);
++  virtual void getMatrix(SoGetMatrixAction * action);
++
++protected:
++  virtual ~SoGuiTranslation(void);
++
++private:
++  void * internals;
++
++};
++
++#endif // !COIN_SOGUITRANSLATION_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/ViewpointWrapper.cpp.in
+@@ -0,0 +1,347 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/nodes/SoGuiViewpointWrapper.h>
++#include <Inventor/SoPath.h>
++#include <Inventor/sensors/SoPathSensor.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++#include <Inventor/actions/SoGetMatrixAction.h>
++#include <Inventor/actions/SoGetBoundingBoxAction.h>
++#include <Inventor/actions/SoSearchAction.h>
++#include <Inventor/fields/SoSFBool.h>        
++#include <Inventor/fields/SoSFTime.h>
++#include <assert.h>
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++#ifdef HAVE_SOVRMLVIEWPOINT
++#include <Inventor/VRMLnodes/SoVRMLViewpoint.h>
++#endif // HAVE_SOVRMLVIEWPOINT
++
++// FIXME: make a generic class to handle bindable nodes, pederb 2003-08-29
++
++void
++SoGuiViewpointWrapper::initClass(void)
++{
++  SO_NODE_INIT_CLASS(SoGuiViewpointWrapper, SoPerspectiveCamera, "PerspectiveCamera");
++}
++
++SO_NODE_SOURCE(SoGuiViewpointWrapper);
++
++SoGuiViewpointWrapper::SoGuiViewpointWrapper(void)
++{
++  SO_NODE_CONSTRUCTOR(SoGuiViewpointWrapper);
++  this->scenegraph = NULL;
++  this->pathtoviewpoint = NULL;
++  this->positionsensor = new SoFieldSensor(fieldsensor_cb, this);
++  this->orientationsensor = new SoFieldSensor(fieldsensor_cb, this);
++  this->heightanglesensor = new SoFieldSensor(fieldsensor_cb, this);
++  this->pathsensor = new SoPathSensor(pathsensor_cb, this);
++  this->attachFieldSensors();
++  this->gmaction = new SoGetMatrixAction(SbViewportRegion(100, 100));
++}
++
++SoGuiViewpointWrapper::~SoGuiViewpointWrapper(void)
++{
++  this->pathsensor->detach();
++  delete this->pathsensor;
++  if (this->pathtoviewpoint) this->pathtoviewpoint->unref();
++  this->detachFieldSensors();
++  delete this->positionsensor;
++  delete this->orientationsensor;
++  delete this->heightanglesensor;
++  delete this->gmaction;
++  if (this->scenegraph) this->scenegraph->unref();
++}
++
++void 
++SoGuiViewpointWrapper::sendBindEvents(SoNode * node, const SbBool onoff)
++{
++  SoSFBool * isBound = (SoSFBool*) node->getField("isBound");
++  SoSFTime * bindTime = (SoSFTime*) node->getField("bindTime");
++  if (isBound && bindTime) {
++    isBound->setValue(onoff);
++    bindTime->setValue(SbTime::getTimeOfDay());
++  }
++}
++
++void 
++SoGuiViewpointWrapper::setViewpoint(SoPath * path)
++{
++  if (this->pathtoviewpoint) {
++    this->sendBindEvents(this->pathtoviewpoint->getTail(), FALSE);
++    this->pathtoviewpoint->unref();
++    this->pathsensor->detach();
++  }
++  this->pathtoviewpoint = (SoFullPath*) path;
++  if (path) {
++    path->ref();
++    this->pathsensor->attach(path); 
++    this->updateCamera();
++    this->sendBindEvents(this->pathtoviewpoint->getTail(), TRUE);
++
++    // calculate a focal distance. It's not possible to specify a
++    // focal point in VRML97. We just set it to the center of the
++    // scene.
++    SbViewportRegion vp(640, 480);
++    SoGetBoundingBoxAction bboxaction(vp);
++    bboxaction.apply(path->getHead());
++    SbVec3f center = bboxaction.getCenter();
++    
++    float dist = (this->position.getValue() - center).length();
++    // avoid focalDistance ~= 0
++    if (dist < 0.1f) dist = 0.1f;
++    this->focalDistance = dist; 
++  }
++}
++
++void 
++SoGuiViewpointWrapper::updateCamera(void)
++{
++#ifdef HAVE_SOVRMLVIEWPOINT
++  if (this->pathtoviewpoint == NULL) return;
++
++  this->detachFieldSensors();
++
++  SoVRMLViewpoint * vp = (SoVRMLViewpoint*)
++    this->pathtoviewpoint->getTail();
++  assert(vp->getTypeId() == SoVRMLViewpoint::getClassTypeId());
++  
++  this->gmaction->apply(this->pathtoviewpoint);
++  SbVec3f pos = vp->position.getValue();
++  float angle = vp->fieldOfView.getValue();
++
++  SbRotation rot = vp->orientation.getValue();
++  SbMatrix m;
++  m.setRotate(rot);  
++  this->gmaction->getMatrix().multVecMatrix(pos, pos);
++  m.multRight(this->gmaction->getInverse());
++  m.multLeft(this->gmaction->getMatrix());
++  rot.setValue(m);
++  
++  this->position = pos;
++  this->orientation = rot;
++  this->heightAngle = angle;
++
++  this->attachFieldSensors();
++#endif // HAVE_SOVRMLVIEWPOINT
++}
++
++void
++SoGuiViewpointWrapper::updateViewpoint(void)
++{
++#ifdef HAVE_SOVRMLVIEWPOINT
++  if (this->pathtoviewpoint == NULL) return;
++  this->pathsensor->detach();
++  
++  SoVRMLViewpoint * vp = (SoVRMLViewpoint*)
++    this->pathtoviewpoint->getTail();
++  assert(vp->getTypeId() == SoVRMLViewpoint::getClassTypeId());
++  
++  this->gmaction->apply(this->pathtoviewpoint);
++  SbVec3f pos = this->position.getValue();
++  float angle = this->heightAngle.getValue();
++
++  SbRotation rot = this->orientation.getValue();
++  SbMatrix m;
++  m.setRotate(rot);  
++  this->gmaction->getInverse().multVecMatrix(pos, pos);
++  m.multRight(this->gmaction->getMatrix());
++  m.multLeft(this->gmaction->getInverse());
++  rot.setValue(m);
++  
++  vp->position = pos;
++  vp->orientation = rot;
++  vp->fieldOfView = angle;
++
++  this->pathsensor->attach(this->pathtoviewpoint); 
++#endif // HAVE_SOVRMLVIEWPOINT
++}
++
++void 
++SoGuiViewpointWrapper::attachFieldSensors(void)
++{
++  this->positionsensor->attach(&this->position);
++  this->orientationsensor->attach(&this->orientation);
++  this->heightanglesensor->attach(&this->heightAngle);
++}
++
++void 
++SoGuiViewpointWrapper::detachFieldSensors(void)
++{
++  this->positionsensor->detach();
++  this->orientationsensor->detach();
++  this->heightanglesensor->detach();
++}
++
++void 
++SoGuiViewpointWrapper::fieldsensor_cb(void * data, SoSensor * sensor)
++{
++  SoGuiViewpointWrapper * thisp = (SoGuiViewpointWrapper *) data;
++  thisp->updateViewpoint();
++}
++
++void 
++SoGuiViewpointWrapper::pathsensor_cb(void * data, SoSensor * sensor)
++{
++  SoGuiViewpointWrapper * thisp = (SoGuiViewpointWrapper *) data;
++  thisp->updateCamera();
++}
++
++void 
++SoGuiViewpointWrapper::set_bind_cb(void * data, SoSensor * sensor)
++{
++  SoGuiViewpointWrapper * thisp = (SoGuiViewpointWrapper *) data;
++  int idx = thisp->set_bind_sensorlist.find(sensor);
++  
++  if (idx >= 0) {
++    SoNode * node = thisp->nodelist[idx];
++    node->ref();
++    SoSFBool * set_bind = (SoSFBool*) node->getField(SbName("set_bind"));
++    assert(set_bind);
++    if (set_bind->getValue()) { // TRUE event
++      // check if node is already bound
++      if (thisp->pathtoviewpoint && thisp->pathtoviewpoint->getTail() == node) return;
++      thisp->nodelist.remove(idx);
++      thisp->nodelist.insert(node, 0);
++      
++      thisp->bindTopOfStack();
++    }
++    else if (idx == 0) { // FALSE event to top-of-stack
++      thisp->nodelist.remove(0);
++      thisp->nodelist.append(node); // place the node at the bottom of the stack
++
++      thisp->bindTopOfStack();
++    }
++    node->unrefNoDelete();
++  }
++}
++
++void
++SoGuiViewpointWrapper::bindTopOfStack(void)
++{
++  if (this->nodelist.getLength()) {
++    this->sa.setNode(this->nodelist[0]);
++    this->sa.setInterest(SoSearchAction::FIRST);
++    this->sa.apply(this->scenegraph);
++    if (this->sa.getPath()) {
++      this->setViewpoint(this->sa.getPath());
++    }
++    this->sa.reset();
++  }
++}
++
++SbBool 
++SoGuiViewpointWrapper::hasViewpoints(SoNode * root)
++{
++#ifdef HAVE_SOVRMLVIEWPOINT
++  SoSearchAction sa;
++  sa.setInterest(SoSearchAction::ALL);
++  sa.setType(SoVRMLViewpoint::getClassTypeId());
++  sa.apply(root);
++  return sa.getPaths().getLength() > 0;
++#else // HAVE_SOVRMLVIEWPOINT
++  return FALSE;
++#endif // ! HAVE_SOVRMLVIEWPOINT
++}
++
++void
++SoGuiViewpointWrapper::setSceneGraph(SoNode * root)
++{
++#ifdef HAVE_SOVRMLVIEWPOINT
++  this->truncateLists();
++  this->setViewpoint(NULL);
++  if (this->scenegraph) this->scenegraph->unref();
++  this->scenegraph = root;
++  if (this->scenegraph) {
++    this->scenegraph->ref();
++    this->sa.setInterest(SoSearchAction::ALL);
++    this->sa.setType(SoVRMLViewpoint::getClassTypeId());
++    this->sa.apply(root);
++    SoPathList & pl = this->sa.getPaths();
++    if (pl.getLength()) {
++      for (int i = 0; i < pl.getLength(); i++) {
++        SoFullPath * p = (SoFullPath*) pl[i];
++        if (p->getTail()->isOfType(SoVRMLViewpoint::getClassTypeId())) {
++          this->nodelist.append(p->getTail());
++          this->set_bind_sensorlist.append(new SoFieldSensor(set_bind_cb, this));
++        }
++      }
++      this->attachSetBindSensors();
++      // bind the first Viewpoint
++      SoSFBool * set_bind = (SoSFBool*) this->nodelist[0]->getField(SbName("set_bind"));
++      assert(set_bind);
++      set_bind->setValue(TRUE);
++    }
++    this->sa.reset();
++  }
++#endif // HAVE_SOVRMLVIEWPOINT
++}
++
++void 
++SoGuiViewpointWrapper::truncateLists(void)
++{
++  this->detachSetBindSensors();
++  this->nodelist.truncate(0);
++  for (int i = 0; i < this->set_bind_sensorlist.getLength(); i++) {
++    SoFieldSensor * fs = (SoFieldSensor*) this->set_bind_sensorlist[i];
++    delete fs;
++  }
++}
++
++void 
++SoGuiViewpointWrapper::attachSetBindSensors(void)
++{
++#ifdef HAVE_SOVRMLVIEWPOINT
++  assert(this->nodelist.getLength() == this->set_bind_sensorlist.getLength());
++  for (int i = 0; i < this->nodelist.getLength(); i++) {
++    SoVRMLViewpoint * vp = (SoVRMLViewpoint*) this->nodelist[i];
++    SoFieldSensor * fs = (SoFieldSensor*) this->set_bind_sensorlist[i];
++    fs->attach(vp->getField(SbName("set_bind")));
++  }
++#endif // HAVE_SOVRMLVIEWPOINT
++}
++
++void 
++SoGuiViewpointWrapper::detachSetBindSensors(void)
++{
++#ifdef HAVE_SOVRMLVIEWPOINT
++  for (int i = 0; i < this->set_bind_sensorlist.getLength(); i++) {
++    SoFieldSensor * fs = (SoFieldSensor*) this->set_bind_sensorlist[i];
++    fs->detach();
++  }
++#endif // HAVE_SOVRMLVIEWPOINT
++}
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/ViewpointWrapper.h.in
+@@ -0,0 +1,103 @@
++#ifndef COIN_SOGUIVIEWPOINTWRAPPER_H
++#define COIN_SOGUIVIEWPOINTWRAPPER_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/nodes/SoPerspectiveCamera.h>
++#include <Inventor/nodes/SoSubNode.h>
++#include <Inventor/actions/SoSearchAction.h>
++#include <Inventor/SoLists.h>
++
++class SoPath;
++class SoFullPath;
++class SoPathSensor;
++class SoSensor;
++class SoFieldSensor;
++class SoGetMatrixAction;
++
++class SoGuiViewpointWrapper : public SoPerspectiveCamera {
++  typedef SoPerspectiveCamera inherited;
++  SO_NODE_HEADER(SoGuiViewpointWrapper);
++public:
++  static void initClass(void);
++  SoGuiViewpointWrapper(void);
++  
++  void setSceneGraph(SoNode * root);
++  
++  static SbBool hasViewpoints(SoNode * root);
++
++protected:
++  ~SoGuiViewpointWrapper();
++  
++private:
++  void setViewpoint(SoPath * path);
++  
++  static void fieldsensor_cb(void * data, SoSensor * sensor);
++  static void pathsensor_cb(void * data, SoSensor * sensor);
++  static void set_bind_cb(void * data, SoSensor * sensor);
++
++  void updateCamera(void);
++  void updateViewpoint(void);
++  
++  void attachFieldSensors(void);
++  void detachFieldSensors(void);
++  
++  SoFullPath * pathtoviewpoint;
++  SoPathSensor * pathsensor;
++  SoFieldSensor * positionsensor;
++  SoFieldSensor * orientationsensor;
++  SoFieldSensor * heightanglesensor;
++  SoGetMatrixAction * gmaction;
++
++  void truncateLists(void);
++  
++  SoNodeList nodelist;
++  SbPList set_bind_sensorlist;
++  SoSearchAction sa;
++  SoNode * scenegraph;
++
++  void attachSetBindSensors(void);
++  void detachSetBindSensors(void);
++
++  void sendBindEvents(SoNode * node, const SbBool onoff);
++  void bindTopOfStack(void);
++
++};
++
++#endif //  COIN_SOGUIVIEWPOINTWRAPPER_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/ViewportFix.cpp.in
+@@ -0,0 +1,178 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <assert.h>
++
++#include <Inventor/SbViewportRegion.h>
++#include <Inventor/SbLinear.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/actions/SoGLRenderAction.h>
++#include <Inventor/actions/SoPickAction.h>
++#include <Inventor/actions/SoRayPickAction.h>
++#include <Inventor/actions/SoGetMatrixAction.h>
++#include <Inventor/elements/SoModelMatrixElement.h>
++
++#include <Inventor/@Gui@/nodes/SoGuiViewportFix.h>
++
++// *************************************************************************
++
++SO_NODE_SOURCE(SoGuiViewportFix);
++
++void
++SoGuiViewportFix::initClass(void)
++{
++  SO_NODE_INIT_CLASS(SoGuiViewportFix, SoTransformation, "Transformation");
++}
++
++SoGuiViewportFix::SoGuiViewportFix(void)
++{
++  this->internals = NULL;
++
++  SO_NODE_CONSTRUCTOR(SoGuiViewportFix);
++
++  SO_NODE_ADD_FIELD(corner, (SoGuiViewportFix::LEFT_BOTTOM));
++  SO_NODE_ADD_FIELD(viewportSize, (SbVec3f(0.0f, 0.0f, 0.0f)));
++
++  SO_NODE_DEFINE_ENUM_VALUE(Corner, LEFT_TOP);
++  SO_NODE_DEFINE_ENUM_VALUE(Corner, RIGHT_TOP);
++  SO_NODE_DEFINE_ENUM_VALUE(Corner, LEFT_BOTTOM);
++  SO_NODE_DEFINE_ENUM_VALUE(Corner, RIGHT_BOTTOM);
++
++  SO_NODE_SET_SF_ENUM_TYPE(corner, Corner);
++}
++
++SoGuiViewportFix::~SoGuiViewportFix(void)
++{
++}
++
++void
++SoGuiViewportFix::doAction(SoAction * action)
++{
++  SoState * state = action->getState();
++  if ( ! state->isElementEnabled(SoModelMatrixElement::getClassStackIndex()) ) return;
++
++  SbVec3f vpsize = this->viewportSize.getValue();
++  if ( vpsize[0] <= 0.0f || vpsize[1] <= 0.0f ) return;
++
++  SoModelMatrixElement::makeIdentity(state, this);
++
++  switch ( this->corner.getValue() ) {
++  case SoGuiViewportFix::LEFT_BOTTOM:
++    do {
++      SbVec3f translation(-1.0f, -1.0f, 0.0f);
++      SbVec3f scale(2.0f, 2.0f, 1.0f);
++      if ( vpsize[0] > vpsize[1] ) {
++	translation[0] = translation[0] * (vpsize[0] / vpsize[1]);
++	scale[0] = scale[0] * (vpsize[0] / vpsize[1]);
++      } else {
++	translation[1] = translation[1] * (vpsize[1] / vpsize[0]);
++	scale[1] = scale[1] * (vpsize[1] / vpsize[0]);
++      }
++      SoModelMatrixElement::translateBy(state, this, translation);
++      SoModelMatrixElement::scaleBy(state, this, scale);
++      // FIXME: scale
++    } while ( FALSE );
++    break;
++  default:
++    do {
++      SoDebugError::postInfo("SoGuiViewportFix::GLRender", "unimplemented corner");
++    } while ( FALSE );
++    break;
++  }
++}
++
++void
++SoGuiViewportFix::GLRender(SoGLRenderAction * action)
++{
++  const SbViewportRegion & vp = action->getViewportRegion();
++  SbVec2s vpsize = vp.getViewportSizePixels();
++
++  SbVec3f viewport(vpsize[0], vpsize[1], 0.0f);
++  if ( viewport != this->viewportSize.getValue() )
++    this->viewportSize.setValue(vpsize[0], vpsize[1], 0.0f);
++
++  this->doAction(action);
++}
++
++void
++SoGuiViewportFix::pick(SoPickAction * action)
++{
++  this->doAction(action);
++}
++
++void
++SoGuiViewportFix::rayPick(SoRayPickAction * action)
++{
++  this->doAction(action);
++}
++
++void
++SoGuiViewportFix::getMatrix(SoGetMatrixAction * action)
++{
++  SoDebugError::postInfo("SoGuiViewportFix::getMatrix", "not implemented yet");
++
++  SbVec3f vpsize = this->viewportSize.getValue();
++  if ( vpsize[0] <= 0.0f || vpsize[1] <= 0.0f ) return;
++
++  action->getMatrix() = SbMatrix::identity();
++
++  switch ( this->corner.getValue() ) {
++  case SoGuiViewportFix::LEFT_BOTTOM:
++    do {
++      SbVec3f translation(-1.0f, -1.0f, 0.0f);
++      SbVec3f scale(2.0f, 2.0f, 1.0f);
++      if ( vpsize[0] > vpsize[1] ) {
++	translation[0] = translation[0] * (vpsize[0] / vpsize[1]);
++	scale[0] = scale[0] * (vpsize[0] / vpsize[1]);
++      } else {
++	translation[1] = translation[1] * (vpsize[1] / vpsize[0]);
++	scale[1] = scale[1] * (vpsize[1] / vpsize[0]);
++      }
++      SbMatrix matrix = SbMatrix::identity();
++      matrix.setTranslate(translation);
++      action->getMatrix().multLeft(matrix);
++
++      matrix = SbMatrix::identity();
++      matrix.setScale(scale);
++      action->getMatrix().multLeft(matrix);
++    } while ( FALSE );
++    break;
++  default:
++    do {
++      SoDebugError::postInfo("SoGuiViewportFix::GLRender", "unimplemented corner");
++    } while ( FALSE );
++    break;
++  }
++}
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/ViewportFix.h.in
+@@ -0,0 +1,82 @@
++#ifndef COIN_SOGUIVIEWPORTFIX_H
++#define COIN_SOGUIVIEWPORTFIX_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/fields/SoSFEnum.h>
++#include <Inventor/fields/SoSFVec3f.h>
++#include <Inventor/nodes/SoTransformation.h>
++
++// might go abstract to separate between ortho and perspective views
++
++class SoGuiViewportFix : public SoTransformation {
++  typedef SoTransformation inherited;
++  SO_NODE_HEADER(SoGuiViewportFix);
++
++public:
++  static void initClass(void);
++
++  SoGuiViewportFix(void);
++
++  enum Corner {
++    LEFT_TOP,
++    RIGHT_TOP,
++    LEFT_BOTTOM,
++    RIGHT_BOTTOM
++  };
++
++  SoSFEnum corner;
++
++  SoSFVec3f viewportSize; // output field: updated internally
++
++  virtual void doAction(SoAction * action);
++  virtual void GLRender(SoGLRenderAction * action);
++  virtual void pick(SoPickAction * action);
++  virtual void rayPick(SoRayPickAction * action);
++  virtual void getMatrix(SoGetMatrixAction * action);
++
++protected:
++  virtual ~SoGuiViewportFix(void);
++
++private:
++  void * internals;
++
++};
++
++#endif // !COIN_SOGUIVIEWPORTFIX_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/help.xpm
+@@ -0,0 +1,266 @@
++#ifndef COIN_PIXMAP_HELP_XPM
++#define COIN_PIXMAP_HELP_XPM
++
++/* XPM */
++static const char * help_xpm[] = {
++"24 24 234 2",
++"  	c None",
++". 	c #020204",
++"+ 	c #0282FC",
++"@ 	c #828A94",
++"# 	c #96CAFC",
++"$ 	c #26A6FC",
++"% 	c #7A828C",
++"& 	c #BAE6FC",
++"* 	c #0296FC",
++"= 	c #024284",
++"- 	c #0262C4",
++"; 	c #8AAED4",
++"> 	c #C6C6CC",
++", 	c #2682E4",
++"' 	c #4AB6FC",
++") 	c #DEEAF4",
++"! 	c #727A8C",
++"~ 	c #0272E4",
++"{ 	c #2696FC",
++"] 	c #AAB2C4",
++"^ 	c #CED6E4",
++"/ 	c #EAF6FC",
++"( 	c #028EFC",
++"_ 	c #3AA6FC",
++": 	c #0252A4",
++"< 	c #8E9AA4",
++"[ 	c #EEEAEC",
++"} 	c #227AD4",
++"| 	c #DEDADC",
++"1 	c #1E82E4",
++"2 	c #96BAE4",
++"3 	c #268EF4",
++"4 	c #027AF4",
++"5 	c #269EFC",
++"6 	c #AED6FC",
++"7 	c #1E96FC",
++"8 	c #026AD4",
++"9 	c #4ABAFC",
++"0 	c #BEBEC4",
++"a 	c #4296EC",
++"b 	c #3AB2FC",
++"c 	c #DEEEFC",
++"d 	c #969EAC",
++"e 	c #028AFC",
++"f 	c #024A94",
++"g 	c #9EAABC",
++"h 	c #C2CEDC",
++"i 	c #D6DEEC",
++"j 	c #FAF6F4",
++"k 	c #025AB4",
++"l 	c #7A96B4",
++"m 	c #BAC6D4",
++"n 	c #328EEC",
++"o 	c #0A7AEC",
++"p 	c #026ADC",
++"q 	c #5AA2EC",
++"r 	c #0A82FC",
++"s 	c #36AEFC",
++"t 	c #0E9EFC",
++"u 	c #3A96F4",
++"v 	c #B6B6BC",
++"w 	c #D6D6D4",
++"x 	c #1E8EFC",
++"y 	c #3AAEFC",
++"z 	c #E2E2E4",
++"A 	c #3A9EFC",
++"B 	c #62BAFC",
++"C 	c #429EF4",
++"D 	c #8A929C",
++"E 	c #2EAEFC",
++"F 	c #DAE6EC",
++"G 	c #0A96FC",
++"H 	c #92B6DC",
++"I 	c #368ADC",
++"J 	c #62AAF4",
++"K 	c #E6E6E4",
++"L 	c #1272DC",
++"M 	c #F2F2F4",
++"N 	c #1E8AF4",
++"O 	c #2692FC",
++"P 	c #16A2FC",
++"Q 	c #C2BEC4",
++"R 	c #9AA6B4",
++"S 	c #CECED4",
++"T 	c #0A7EF4",
++"U 	c #0A6EDC",
++"V 	c #A2C6EC",
++"W 	c #26AAFC",
++"X 	c #02468C",
++"Y 	c #0266CC",
++"Z 	c #268AEC",
++"` 	c #0276EC",
++" .	c #269AFC",
++"..	c #F2FAFC",
++"+.	c #0A8EFC",
++"@.	c #42A6FC",
++"#.	c #0256AC",
++"$.	c #86A6CC",
++"%.	c #DEDEDC",
++"&.	c #9EC2E4",
++"*.	c #26A2FC",
++"=.	c #BEDEFC",
++"-.	c #42B2FC",
++";.	c #E6EEFC",
++">.	c #024E9C",
++",.	c #FEFEFC",
++"'.	c #025EBC",
++").	c #026EDC",
++"!.	c #0A86FC",
++"~.	c #DADADC",
++"{.	c #5EC2FC",
++"].	c #0A9AFC",
++"^.	c #62B2FC",
++"/.	c #C2EAFC",
++"(.	c #92B2D4",
++"_.	c #CECACC",
++":.	c #AEBACC",
++"<.	c #EEFAFC",
++"[.	c #929EAC",
++"}.	c #EEEEEC",
++"|.	c #1E86EC",
++"1.	c #9ABEE4",
++"2.	c #B2DEFC",
++"3.	c #4A96E4",
++"4.	c #96A2AC",
++"5.	c #A6B2BC",
++"6.	c #F6FAFC",
++"7.	c #AACEFC",
++"8.	c #0E7AE4",
++"9.	c #0E82F4",
++"0.	c #023E84",
++"a.	c #A6CEF4",
++"b.	c #52BEFC",
++"c.	c #3A92EC",
++"d.	c #BEBABC",
++"e.	c #1E9EFC",
++"f.	c #D6D2D4",
++"g.	c #1E7EE4",
++"h.	c #BAC2D4",
++"i.	c #868E9C",
++"j.	c #7E8694",
++"k.	c #8E96A4",
++"l.	c #EAEAEC",
++"m.	c #A6CAF4",
++"n.	c #BEEAFC",
++"o.	c #8EB2D4",
++"p.	c #767E8C",
++"q.	c #B2DAFC",
++"r.	c #A2AEBC",
++"s.	c #C6D2DC",
++"t.	c #C2C2C4",
++"u.	c #D2D2D4",
++"v.	c #46B6FC",
++"w.	c #027EFC",
++"x.	c #429AF4",
++"y.	c #42A2FC",
++"z.	c #62AEFC",
++"A.	c #0A8AFC",
++"B.	c #42AEFC",
++"C.	c #66C2FC",
++"D.	c #0286FC",
++"E.	c #AAB6C4",
++"F.	c #CEDAE4",
++"G.	c #0292FC",
++"H.	c #3AAAFC",
++"I.	c #1E9AFC",
++"J.	c #D6E2EC",
++"K.	c #3A9AF4",
++"L.	c #1E92FC",
++"M.	c #3AA2FC",
++"N.	c #62BEFC",
++"O.	c #0A92FC",
++"P.	c #42AAFC",
++"Q.	c #E6F2FC",
++"R.	c #62B6FC",
++"S.	c #AAD2FC",
++"T.	c #1EA2FC",
++"U.	c #0672DC",
++"V.	c #929AAC",
++"W.	c #066ACC",
++"X.	c #DAD6DC",
++"Y.	c #EAE6EC",
++"Z.	c #2A92F4",
++"`.	c #0E7EEC",
++" +	c #2A8AEC",
++".+	c #E2DEE4",
++"++	c #066EDC",
++"@+	c #F2EEF4",
++"#+	c #9AA2B4",
++"$+	c #2AA6FC",
++"%+	c #CAC6CC",
++"&+	c #E2EAF4",
++"*+	c #2A96FC",
++"=+	c #EEF6FC",
++"-+	c #9ABAE4",
++";+	c #2A8EF4",
++">+	c #2A9EFC",
++",+	c #3EB2FC",
++"'+	c #E2EEFC",
++")+	c #BAB6BC",
++"!+	c #E6E2E4",
++"~+	c #0E96FC",
++"{+	c #96B6DC",
++"]+	c #F6F2F4",
++"^+	c #9EA6B4",
++"/+	c #2AAAFC",
++"(+	c #2A9AFC",
++"_+	c #2AA2FC",
++":+	c #0E9AFC",
++"<+	c #FAFAFC",
++"[+	c #C6C2C4",
++"}+	c #02428C",
++"|+	c #0262CC",
++"1+	c #0252AC",
++"2+	c #1E82EC",
++"3+	c #024A9C",
++"4+	c #025ABC",
++"5+	c #D6D6DC",
++"6+	c #429EFC",
++"7+	c #8A92A4",
++"8+	c #DAE6F4",
++"9+	c #1E8AFC",
++"0+	c #024694",
++"a+	c #0266D4",
++"b+	c #268AF4",
++"c+	c #0276F4",
++"d+	c #0256B4",
++"e+	c #DEDEE4",
++"f+	c #024EA4",
++"g+	c #025EC4",
++"h+	c #026EE4",
++"i+	c #0E7AEC",
++"j+	c #0E82FC",
++"k+	c #2A92FC",
++". . . . . . . . . . . . . . . . . . . . . . . . ",
++". W.} I 3.q J J z.z.^.^.R.R.B B N.N.C.# # =.c . ",
++". - h.h ^ i F ) '+Q.=+..6.6.6.6.6.6.6.6.6.6.=.. ",
++". '.:.U g.n c.u K.A A M._ _ H.y y b v.b.{.6.# . ",
++". k ] a+U.1 Z b+3 O { {  .5 *.*.$ $ E ,+9 6.# . ",
++". #.r.- 8 ~ i+`.9.j+q.c c /.~+~+:+t P W s 6.' . ",
++". 1+^+g+Y ).~ ` 4 7.,.,.,.,.n.G.G.* ].T./+6.-.. ",
++". 1+^+g+Y ).~ ` c+c ,.,.,.,.c ( G.G.].T.$+6.-.. ",
++". 1+R '.Y p ~ ~ ` m.<+,.,.,.& e ( G.G e.$+6.B.. ",
++". : R '.|+8 h+~ ` c+a.c c 2.D.e e ( O.I._+6.B.. ",
++". : #+'.- 8 ).~ ~ ` 4 4 w.+ + D.e e O.I.>+6.P.. ",
++". : 4.4+- a+).).1.c c c c c c q.D.D.+.7 >+.. at .. ",
++". : d 4+- Y 8 ).h+1.l.}.]+j c 6 + + A.L.(+<. at .. ",
++". f+[.k g+Y 8 p ).2 K l.}.M c S.w.w.!.x *+/ y.. ",
++". >.V.k '.|+a+8 p {+.+!+Y.[ @+m.4 w.r 9+k+;.6+. ",
++". >.< d+'.- Y a+8 H | .+!+K l.V c+4 T N Z.&+C . ",
++". >.k.#.4+- |+Y a+o.5+~.%.z !+&.` ` o |.;+8+x.. ",
++". 3+k.#.k g+- |+Y ; u.w X.| e+-+~ ~ o 2+ +J.a . ",
++". f i.: d+4+'.- - $.%+_.S u.f.(.p ).).8.1 F.c.. ",
++". X @ >.: #.d+l v )+d.0 Q t.[+> $.|+Y 8 ++s., . ",
++". }+% f >.f+1+1+#.#.d+d+k k 4+4+'.'.'.- Y m L . ",
++". = ! p.j.@ i.i.D 7+k.k.< V.V.[.d d #+g 5.E.Y . ",
++". 0.0.= }+X 0+0+0+f f 3+3+>.>.>.>.>.: 1+#.k '.. ",
++". . . . . . . . . . . . . . . . . . . . . . . . "};
++
++#endif /* !COIN_PIXMAP_HELP_XPM /
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/home.xpm
+@@ -0,0 +1,43 @@
++#ifndef COIN_PIXMAP_HOME_XPM
++#define COIN_PIXMAP_HOME_XPM
++
++/* XPM */
++static const char * home_xpm[] = {
++"24 24 11 1",
++" 	c None",
++".	c #000000",
++"+	c #808080",
++"@	c #898989",
++"#	c #C0C0C0",
++"$	c #F9F9F9",
++"%	c #424242",
++"&	c #A4A4A4",
++"*	c #5D5D5D",
++"=	c #C1C1C1",
++"-	c #DFDFDF",
++"                        ",
++"                        ",
++"                        ",
++"           ..           ",
++"           ..           ",
++"      .............     ",
++"     ..+............    ",
++"    ..+ at +............   ",
++"   ..+###+............  ",
++"  ..+#$$$#+............ ",
++" ...#$$$$$#+.......%%   ",
++"   .$+&$$$+++....%**%   ",
++"   .$&#$$$+#$.*%**%+%   ",
++"   .$##$$$=#$$**++++%   ",
++"   .$$$$$$--$$++++%+%   ",
++"   .$$$$$$$$$$+%++*+%   ",
++"   .$$$@@#-$$$+*++++%   ",
++"   .$$$@##-$$$+%+++%%   ",
++"   .$$$###-$$$+++%%     ",
++"   .%+####-$$$+%%       ",
++"     %%%%%%%..%         ",
++"                        ",
++"                        ",
++"                        "};
++
++#endif /* !COIN_PIXMAP_HOME_XPM */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/ortho.xpm
+@@ -0,0 +1,47 @@
++#ifndef COIN_PIXMAP_ORTHO_XPM
++#define COIN_PIXMAP_ORTHO_XPM
++
++/* XPM */
++static const char * ortho_xpm[] = {
++"24 24 15 1",
++" 	c None",
++".	c #000000",
++"+	c #F5680A",
++"@	c #D00000",
++"#	c #A80000",
++"$	c #806840",
++"%	c #D9D900",
++"&	c #FF0000",
++"*	c #808000",
++"=	c #FFFF00",
++"-	c #600000",
++";	c #800000",
++">	c #EAEA00",
++",	c #FCB803",
++"'	c #4F4F00",
++"                        ",
++"                        ",
++"                        ",
++"                        ",
++" ...................... ",
++" .+@@@@@@@@@####$$$$$$. ",
++" .%+&&&&&&&&&&&#$****$. ",
++" .%=+&&&&&&&&&&#$****$. ",
++" .%==+&&&&&&&&&#$****-. ",
++" .%===+&&&&&&&&@$****-. ",
++" .%====+&&&&&&&@$****-. ",
++" .%=====+&&&&&&@$***$-. ",
++" .%======+&&&&&@$***;-. ",
++" .%>======+&&&&@$***;-. ",
++" .%>=======+&&&#$**$;-. ",
++" .%>=======,+&&#$**;;-. ",
++" .%>>=======,+&#$*$;;-. ",
++" .%>>>=======,+#$*;;;-. ",
++" .%>>>>>>=====,#$$;;;-. ",
++" .%%%%%%%%%%%%%**'----. ",
++" ...................... ",
++"                        ",
++"                        ",
++"                        "};
++
++#endif /* !COIN_PIXMAP_ORTHO_XPM */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/perspective.xpm
+@@ -0,0 +1,49 @@
++#ifndef COIN_PIXMAP_PERSPECTIVE_XPM
++#define COIN_PIXMAP_PERSPECTIVE_XPM
++
++/* XPM */
++static const char * perspective_xpm[] = {
++"24 24 17 1",
++" 	c None",
++".	c #000000",
++"+	c #D20000",
++"@	c #ECEC00",
++"#	c #FC4203",
++"$	c #AC0000",
++"%	c #FFFF00",
++"&	c #FF0000",
++"*	c #C4C400",
++"=	c #FFB862",
++"-	c #840000",
++";	c #FFA940",
++">	c #666600",
++",	c #7D7D00",
++"'	c #804000",
++")	c #FE8263",
++"!	c #737300",
++"                        ",
++"          .             ",
++"         .+..           ",
++"        .@#+$..         ",
++"       .@%#&&+$..       ",
++"      .@%%#&&&&+$..     ",
++"     .@@%%#&&&&&&+$..   ",
++"    .*@%%=#&&&&&&&&&.   ",
++"   .*@%%%=#&&&&&&&&-.   ",
++"  .*@%%%%;&&&&&&&&>-.   ",
++" .@%%%%%%=&&&&&&&>,-.   ",
++" .*@%%%%%=&&&&&#>,'-.   ",
++"  .*@%%%%;&&&&#>,,'-.   ",
++"   .*@%%%;&&&&>,,,--.   ",
++"    .*@%%;&&&>,,,'--.   ",
++"     .*@%;&+>,,,,'--.   ",
++"      .*%;+',,,,'---.   ",
++"       .*)'!,,,,'--.    ",
++"        .'!,,,,,--.     ",
++"         ...,,,'-.      ",
++"            ..,-.       ",
++"              ..        ",
++"                        ",
++"                        "};
++
++#endif /* !COIN_PIXMAP_PERSPECTIVE_XPM */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/pick.xpm
+@@ -0,0 +1,45 @@
++#ifndef COIN_PIXMAP_PICK_XPM
++#define COIN_PIXMAP_PICK_XPM
++
++/* XPM */
++static const char * pick_xpm[] = {
++"24 24 13 1",
++" 	c None",
++".	c #000000",
++"+	c #646464",
++"@	c #EC0000",
++"#	c #FF7171",
++"$	c #800000",
++"%	c #BB0000",
++"&	c #FF4D4D",
++"*	c #FF8C8C",
++"=	c #FFA2A2",
++"-	c #FFBFBF",
++";	c #FFD0D0",
++">	c #D00000",
++"                        ",
++"                        ",
++"                        ",
++"  .+                    ",
++"  + at .+                  ",
++"   .@#.+                ",
++"   +$@##.+              ",
++"    .%@&##.+            ",
++"    +$@&&*##.+          ",
++"     .%@&&*=##.+        ",
++"     +$@&&&&=-##.+      ",
++"      .%@&&&&&-;#&+     ",
++"      +$@&&&&&&=#.      ",
++"       .%@&&&&*#.       ",
++"       +$@&&&&#.        ",
++"        .%@&@%@#.       ",
++"        +$%@%.$@#.      ",
++"         .%%. .$@#.     ",
++"         +$.   .$>#.    ",
++"          +     .$.     ",
++"                 .      ",
++"                        ",
++"                        ",
++"                        "};
++
++#endif /* !COIN_PIXMAP_PICK_XPM */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/seek.xpm
+@@ -0,0 +1,44 @@
++#ifndef COIN_PIXMAP_SEEK_XPM
++#define COIN_PIXMAP_SEEK_XPM
++
++/* XPM */
++static const char * seek_xpm[] = {
++"24 24 12 1",
++" 	c None",
++".	c #000000",
++"+	c #005FBD",
++"@	c #5EAEFF",
++"#	c #7DBEFF",
++"$	c #0080FF",
++"%	c #FFFFFF",
++"&	c #004080",
++"*	c #FFFF00",
++"=	c #A8A800",
++"-	c #6D6D36",
++";	c #FFFF80",
++"                        ",
++"                        ",
++"                ...     ",
++"               .+ at +.    ",
++"              .+#$$+.   ",
++"             .+%$$$+.   ",
++"            .+#$$$+&.   ",
++"           .+@#@$+&.    ",
++"          .+@%&$+&.     ",
++"    .....+@@+.$+&.      ",
++"   .$$$@@@&&$$+&.       ",
++"  .$@#%@@$$+&+&.        ",
++"  .&&+@#@$$$&&.         ",
++"  .**=&+@$$$$&.         ",
++"  -**;*&+@$$+.          ",
++"   -**%%++ at ++.          ",
++"    =%%%*&+ at +.          ",
++"     =%%**&+&.          ",
++"      =***=+&.          ",
++"       =-*=&.           ",
++"         -..            ",
++"                        ",
++"                        ",
++"                        "};
++
++#endif /* !COIN_PIXMAP_SEEK_XPM */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/set_home.xpm
+@@ -0,0 +1,41 @@
++#ifndef COIN_PIXMAP_SET_HOME_XPM
++#define COIN_PIXMAP_SET_HOME_XPM
++
++/* XPM */
++static const char * set_home_xpm[] = {
++"24 24 9 1",
++" 	c None",
++".	c #000000",
++"+	c #2894FF",
++"@	c #4FA7FF",
++"#	c #62B0FF",
++"$	c #0077EE",
++"%	c #BDDEFF",
++"&	c #97CBFF",
++"*	c #399CFF",
++"   .....................",
++"  .++.@@@@@@@@@@@@@@@@@.",
++" .+++.################@.",
++".++++.################@.",
++"......################@.",
++".$$$$$################@.",
++".$$$$@#####%%#########@.",
++".+@@@######%&#########@.",
++".*######%%%%&&%%######@.",
++".*#####%#%######%#####@.",
++".+####%###%######&####@.",
++".+*##&&####%######%###@.",
++".+*#%#######%######%##@.",
++".+*%%%######%%%&&%%%%#@.",
++".++*#%######%#####&###@.",
++".++*#&######%#####%###@.",
++".$++*%*#####%#####%###@.",
++".+++*%**####%#####%###@.",
++".$+$+%%%%%&&%%%&&%%###@.",
++".+$+++++*#############@.",
++".$+$+$+++**###########@.",
++".+$+$++++++***########@.",
++".$+$+$+$+++++++++++****.",
++"........................"};
++
++#endif /* !COIN_PIXMAP_SET_HOME_XPM */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/view.xpm
+@@ -0,0 +1,43 @@
++#ifndef COIN_PIXMAP_VIEW_XPM
++#define COIN_PIXMAP_VIEW_XPM
++
++/* XPM */
++static const char * view_xpm[] = {
++"24 24 11 1",
++" 	c None",
++".	c #000000",
++"+	c #A0A0A0",
++"@	c #C0C0C0",
++"#	c #464646",
++"$	c #E2E2E2",
++"%	c #5E5E5E",
++"&	c #FFFFFF",
++"*	c #808080",
++"=	c #939393",
++"-	c #9B9B9B",
++"                        ",
++"           ..           ",
++"          .+ at ...        ",
++"        ..#+$#+ at .       ",
++"       .+@%@&%+$#.      ",
++"       .+$%@&%@&%+.     ",
++"       .+&*@&*@&%+ at .    ",
++"       .+&*@&*@&*+$.    ",
++"       .@$=@$=@$*@$.    ",
++"       .@$-@$-@$=@$.    ",
++"       .@$+@$+@$-@$.    ",
++"       .@&@&@@&@+&$.    ",
++"   ..  .@&&&&&&&&&&.    ",
++"  .@$. .@&$&&$&&$&&.    ",
++"  .+&$..@&+$&+&$+&&.    ",
++"   .@&$*@$$+&+&+$&&.    ",
++"    .@&$@$&+&+&+&&&.    ",
++"     .@$$$$$&$&$&&&.    ",
++"      .@@$$$&&&&&$$.    ",
++"       *++@@@@@&&$@*    ",
++"        .*+++@@@@*.     ",
++"       .@$$$@.@$$$@.    ",
++"       .....# #.....    ",
++"                        "};
++
++#endif /* !COIN_PIXMAP_VIEW_XPM */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/view_all.xpm
+@@ -0,0 +1,58 @@
++#ifndef COIN_PIXMAP_VIEW_ALL_XPM
++#define COIN_PIXMAP_VIEW_ALL_XPM
++
++/* XPM */
++static const char * view_all_xpm[] = {
++"24 24 26 1",
++" 	c None",
++".	c #000000",
++"+	c #ACAC00",
++"@	c #D9D900",
++"#	c #FFFF73",
++"$	c #EAEA00",
++"%	c #6A6A35",
++"&	c #004080",
++"*	c #808080",
++"=	c #C0C0C0",
++"-	c #0067CE",
++";	c #4B4B4B",
++">	c #FFFFFF",
++",	c #B8B8B8",
++"'	c #CCCCCC",
++")	c #1188FF",
++"!	c #D9D9D9",
++"~	c #0077EE",
++"{	c #7DBEFF",
++"]	c #399CFF",
++"^	c #158AFF",
++"/	c #B5DAFF",
++"(	c #E7E7E7",
++"_	c #808040",
++":	c #95954A",
++"<	c #919100",
++"                        ",
++"    ................... ",
++"   .+.@@@@@@@@@@@@@@@@. ",
++"  .++.###############@. ",
++" .....###############@. ",
++" .++++#$@+++++@@#####@. ",
++" .++#$@%........%+###@. ",
++" .@$@%.&&&&.*......%+ at . ",
++" .+%.*&&&&.*=*..=.&&%+. ",
++" ..**&--&;*=>=*....&&.. ",
++" .*,,&---;.*=*.**..--&. ",
++" .,''&---;..*.**==.)--. ",
++" *'!!~---;....*=>>.{]^* ",
++" ,'!>~--~-.....=>>>/{], ",
++" ,'(>{&~)]-......>>>>!' ",
++" *'!(>&-)]]-;..;-{>>>(, ",
++" ._''!{&-)]]]]]]]]/>('* ",
++" .+_'''{&~-))]]])/(('_. ",
++" .++__'''{~~~---/(',_ at . ",
++" .++++:_,'''!!''':_:@@. ",
++" . at +++++<::____::@@##@. ",
++" .@@@++++++++++@@@@@@@. ",
++" ...................... ",
++"                        "};
++
++#endif /* !COIN_PIXMAP_VIEW_ALL_XPM */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/x.xpm
+@@ -0,0 +1,177 @@
++#ifndef COIN_PIXMAP_X_XPM
++#define COIN_PIXMAP_X_XPM
++
++/* XPM */
++static const char * x_xpm[] = {
++"24 24 145 2",
++"  	c None",
++". 	c #000000",
++"+ 	c #C50000",
++"@ 	c #ED0000",
++"# 	c #F53636",
++"$ 	c #F76969",
++"% 	c #F98B8B",
++"& 	c #FAA2A2",
++"* 	c #F54242",
++"= 	c #F76767",
++"- 	c #F98D8D",
++"; 	c #FBABAB",
++"> 	c #FCBDBD",
++", 	c #FCBEBE",
++"' 	c #9F0000",
++") 	c #CA0000",
++"! 	c #F30D0D",
++"~ 	c #F65454",
++"{ 	c #F98585",
++"] 	c #FBAFAF",
++"^ 	c #F42525",
++"/ 	c #F64949",
++"( 	c #F87575",
++"_ 	c #FA9F9F",
++": 	c #FBBABA",
++"< 	c #FBB1B1",
++"[ 	c #7B0000",
++"} 	c #9E0000",
++"| 	c #D20000",
++"1 	c #F42A2A",
++"2 	c #F87272",
++"3 	c #FA9A9A",
++"4 	c #FBACAC",
++"5 	c #F43131",
++"6 	c #F75A5A",
++"7 	c #F98A8A",
++"8 	c #FCBBBB",
++"9 	c #FA9696",
++"0 	c #9C0000",
++"a 	c #DB0000",
++"b 	c #F64545",
++"c 	c #F98888",
++"d 	c #FAA6A6",
++"e 	c #F53F3F",
++"f 	c #F64646",
++"g 	c #F87373",
++"h 	c #FAA0A0",
++"i 	c #F86D6D",
++"j 	c #9B0000",
++"k 	c #E40000",
++"l 	c #F65757",
++"m 	c #F99393",
++"n 	c #FAA3A3",
++"o 	c #FA9797",
++"p 	c #F75D5D",
++"q 	c #F64F4F",
++"r 	c #F64B4B",
++"s 	c #F76161",
++"t 	c #F98E8E",
++"u 	c #F86C6C",
++"v 	c #F65151",
++"w 	c #F54040",
++"x 	c #E90000",
++"y 	c #FA9494",
++"z 	c #F99191",
++"A 	c #F98787",
++"B 	c #F87676",
++"C 	c #F76363",
++"D 	c #F76666",
++"E 	c #F87C7C",
++"F 	c #F87979",
++"G 	c #F65252",
++"H 	c #F53333",
++"I 	c #F41F1F",
++"J 	c #F31515",
++"K 	c #F98181",
++"L 	c #F87F7F",
++"M 	c #F87B7B",
++"N 	c #F87E7E",
++"O 	c #F31C1C",
++"P 	c #F20404",
++"Q 	c #EB0000",
++"R 	c #AC0000",
++"S 	c #F53D3D",
++"T 	c #F86F6F",
++"U 	c #F87878",
++"V 	c #F76A6A",
++"W 	c #F42424",
++"X 	c #F20909",
++"Y 	c #840000",
++"Z 	c #BD0000",
++"` 	c #EE0000",
++" .	c #F87070",
++"..	c #F75B5B",
++"+.	c #F42727",
++"@.	c #F31313",
++"#.	c #F10000",
++"$.	c #F42D2D",
++"%.	c #F64C4C",
++"&.	c #F76060",
++"*.	c #F76464",
++"=.	c #8E0000",
++"-.	c #B20000",
++";.	c #D60000",
++">.	c #F20303",
++",.	c #F65555",
++"'.	c #8A0000",
++").	c #A50000",
++"!.	c #BE0000",
++"~.	c #8C0000",
++"{.	c #9D0000",
++"].	c #AB0000",
++"^.	c #B90000",
++"/.	c #CD0000",
++"(.	c #E60000",
++"_.	c #F64848",
++":.	c #8D0000",
++"<.	c #930000",
++"[.	c #960000",
++"}.	c #A70000",
++"|.	c #DF0000",
++"1.	c #7E0000",
++"2.	c #860000",
++"3.	c #7F0000",
++"4.	c #AD0000",
++"5.	c #DE0000",
++"6.	c #F53939",
++"7.	c #810000",
++"8.	c #880000",
++"9.	c #8B0000",
++"0.	c #830000",
++"a.	c #DD0000",
++"b.	c #F54343",
++"c.	c #F99090",
++"d.	c #D80000",
++"e.	c #890000",
++"f.	c #CF0000",
++"g.	c #F42121",
++"h.	c #C30000",
++"i.	c #F20101",
++"j.	c #F42B2B",
++"k.	c #B50000",
++"l.	c #F30A0A",
++"m.	c #800000",
++"n.	c #D00000",
++". . . . . . .                     . . . . . . . ",
++". + @ # $ % & .                 . * = - ; > , . ",
++". ' ) ! ~ { & ] .             . ^ / ( _ : , < . ",
++". [ } | 1 2 3 4 ] .         . ^ 5 6 7 < 8 4 9 . ",
++". [ [ 0 a b c d 4 d .     . e # f g h < h { i . ",
++". [ [ [ j k l m n & o . . p q r s - h t u v w . ",
++". [ [ [ [ 0 x p % y z A B $ C D E - F G H I J . ",
++"  . [ [ [ [ } @ v ( K L F g ( M N $ w O P Q .   ",
++"    . [ [ [ [ R @ S s T g U N E V f W X Q .     ",
++"      . [ [ [ Y Z ` H G D 2 U  ...w +. at ..       ",
++"        . [ [ [ } ) #.$.%.&.= *.l b # .         ",
++"          . [ [ =.-.;.>.1 b ,.p ..,..           ",
++"          . [ [ '.).!.;.` I e l C = .           ",
++"        . [ [ [ ~.{.].^./.(.O _.D ( E .         ",
++"      . [ [ [ Y :.<.[.j }.Z |.^ ..M c t .       ",
++"    . [ [ 1.2.:.:.2.3.[ 1.:.4.5.6.g - o 3 .     ",
++"  . [ [ [ 7.8.9.0.[ [ [ [ [ [ } a.b.M c.o 3 .   ",
++". [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ =.d.6.u L A c . ",
++". [ [ [ [ [ [ [ [ [ [ . . [ [ [ [ e.f.g.q *.u . ",
++". [ [ [ [ [ [ [ [ [ .     . [ [ [ [ Y h.i.j.* . ",
++". [ [ [ [ [ [ [ [ .         . [ [ [ [ 7.k.a.l.. ",
++". [ [ [ [ [ [ [ .             . [ [ [ [ m.R n.. ",
++". [ [ [ [ [ [ .                 . [ [ [ [ 7.}.. ",
++". . . . . . .                     . . . . . . . "};
++
++#endif /* !COIN_PIXMAP_X_XPM */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/y.xpm
+@@ -0,0 +1,167 @@
++#ifndef COIN_PIXMAP_Y_XPM
++#define COIN_PIXMAP_Y_XPM
++
++/* XPM */
++static const char * y_xpm[] = {
++"24 24 135 2",
++"  	c None",
++". 	c #000000",
++"+ 	c #FFFFFF",
++"@ 	c #006AD3",
++"# 	c #007DFA",
++"$ 	c #369BFF",
++"% 	c #69B4FF",
++"& 	c #8BC5FF",
++"* 	c #A2D1FF",
++"= 	c #42A1FF",
++"- 	c #67B3FF",
++"; 	c #8DC6FF",
++"> 	c #ABD5FF",
++", 	c #BDDEFF",
++"' 	c #BEDFFF",
++") 	c #0057AD",
++"! 	c #006CD8",
++"~ 	c #0D86FF",
++"{ 	c #54AAFF",
++"] 	c #85C2FF",
++"^ 	c #AFD7FF",
++"/ 	c #2592FF",
++"( 	c #49A4FF",
++"_ 	c #75BAFF",
++": 	c #9FCFFF",
++"< 	c #BADDFF",
++"[ 	c #B1D8FF",
++"} 	c #00458A",
++"| 	c #0056AB",
++"1 	c #0070DF",
++"2 	c #2A95FF",
++"3 	c #72B9FF",
++"4 	c #9ACDFF",
++"5 	c #ACD6FF",
++"6 	c #3198FF",
++"7 	c #5AADFF",
++"8 	c #8AC5FF",
++"9 	c #BBDDFF",
++"0 	c #96CBFF",
++"a 	c #0054A8",
++"b 	c #0074E8",
++"c 	c #43A1FF",
++"d 	c #87C3FF",
++"e 	c #A6D3FF",
++"f 	c #3F9FFF",
++"g 	c #46A3FF",
++"h 	c #73B9FF",
++"i 	c #A0D0FF",
++"j 	c #84C2FF",
++"k 	c #6CB6FF",
++"l 	c #0050A0",
++"m 	c #0075E9",
++"n 	c #4EA7FF",
++"o 	c #90C8FF",
++"p 	c #A3D1FF",
++"q 	c #99CCFF",
++"r 	c #5DAEFF",
++"s 	c #4FA7FF",
++"t 	c #4BA5FF",
++"u 	c #61B0FF",
++"v 	c #97CBFF",
++"w 	c #82C1FF",
++"x 	c #3A9DFF",
++"y 	c #004890",
++"z 	c #006FDE",
++"A 	c #81C0FF",
++"B 	c #76BBFF",
++"C 	c #6AB5FF",
++"D 	c #64B2FF",
++"E 	c #52A9FF",
++"F 	c #2D96FF",
++"G 	c #158AFF",
++"H 	c #0783FF",
++"I 	c #0482FF",
++"J 	c #0066CC",
++"K 	c #2291FF",
++"L 	c #7BBDFF",
++"M 	c #2492FF",
++"N 	c #007DF9",
++"O 	c #0071E2",
++"P 	c #0070E0",
++"Q 	c #005EBC",
++"R 	c #168BFF",
++"S 	c #0078EF",
++"T 	c #006EDB",
++"U 	c #0068D0",
++"V 	c #0059B2",
++"W 	c #0077ED",
++"X 	c #2793FF",
++"Y 	c #4CA6FF",
++"Z 	c #58ACFF",
++"` 	c #48A4FF",
++" .	c #1F8FFF",
++"..	c #007BF6",
++"+.	c #0071E1",
++"@.	c #0069D1",
++"#.	c #0064C8",
++"$.	c #005BB6",
++"%.	c #1E8FFF",
++"&.	c #3098FF",
++"*.	c #2190FF",
++"=.	c #007FFE",
++"-.	c #0076EB",
++";.	c #006DDA",
++">.	c #0067CE",
++",.	c #00468B",
++"'.	c #0064C7",
++").	c #007BF5",
++"!.	c #0F87FF",
++"~.	c #0058AF",
++"{.	c #0073E5",
++"].	c #007FFD",
++"^.	c #0180FF",
++"/.	c #0076EC",
++"(.	c #0055AA",
++"_.	c #0073E6",
++":.	c #0683FF",
++"<.	c #0C86FF",
++"[.	c #0057AE",
++"}.	c #0078F0",
++"|.	c #188CFF",
++"1.	c #1C8EFF",
++"2.	c #1389FF",
++"3.	c #005AB3",
++"4.	c #2B95FF",
++"5.	c #0052A4",
++"6.	c #198CFF",
++"7.	c #0065C9",
++"8.	c #007AF3",
++"9.	c #0A85FF",
++"0.	c #0381FF",
++"a.	c #0079F2",
++"b.	c #0056AC",
++"c.	c #0065CA",
++"d.	c #0058B0",
++". . . . . . .                     . . . . . . . ",
++". @ # $ % & * .                 . = - ; > , ' . ",
++". ) ! ~ { ] * ^ .             . / ( _ : < ' [ . ",
++". } | 1 2 3 4 5 ^ .         . / 6 7 8 [ 9 5 0 . ",
++". } } a b c d e 5 e .     . f $ g h i ^ : j k . ",
++". } } } l m n o p * q . . r s t u 8 v w u ( x . ",
++". } } } } y z g A o o ] B C D D h h E F G H I . ",
++"  . } } } } } J K r _ L B _ _ k E M N m O P .   ",
++"    . } } } } } Q N x r C 3 k t R S T U J .     ",
++"      . } } } } } V W X Y Z `  ...+. at .#..       ",
++"        . } } } } } $.W %.&.*.=.-.;.>..         ",
++"          . } } } } ,.'.).!.H ..b T .           ",
++"            . } } } } ~.{.].^.../..             ",
++"              . } } } (._.:.<.^..               ",
++"              . } } } [.}.|.1.2..               ",
++"              . } } } 3.N X 4.M .               ",
++"              . } } } 5./.6./ M .               ",
++"              . } } } } 7.8.9.G .               ",
++"              . } } } } a ! 8.0..               ",
++"              . } } } } ,.Q z a..               ",
++"              . } } } } } l '.+..               ",
++"              . } } } } } } b.c..               ",
++"              . } } } } } } y d..               ",
++"              . . . . . . . . . .               "};
++
++#endif /* !COIN_PIXMAP_Y_XPM */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/z.xpm
+@@ -0,0 +1,163 @@
++#ifndef COIN_PIXMAP_Z_XPM
++#define COIN_PIXMAP_Z_XPM
++
++/* XPM */
++static const char * z_xpm[] = {
++"24 24 131 2",
++"  	c None",
++". 	c #020204",
++"+ 	c #82820C",
++"@ 	c #C2C214",
++"# 	c #E2E21C",
++"$ 	c #EEEE94",
++"% 	c #F2F25C",
++"& 	c #E2E25C",
++"* 	c #EAEA1C",
++"= 	c #D2D214",
++"- 	c #A2A214",
++"; 	c #FEFEFC",
++"> 	c #DADA14",
++", 	c #FAFA9C",
++"' 	c #EAEA5C",
++") 	c #E2E23C",
++"! 	c #DADA34",
++"~ 	c #EAEA3C",
++"{ 	c #929214",
++"] 	c #B2B214",
++"^ 	c #6E6E0C",
++"/ 	c #F2F27C",
++"( 	c #F6F694",
++"_ 	c #E6E674",
++": 	c #FAFAB4",
++"< 	c #EAEA7C",
++"[ 	c #EAEA4C",
++"} 	c #7A7A0C",
++"| 	c #DADA24",
++"1 	c #E2E22C",
++"2 	c #EAE65C",
++"3 	c #E2E254",
++"4 	c #8A8A0C",
++"5 	c #CACA14",
++"6 	c #F2F2AC",
++"7 	c #E6E65C",
++"8 	c #E2DE3C",
++"9 	c #BABA14",
++"0 	c #FEFEBC",
++"a 	c #F2EE54",
++"b 	c #F2F26C",
++"c 	c #D6D614",
++"d 	c #AAAA14",
++"e 	c #EAEA74",
++"f 	c #DEDE34",
++"g 	c #9A9A14",
++"h 	c #76760C",
++"i 	c #FAFA8C",
++"j 	c #EEEE4C",
++"k 	c #E2E26C",
++"l 	c #DEDE1C",
++"m 	c #F2EE5C",
++"n 	c #EAE644",
++"o 	c #FAF68C",
++"p 	c #FAFAC4",
++"q 	c #EEEE8C",
++"r 	c #827E0C",
++"s 	c #E2DE2C",
++"t 	c #E6E62C",
++"u 	c #928E14",
++"v 	c #C6C614",
++"w 	c #E6E61C",
++"x 	c #F2EEA4",
++"y 	c #F6F664",
++"z 	c #E6E25C",
++"A 	c #EAEA34",
++"B 	c #D2D224",
++"C 	c #DEDA14",
++"D 	c #FAFAAC",
++"E 	c #EEEE5C",
++"F 	c #E6E63C",
++"G 	c #DADA44",
++"H 	c #F2EE3C",
++"I 	c #969614",
++"J 	c #BAB614",
++"K 	c #76720C",
++"L 	c #F6F67C",
++"M 	c #F6F6BC",
++"N 	c #FEFABC",
++"O 	c #EAEA8C",
++"P 	c #EEEA4C",
++"Q 	c #7E7E0C",
++"R 	c #DEDE2C",
++"S 	c #E6E64C",
++"T 	c #8E8E14",
++"U 	c #CECE14",
++"V 	c #F6F2B4",
++"W 	c #C2BE14",
++"X 	c #AEAE14",
++"Y 	c #86860C",
++"Z 	c #C6C214",
++"` 	c #EEEE9C",
++" .	c #F2F264",
++"..	c #E2E264",
++"+.	c #D2D21C",
++"@.	c #A6A614",
++"#.	c #FAFAA4",
++"$.	c #DADA3C",
++"%.	c #EAEA44",
++"&.	c #969214",
++"*.	c #B6B614",
++"=.	c #72720C",
++"-.	c #F6F69C",
++";.	c #E6E67C",
++">.	c #FAFABC",
++",.	c #EAEA84",
++"'.	c #7E7A0C",
++").	c #DADA2C",
++"!.	c #E6E234",
++"~.	c #8A8A14",
++"{.	c #CECA14",
++"].	c #F2F2B4",
++"^.	c #E6E66C",
++"/.	c #BEBE14",
++"(.	c #FEFEC4",
++"_.	c #F2F274",
++":.	c #D6D61C",
++"<.	c #AEAA14",
++"[.	c #DEDE44",
++"}.	c #9E9E14",
++"|.	c #7A760C",
++"1.	c #EEEE54",
++"2.	c #E6E634",
++"3.	c #E6E624",
++"4.	c #EEEE34",
++"5.	c #DEDA1C",
++"6.	c #EEEE64",
++"7.	c #E6E644",
++"8.	c #F6F68C",
++"9.	c #EEEA54",
++"0.	c #E6E654",
++". . . . . . . . . . . . . . . . . . . . . . . . ",
++". T }.] v c R 7.S [ [ [ 9.1.a %  .L o #.: 0 ; . ",
++". } Y I d W c s ) F 7.%.[ j 1.% b 8., : >.(.(.. ",
++". } } '.T - 9 U l # 1 2.~ [ 1.m _.( D >.p >.N . ",
++". } } } Q r I <./.v c l t ~ P 6./ -.D : : D #.. ",
++". } } } '.Q Q Y g @.J 5 > 3.%.E / ( -.-.( o i . ",
++". . . . . . . . . . . . v > t %.E b b b  .y y . ",
++"                    . g ] v C 3.A A A 4.4.H .   ",
++"                  . + I X @ = C # # w w * .     ",
++"                . Q 4 - 9 U l # # w w w .       ",
++"              . Q Y g ] {.l 1 !.2.t t .         ",
++"            . } + { d Z 5.) 7.7.7.n .           ",
++"          . } + T - 9 :.8 0.7 2 ' .             ",
++"        . Q + T }.] U f z ^.e e .               ",
++"      . Q Y T }.X v ).3 _ < q .                 ",
++"    . Q + ~.I @./.+.[.k < $ .                   ",
++"  . =.h } Y I d @ B G ..;..                     ",
++". =.=.K h } ~.- *.v +.$.. . . . . . . . . . . . ",
++". =.=.=.K h } u - <.9 v :.$.& _ O x ].V M M ; . ",
++". =.=.=.=.K h Q T I }.d *.v :.! 3 _ q ` 6 6 V . ",
++". =.=.=.=.=.K h Q + 4 { g @.] 9 U ! 3 ^.,.q $ . ",
++". ^ =.=.=.=.=.h h h h '.+ 4 { g @.9 {.| [.z ^.. ",
++". ^ ^ =.=.=.=.=.h h h h h |.} } Y &. at .*.v :.f . ",
++". . . . . . . . . . . . . . . . . . . . . . . . "};
++
++#endif /* !COIN_PIXMAP_Z_XPM */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/sogui-config.1.in
+@@ -0,0 +1,37 @@
++.\" Process this file with
++.\" groff -man -Tascii so at gui@-config.1
++.\"
++.TH so at gui@-config 1 "AUGUST 2001" "Library Configuration" "User Manuals"
++.SH NAME
++so at gui@-config \- Display So at Gui@ Library Configuration
++.SH SYNOPSIS
++.B so at gui@-config 
++.I OPTION 
++.B [
++.I OPTION
++.B ... ]
++.SH DESCRIPTION
++.B so at gui@-config
++is a script that is used to display what compiler flags and libraries were
++used when So at Gui@ was built.
++.SH OPTIONS
++.IP --version
++Return So at Gui@ version string
++.IP --help
++Display so at gui@-config usage information
++.IP --cppflags
++Return C pre-processor flags for use when compiling with So at Gui@
++.IP --cxxflags
++Return C++ compiler flags for use when compiling with So at Gui@
++.IP --ldflags
++Return linker flags needed when linking against So at Gui@
++.IP --libs
++Return libraries one must link with when using So at Gui@
++.IP --alternate=<config-name>
++Set So at Gui@ configuration to something other than default (when using
++multiple So at Gui@ configurations).
++.SH AUTHORS
++Steve Robbins <smr at debian.org>, and
++.br
++Lars J. Aas <larsa at coin3d.org>
++.
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/sogui-config.in
+@@ -0,0 +1,377 @@
++#! /bin/sh
++# **************************************************************************
++# so at gui@-config -- a utility for retrieving configuration information about
++# the installed So at Gui@ library.
++#
++# Authors:
++#   Lars J. Aas <larsa at coin3d.org>
++#   Morten Eriksen <mortene at coin3d.org>
++
++program="$0"
++me=`echo "$0" | sed 's,^.*[/\\],,g'`
++wd=`echo "$0" | sed 's,/[^/]*$,,'`
++prefix=`cd "$wd"/..; pwd` 
++
++hello=`echo hello | fmt -t -w70 2>&1`
++if test x"$hello" = x"hello"; then
++  # 'fmt -t' works
++  preformat="fmt -t -w76"
++  sedformat='$ q; s/$/ \\/'
++else
++  # sed script replacing "fmt -w76 | sed '2,$ s/^/  /g; $ q; 1,$ s/$/ \\/'"
++  preformat="cat"
++  sedformat='/^............................................................................./ {
++  G
++  s/^\([^\
++]\{1,76\}\) \(.*\)\(\
++\)/\1 \\\3  \2/
++  P
++  D
++}'
++  if test xhello != x"`echo hello | sed -e $sedformat 2>&1`"; then
++    sedformat="s/a/a/"
++  fi
++fi
++
++
++usage="\
++Usage: $me [OPTIONS]
++Options:
++  --alternate=<string>
++  --prefix
++  --cppflags
++  --cflags
++  --cxxflags
++  --ldflags
++  --libs
++  --msvcrt
++  --datadir
++  --includedir
++  --frameworkdir
++  --ac-subst <string> | <sourcefile.in>
++  --ac-desubst <sourcefile>
++  --compile <sourcefile> [<sourcefile>]...
++  --link <program> <object> [<object>]...
++  --build <program> <sourcefile> [<sourcefile>]...
++  --setup | --setup-front
++  --header <classname>
++  --version
++  --usage | --help"
++
++alternate=default
++for arg
++do
++  case $arg in
++  --usage | --help)
++    echo "$usage"
++    exit 0
++    ;;
++  --alternate=*)
++    alternate=`echo $arg | cut -d= -f2-`
++    ;;
++  --debug)
++    alternate=debug
++    ;;
++  esac
++done
++
++if test -f "$prefix/share/Coin/conf/so at gui@-$alternate.cfg"; then
++  configfile="$prefix/share/Coin/conf/so at gui@-$alternate.cfg"
++  . "$configfile"
++elif test -f "$prefix/share/Coin/conf/so at gui@-default.cfg"; then
++  configfile="$prefix/share/Coin/conf/so at gui@-default.cfg"
++  . "$configfile"
++else
++  echo >&2 "$me: no default So at Gui@ config available in \"$prefix/share/Coin/conf/\""
++  exit 1
++fi
++
++# Remove gcc system directories includes from the include path
++if test x"$compiler_is_gcc" = x"yes"; then
++  sim_ac_save_cpp=$CPP
++  CPP="cpp"
++  case `uname -s` in
++    Darwin) CPP="cpp3"
++    ;;
++  esac
++  cpp_sys_dirs=`$CPP -v <<EOF 2>&1 | sed -n -e \
++  '/#include <...> search starts here:/,/End of search list./{
++    /#include <...> search starts here:/b
++    /End of search list./b
++    s/ /-I/
++    p
++  }'
++EOF`
++  result=
++  for inc_path in $cppflags; do
++    additem=true
++    for sys_dir in $cpp_sys_dirs; do
++      if test x$inc_path = x$sys_dir; then
++        additem=false
++        break
++      fi
++    done
++    $additem && result="$result $inc_path"
++  done
++  cppflags=$result
++  CPP=$sim_ac_save_cpp
++fi
++
++while test $# -gt 0
++do
++  case $1 in
++  --version)         echo "$version"       ;;
++  --prefix)          echo "$prefix"        ;;
++  --cppflags)        echo "$cppflags"      ;;
++  --cflags)          echo "$cflags"        ;;
++  --cxxflags)        echo "$cxxflags"      ;;
++  --ldflags)         echo "$ldflags"       ;;
++  --libs)            echo "$libs"          ;;
++  --msvcrt)          echo "$msvcrt"        ;;
++  --datadir)         echo "$datadir"       ;;
++  --includedir)      echo "$includedir"    ;;
++  --frameworkdir)    echo "$frameworkdir"  ;;
++  --ac-subst)
++    shift
++    if test $# -eq 1; then
++      case $1 in
++      *\.in)
++        echo $me --ac-subst $1
++        outfile=`echo $1 | sed -e 's/\.in$//'`
++        sedscript=/tmp/ac_subst_$$.sed
++        grep "^AC_SUBST_" $configfile \
++          | sed -e 's/^AC_SUBST_\([^=]*\)="\([^"]*\)"$/s\/@\1@\/\2\/g;/g' \
++          >$sedscript
++        rm -f $outfile
++        case `echo "$compiler" | sed 's/ .*//g'` in
++        gcc | g++)
++          echo "# 1 \"$1\"" >$outfile
++          ;;
++        wrapmsvc | wrapmsvc.exe | msvccc)
++          echo "#line 1 \"$1\"" >$outfile
++          ;;
++        esac
++        sed -f $sedscript <$1 >>$outfile
++        rm -f $sedscript
++        ;;
++      *)
++        eval "VAL=\${AC_SUBST_$1}"
++        echo "$VAL"
++        ;;
++      esac
++    else
++      for arg in $@; do
++        $program --alternate="$alternate" --ac-subst $arg
++        retval=$?
++        test $retval -ne 0 && exit $retval
++      done
++    fi
++    exit 0
++    ;;
++  --ac-desubst)
++    shift
++    echo $me --ac-desubst $1
++    outfile="$1.in"
++    sedscript=/tmp/ac_subst_$$.sed
++    grep "^AC_SUBST_" $configfile \
++      | sed -e 's/^AC_SUBST_\([^=]*\)="\([^"]*\)"$/s\/\2\/@\1@\/g;/g' \
++      >$sedscript
++    sed -f $sedscript <$1 >$outfile
++    rm -f $sedscript
++    ;;
++  --compile)
++    shift
++    if test $# -eq 1; then
++      case $1 in
++      *\.in)
++        outfile=`echo $1 | sed -e 's/\.in$//'`
++        $program --alternate="$alternate" --ac-subst $1
++        $program --alternate="$alternate" --compile $outfile
++        retval=$?
++        test $retval -ne 0 && exit $retval
++        ;;
++      *)
++        basename=`echo "$1" | sed -e 's/\.[^\.]*$//'`  # strip off extension
++        echo $compiler $CPPFLAGS $cppflags $CXXFLAGS $cxxflags -c $1 -o $basename. at OBJEXT@ \
++          | $preformat | sed "$sedformat"
++        $compiler \
++          $CPPFLAGS $cppflags \
++          $CXXFLAGS $cxxflags \
++          -c $1 -o $basename. at OBJEXT@
++        retval=$?
++        test $retval -ne 0 && exit $retval
++        ;;
++      esac
++    else
++      for arg in $@; do
++        $program --alternate="$alternate" --compile $arg
++        retval=$?
++        test $retval -ne 0 && exit $retval
++      done
++    fi
++    exit 0
++    ;;
++  --link)
++    shift
++    progname=$1
++    shift
++    echo $compiler $LDFLAGS $ldflags -o $progname $@ $libs $LIBS \
++      | $preformat | sed "$sedformat"
++    $compiler \
++      $LDFLAGS $ldflags \
++      -o $progname $@ \
++      $libs $LIBS
++    retval=$?
++    test $retval -ne 0 && exit $retval
++    case $host in
++    *-darwin*)
++      echo "$me: making Mac OS X application \"$progname.app\""
++      mkdir $progname.app 2>/dev/null
++      mkdir $progname.app/Contents 2>/dev/null
++      mkdir $progname.app/Contents/MacOS 2>/dev/null
++      if test -d $progname.app/Contents/MacOS &&
++        mv -f $progname $progname.app/Contents/MacOS/ &&
++        echo "APPL????" >$progname.app/Contents/PkgInfo; then
++        :
++      else
++        echo >&2 "$me: failed to make Mac OS X application"
++        echo >&2 " - problem is probably user permission or disk space related"
++        exit 1
++      fi
++      ;;
++    esac
++    exit 0
++    ;;
++  --build)
++    shift
++    progname=$1
++    objs=
++    extraldflags=
++    extralibs=
++    shift
++    for arg in $@; do
++      case $arg in
++      *.h.in)
++        $program --alternate="$alternate" --ac-subst $arg
++        ;;
++      *.c.in | *.cpp.in | *.cxx.in | *.cc.in)
++        outfile=`echo "$arg" | sed -e 's/\.in$//'`
++        basename=`echo "$outfile" | sed -e 's/\.[^\.]*$//'`  # strip off extension
++        $program --alternate="$alternate" --ac-subst $arg
++        $program --alternate="$alternate" --compile $outfile
++        retval=$?
++        test $retval -ne 0 && exit $retval
++        objs="$objs $basename. at OBJEXT@"
++        ;;
++      *.c | *.cpp | *.cxx | *.cc)
++        basename=`echo "$arg" | sed -e 's/\.[^\.]*$//'`  # strip off extension
++        $program --alternate="$alternate" --compile $arg
++        retval=$?
++        test $retval -ne 0 && exit $retval
++        objs="$objs $basename. at OBJEXT@"
++        ;;
++      -L*)
++        extraldflags="$extraldflags $arg"
++        ;;
++      -l*)
++        extralibs="$extralibs $arg"
++        ;;
++      esac
++    done
++    if test -z "$objs"; then
++      echo >&2 "$usage"
++      echo >&2 ""
++      echo >&2 "$me: no object files"
++      exit 1
++    fi
++    echo $compiler $CPPFLAGS $cppflags $CXXFLAGS $cxxflags \
++      $LDFLAGS $ldflags $extraldflags \
++      -o $progname $objs $extralibs $libs $LIBS \
++      | $preformat | sed "$sedformat"
++    $compiler \
++      $CPPFLAGS $cppflags \
++      $CXXFLAGS $cxxflags \
++      $LDFLAGS $ldflags $extraldflags \
++      -o $progname $objs \
++      $extralibs $libs $LIBS
++    retval=$?
++    test $retval -ne 0 && exit $retval
++    exit 0
++    ;;
++  --build-app)
++    case $host in
++    *-darwin*)
++      shift
++      progname=$1
++      shift
++      if test $@; then
++        $program --alternate="$alternate" --build $progname $@ || exit $?
++      fi
++      echo "$me: making Mac OS X application \"$progname.app\""
++      mkdir $progname.app 2>/dev/null
++      mkdir $progname.app/Contents 2>/dev/null
++      mkdir $progname.app/Contents/MacOS 2>/dev/null
++      if test -d $progname.app/Contents/MacOS &&
++        mv -f $progname $progname.app/Contents/MacOS/ &&
++        echo "APPL????" >$progname.app/Contents/PkgInfo &&
++        cat > $progname.app/Contents/Info.plist <<EOF ; then
++<?xml version="1.0" encoding="UTF-8"?>
++<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1
++.0.dtd">
++<plist version="1.0">
++<dict>
++        <key>CFBundleExecutable</key>
++        <string>$progname</string>
++        <key>CFBundlePackageType</key>
++        <string>APPL</string>
++</dict>
++</plist>
++EOF
++        :
++      else
++        echo >&2 "$me: failed to make Mac OS X application"
++        echo >&2 " - problem is probably user permission or disk space related"
++        exit 1
++      fi
++      ;;
++    esac
++    exit 0
++    ;;
++  --setup)
++    # FIXME: scan variables and only modify variables that need modification
++    echo "PATH=\$PATH:$prefix/bin"
++    echo "LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:$prefix/lib"
++    echo "export PATH LD_LIBRARY_PATH"
++    exit 0
++    ;;
++  --setup-front)
++    # FIXME: scan variables and only modify variables that need modification
++    echo "PATH=$prefix/bin:\$PATH"
++    echo "LD_LIBRARY_PATH=$prefix/lib:\$LD_LIBRARY_PATH"
++    echo "export PATH LD_LIBRARY_PATH"
++    exit 0
++    ;;
++  --header)
++    shift
++    classname=$1
++    for header in `find ${prefix}/include/Inventor/@Gui@ -type f | xargs grep -n "^class SO at GUI@_DLL_API ${classname}\>" | cut -d: -f1`; do
++      echo "FILE: ${header}"
++      cat "${header}"
++    done
++    exit 0
++    ;;
++  # ignore some options
++  --alternate=*) ;;
++  --debug) ;;
++  # args not catched until now are invalid
++  *)
++    echo >&2 "$me: Invalid option: \"$1\""
++    echo >&2 "$usage"
++    exit 1
++    ;;
++  esac
++  shift
++done
++
++exit 0
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/sogui.cfg.in
+@@ -0,0 +1,23 @@
++# prefix is determined in so at gui@-config, making the package "movable"
++# prefix="@prefix@"
++host="@host@"
++exec_prefix="@exec_prefix@"
++version="@VERSION@"
++cppflags="@SOGUI_EXTRA_CPPFLAGS@"
++cflags="@SOGUI_EXTRA_CFLAGS@"
++cxxflags="@SOGUI_EXTRA_CXXFLAGS@"
++ldflags="@SOGUI_EXTRA_LDFLAGS@"
++libs="@SOGUI_EXTRA_LIBS@"
++msvcrt="@SOGUI_MSVC_LIBC@"
++datadir="@datarootdir@"
++includedir="@soguiincludedir@"
++frameworkdir="@frameworkdir@"
++compiler="@COIN_COMPILER@"
++AC_SUBST_GUI="@GUI@"
++AC_SUBST_Gui="@Gui@"
++AC_SUBST_gui="@gui@"
++AC_SUBST_WIDGET="@WIDGET@"
++AC_SUBST_EVENT="@EVENT@"
++AC_SUBST_COMPONENTHEADER="@COMPONENTHEADER@"
++compiler_is_gcc=@ac_compiler_gnu@
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/sogui.doxygen.in
+@@ -0,0 +1,1268 @@
++# Doxyfile 1.4.3
++
++# This file describes the settings to be used by the documentation system
++# doxygen (www.doxygen.org) for a project
++#
++# All text after a hash (#) is considered a comment and will be ignored
++# The format is:
++#       TAG = value [value, ...]
++# For lists items can also be appended using:
++#       TAG += value [value, ...]
++# Values that contain spaces should be placed between quotes (" ")
++
++#---------------------------------------------------------------------------
++# Project related configuration options
++#---------------------------------------------------------------------------
++
++# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
++# by quotes) that should identify the project.
++
++PROJECT_NAME           = @PACKAGE@
++
++# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
++# This could be handy for archiving the generated documentation or 
++# if some version control system is used.
++
++PROJECT_NUMBER         = @VERSION@
++
++# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
++# base path where the generated documentation will be put. 
++# If a relative path is entered, it will be relative to the location 
++# where doxygen was started. If left blank the current directory will be used.
++
++OUTPUT_DIRECTORY       = 
++
++# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
++# 4096 sub-directories (in 2 levels) under the output directory of each output 
++# format and will distribute the generated files over these directories. 
++# Enabling this option can be useful when feeding doxygen a huge amount of 
++# source files, where putting all generated files in the same directory would 
++# otherwise cause performance problems for the file system.
++
++CREATE_SUBDIRS         = NO
++
++# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
++# documentation generated by doxygen is written. Doxygen will use this 
++# information to generate all constant output in the proper language. 
++# The default language is English, other supported languages are: 
++# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, 
++# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, 
++# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, 
++# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, 
++# Swedish, and Ukrainian.
++
++OUTPUT_LANGUAGE        = English
++
++# This tag can be used to specify the encoding used in the generated output. 
++# The encoding is not always determined by the language that is chosen, 
++# but also whether or not the output is meant for Windows or non-Windows users. 
++# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES 
++# forces the Windows encoding (this is the default for the Windows binary), 
++# whereas setting the tag to NO uses a Unix-style encoding (the default for 
++# all platforms other than Windows).
++
++USE_WINDOWS_ENCODING   = NO
++
++# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
++# include brief member descriptions after the members that are listed in 
++# the file and class documentation (similar to JavaDoc). 
++# Set to NO to disable this.
++
++BRIEF_MEMBER_DESC      = YES
++
++# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
++# the brief description of a member or function before the detailed description. 
++# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
++# brief descriptions will be completely suppressed.
++
++REPEAT_BRIEF           = YES
++
++# This tag implements a quasi-intelligent brief description abbreviator 
++# that is used to form the text in various listings. Each string 
++# in this list, if found as the leading text of the brief description, will be 
++# stripped from the text and the result after processing the whole list, is 
++# used as the annotated text. Otherwise, the brief description is used as-is. 
++# If left blank, the following values are used ("$name" is automatically 
++# replaced with the name of the entity): "The $name class" "The $name widget" 
++# "The $name file" "is" "provides" "specifies" "contains" 
++# "represents" "a" "an" "the"
++
++ABBREVIATE_BRIEF       = 
++
++# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
++# Doxygen will generate a detailed section even if there is only a brief 
++# description.
++
++ALWAYS_DETAILED_SEC    = NO
++
++# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
++# inherited members of a class in the documentation of that class as if those 
++# members were ordinary class members. Constructors, destructors and assignment 
++# operators of the base classes will not be shown.
++
++INLINE_INHERITED_MEMB  = NO
++
++# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
++# path before files name in the file list and in the header files. If set 
++# to NO the shortest path that makes the file name unique will be used.
++
++FULL_PATH_NAMES        = NO
++
++# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
++# can be used to strip a user-defined part of the path. Stripping is 
++# only done if one of the specified strings matches the left-hand part of 
++# the path. The tag can be used to show relative paths in the file list. 
++# If left blank the directory from which doxygen is run is used as the 
++# path to strip.
++
++STRIP_FROM_PATH        = 
++
++# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
++# the path mentioned in the documentation of a class, which tells 
++# the reader which header file to include in order to use a class. 
++# If left blank only the name of the header file containing the class 
++# definition is used. Otherwise one should specify the include paths that 
++# are normally passed to the compiler using the -I flag.
++
++STRIP_FROM_INC_PATH    = 
++
++# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
++# (but less readable) file names. This can be useful is your file systems 
++# doesn't support long names like on DOS, Mac, or CD-ROM.
++
++SHORT_NAMES            = NO
++
++# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
++# will interpret the first line (until the first dot) of a JavaDoc-style 
++# comment as the brief description. If set to NO, the JavaDoc 
++# comments will behave just like the Qt-style comments (thus requiring an 
++# explicit @brief command for a brief description.
++
++JAVADOC_AUTOBRIEF      = YES
++
++# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
++# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
++# comments) as a brief description. This used to be the default behaviour. 
++# The new default is to treat a multi-line C++ comment block as a detailed 
++# description. Set this tag to YES if you prefer the old behaviour instead.
++
++MULTILINE_CPP_IS_BRIEF = NO
++
++# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
++# will output the detailed description near the top, like JavaDoc.
++# If set to NO, the detailed description appears after the member 
++# documentation.
++
++DETAILS_AT_TOP         = YES
++
++# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
++# member inherits the documentation from any documented member that it 
++# re-implements.
++
++INHERIT_DOCS           = YES
++
++# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
++# tag is set to YES, then doxygen will reuse the documentation of the first 
++# member in the group (if any) for the other members of the group. By default 
++# all members of a group must be documented explicitly.
++
++DISTRIBUTE_GROUP_DOC   = NO
++
++# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
++# a new page for each member. If set to NO, the documentation of a member will 
++# be part of the file/class/namespace that contains it.
++
++SEPARATE_MEMBER_PAGES  = NO
++
++# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
++# Doxygen uses this value to replace tabs by spaces in code fragments.
++
++TAB_SIZE               = 8
++
++# This tag can be used to specify a number of aliases that acts 
++# as commands in the documentation. An alias has the form "name=value". 
++# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
++# put the command \sideeffect (or @sideeffect) in the documentation, which 
++# will result in a user-defined paragraph with heading "Side Effects:". 
++# You can put \n's in the value part of an alias to insert newlines.
++
++ALIASES                = "COIN=<a href=http://www.coin3d.org><b>Coin</b></a>" \
++                         "QT=<a href=http://www.trolltech.com><b>Qt</b></a>"
++
++# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
++# sources only. Doxygen will then generate output that is more tailored for C. 
++# For instance, some of the names that are used will be different. The list 
++# of all members will be omitted, etc.
++
++OPTIMIZE_OUTPUT_FOR_C  = NO
++
++# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources 
++# only. Doxygen will then generate output that is more tailored for Java. 
++# For instance, namespaces will be presented as packages, qualified scopes 
++# will look different, etc.
++
++OPTIMIZE_OUTPUT_JAVA   = NO
++
++# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
++# the same type (for instance a group of public functions) to be put as a 
++# subgroup of that type (e.g. under the Public Functions section). Set it to 
++# NO to prevent subgrouping. Alternatively, this can be done per class using 
++# the \nosubgrouping command.
++
++SUBGROUPING            = YES
++
++#---------------------------------------------------------------------------
++# Build related configuration options
++#---------------------------------------------------------------------------
++
++# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
++# documentation are documented, even if no documentation was available. 
++# Private class members and static file members will be hidden unless 
++# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
++
++EXTRACT_ALL            = NO
++
++# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
++# will be included in the documentation.
++
++EXTRACT_PRIVATE        = NO
++
++# If the EXTRACT_STATIC tag is set to YES all static members of a file 
++# will be included in the documentation.
++
++EXTRACT_STATIC         = NO
++
++# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
++# defined locally in source files will be included in the documentation. 
++# If set to NO only classes defined in header files are included.
++
++EXTRACT_LOCAL_CLASSES  = NO
++
++# This flag is only useful for Objective-C code. When set to YES local 
++# methods, which are defined in the implementation section but not in 
++# the interface are included in the documentation. 
++# If set to NO (the default) only methods in the interface are included.
++
++EXTRACT_LOCAL_METHODS  = NO
++
++# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
++# undocumented members of documented classes, files or namespaces. 
++# If set to NO (the default) these members will be included in the 
++# various overviews, but no documentation section is generated. 
++# This option has no effect if EXTRACT_ALL is enabled.
++
++HIDE_UNDOC_MEMBERS     = NO
++
++# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
++# undocumented classes that are normally visible in the class hierarchy. 
++# If set to NO (the default) these classes will be included in the various 
++# overviews. This option has no effect if EXTRACT_ALL is enabled.
++
++HIDE_UNDOC_CLASSES     = YES
++
++# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
++# friend (class|struct|union) declarations. 
++# If set to NO (the default) these declarations will be included in the 
++# documentation.
++
++HIDE_FRIEND_COMPOUNDS  = NO
++
++# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
++# documentation blocks found inside the body of a function. 
++# If set to NO (the default) these blocks will be appended to the 
++# function's detailed documentation block.
++
++HIDE_IN_BODY_DOCS      = NO
++
++# The INTERNAL_DOCS tag determines if documentation 
++# that is typed after a \internal command is included. If the tag is set 
++# to NO (the default) then the documentation will be excluded. 
++# Set it to YES to include the internal documentation.
++
++INTERNAL_DOCS          = NO
++
++# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
++# file names in lower-case letters. If set to YES upper-case letters are also 
++# allowed. This is useful if you have classes or files whose names only differ 
++# in case and if your file system supports case sensitive file names. Windows 
++# and Mac users are advised to set this option to NO.
++
++CASE_SENSE_NAMES       = YES
++
++# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
++# will show members with their full class and namespace scopes in the 
++# documentation. If set to YES the scope will be hidden.
++
++HIDE_SCOPE_NAMES       = NO
++
++# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
++# will put a list of the files that are included by a file in the documentation 
++# of that file.
++
++SHOW_INCLUDE_FILES     = YES
++
++# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
++# is inserted in the documentation for inline members.
++
++INLINE_INFO            = YES
++
++# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
++# will sort the (detailed) documentation of file and class members 
++# alphabetically by member name. If set to NO the members will appear in 
++# declaration order.
++
++SORT_MEMBER_DOCS       = NO
++
++# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
++# brief documentation of file, namespace and class members alphabetically 
++# by member name. If set to NO (the default) the members will appear in 
++# declaration order.
++
++SORT_BRIEF_DOCS        = NO
++
++# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
++# sorted by fully-qualified names, including namespaces. If set to 
++# NO (the default), the class list will be sorted only by class name, 
++# not including the namespace part. 
++# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
++# Note: This option applies only to the class list, not to the 
++# alphabetical list.
++
++SORT_BY_SCOPE_NAME     = NO
++
++# The GENERATE_TODOLIST tag can be used to enable (YES) or 
++# disable (NO) the todo list. This list is created by putting \todo 
++# commands in the documentation.
++
++GENERATE_TODOLIST      = YES
++
++# The GENERATE_TESTLIST tag can be used to enable (YES) or 
++# disable (NO) the test list. This list is created by putting \test 
++# commands in the documentation.
++
++GENERATE_TESTLIST      = YES
++
++# The GENERATE_BUGLIST tag can be used to enable (YES) or 
++# disable (NO) the bug list. This list is created by putting \bug 
++# commands in the documentation.
++
++GENERATE_BUGLIST       = YES
++
++# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
++# disable (NO) the deprecated list. This list is created by putting 
++# \deprecated commands in the documentation.
++
++GENERATE_DEPRECATEDLIST= YES
++
++# The ENABLED_SECTIONS tag can be used to enable conditional 
++# documentation sections, marked by \if sectionname ... \endif.
++
++ENABLED_SECTIONS       = SO at GUI@_DOC
++
++# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
++# the initial value of a variable or define consists of for it to appear in 
++# the documentation. If the initializer consists of more lines than specified 
++# here it will be hidden. Use a value of 0 to hide initializers completely. 
++# The appearance of the initializer of individual variables and defines in the 
++# documentation can be controlled using \showinitializer or \hideinitializer 
++# command in the documentation regardless of this setting.
++
++MAX_INITIALIZER_LINES  = 30
++
++# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
++# at the bottom of the documentation of classes and structs. If set to YES the 
++# list will mention the files that were used to generate the documentation.
++
++SHOW_USED_FILES        = YES
++
++# If the sources in your project are distributed over multiple directories 
++# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
++# in the documentation.
++
++SHOW_DIRECTORIES       = YES
++
++# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
++# doxygen should invoke to get the current version for each file (typically from the 
++# version control system). Doxygen will invoke the program by executing (via 
++# popen()) the command <command> <input-file>, where <command> is the value of 
++# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
++# provided by doxygen. Whatever the progam writes to standard output 
++# is used as the file version. See the manual for examples.
++
++FILE_VERSION_FILTER    = 
++
++#---------------------------------------------------------------------------
++# configuration options related to warning and progress messages
++#---------------------------------------------------------------------------
++
++# The QUIET tag can be used to turn on/off the messages that are generated 
++# by doxygen. Possible values are YES and NO. If left blank NO is used.
++
++QUIET                  = YES
++
++# The WARNINGS tag can be used to turn on/off the warning messages that are 
++# generated by doxygen. Possible values are YES and NO. If left blank 
++# NO is used.
++
++WARNINGS               = YES
++
++# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
++# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
++# automatically be disabled.
++
++WARN_IF_UNDOCUMENTED   = YES
++
++# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
++# potential errors in the documentation, such as not documenting some 
++# parameters in a documented function, or documenting parameters that 
++# don't exist or using markup commands wrongly.
++
++WARN_IF_DOC_ERROR      = YES
++
++# This WARN_NO_PARAMDOC option can be abled to get warnings for 
++# functions that are documented, but have no documentation for their parameters 
++# or return value. If set to NO (the default) doxygen will only warn about 
++# wrong or incomplete parameter documentation, but not about the absence of 
++# documentation.
++
++WARN_NO_PARAMDOC       = NO
++
++# The WARN_FORMAT tag determines the format of the warning messages that 
++# doxygen can produce. The string should contain the $file, $line, and $text 
++# tags, which will be replaced by the file and line number from which the 
++# warning originated and the warning text. Optionally the format may contain 
++# $version, which will be replaced by the version of the file (if it could 
++# be obtained via FILE_VERSION_FILTER)
++
++WARN_FORMAT            = "$file:$line: $text"
++
++# The WARN_LOGFILE tag can be used to specify a file to which warning 
++# and error messages should be written. If left blank the output is written 
++# to stderr.
++
++WARN_LOGFILE           = 
++
++#---------------------------------------------------------------------------
++# configuration options related to the input files
++#---------------------------------------------------------------------------
++
++# The INPUT tag can be used to specify the files and/or directories that contain 
++# documented source files. You may enter file names like "myfile.cpp" or 
++# directories like "/usr/src/myproject". Separate the files or directories 
++# with spaces.
++
++INPUT                  = \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@.h \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@Basic.h \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@Common.cpp \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@Component.h \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@ComponentCommon.cpp \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@Cursor.cpp \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@Cursor.h \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@GLWidget.h \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@GLWidgetCommon.cpp \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@Object.cpp \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@Object.h \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@RenderArea.cpp \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@RenderArea.h \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/devices/So at Gui@Device.h \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/devices/So at Gui@DeviceCommon.cpp \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/devices/So at Gui@Keyboard.h \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/devices/So at Gui@KeyboardCommon.cpp \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/devices/So at Gui@Mouse.h \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/devices/So at Gui@MouseCommon.cpp \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.cpp \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.h \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.cpp \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.h \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@FlyViewer.cpp \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@FlyViewer.h \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@FullViewer.cpp \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@FullViewer.h \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@PlaneViewer.cpp \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@PlaneViewer.h \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@Viewer.cpp \
++                         @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@Viewer.h \
++                         @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/So at Gui@.cpp \
++                         @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/So at Gui@Component.cpp \
++                         @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/So at Gui@GLWidget.cpp \
++                         @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/devices/So at Gui@Device.cpp \
++                         @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/devices/So at Gui@Keyboard.cpp \
++                         @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/devices/So at Gui@Mouse.cpp \
++                         @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/viewers/ExaminerViewer.cpp \
++                         @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/viewers/FullViewer.cpp \
++                         @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/viewers/PlaneViewer.cpp
++
++# If the value of the INPUT tag contains directories, you can use the 
++# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
++# and *.h) to filter out the source-files in the directories. If left 
++# blank the following patterns are tested: 
++# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
++# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
++
++FILE_PATTERNS          = 
++
++# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
++# should be searched for input files as well. Possible values are YES and NO. 
++# If left blank NO is used.
++
++RECURSIVE              = NO
++
++# The EXCLUDE tag can be used to specify files and/or directories that should 
++# excluded from the INPUT source files. This way you can easily exclude a 
++# subdirectory from a directory tree whose root is specified with the INPUT tag.
++
++EXCLUDE                = 
++
++# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
++# directories that are symbolic links (a Unix filesystem feature) are excluded 
++# from the input.
++
++EXCLUDE_SYMLINKS       = NO
++
++# If the value of the INPUT tag contains directories, you can use the 
++# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
++# certain files from those directories.
++
++EXCLUDE_PATTERNS       = 
++
++# The EXAMPLE_PATH tag can be used to specify one or more files or 
++# directories that contain example code fragments that are included (see 
++# the \include command).
++
++EXAMPLE_PATH           = 
++
++# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
++# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
++# and *.h) to filter out the source-files in the directories. If left 
++# blank all files are included.
++
++EXAMPLE_PATTERNS       = 
++
++# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
++# searched for input files to be used with the \include or \dontinclude 
++# commands irrespective of the value of the RECURSIVE tag. 
++# Possible values are YES and NO. If left blank NO is used.
++
++EXAMPLE_RECURSIVE      = NO
++
++# The IMAGE_PATH tag can be used to specify one or more files or 
++# directories that contain image that are included in the documentation (see 
++# the \image command).
++
++IMAGE_PATH             = 
++
++# The INPUT_FILTER tag can be used to specify a program that doxygen should 
++# invoke to filter for each input file. Doxygen will invoke the filter program 
++# by executing (via popen()) the command <filter> <input-file>, where <filter> 
++# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
++# input file. Doxygen will then use the output that the filter program writes 
++# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
++# ignored.
++
++INPUT_FILTER           = 
++
++# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
++# basis.  Doxygen will compare the file name with each pattern and apply the 
++# filter if there is a match.  The filters are a list of the form: 
++# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
++# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
++# is applied to all files.
++
++FILTER_PATTERNS        = 
++
++# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
++# INPUT_FILTER) will be used to filter the input files when producing source 
++# files to browse (i.e. when SOURCE_BROWSER is set to YES).
++
++FILTER_SOURCE_FILES    = NO
++
++#---------------------------------------------------------------------------
++# configuration options related to source browsing
++#---------------------------------------------------------------------------
++
++# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
++# be generated. Documented entities will be cross-referenced with these sources. 
++# Note: To get rid of all source code in the generated output, make sure also 
++# VERBATIM_HEADERS is set to NO.
++
++SOURCE_BROWSER         = NO
++
++# Setting the INLINE_SOURCES tag to YES will include the body 
++# of functions and classes directly in the documentation.
++
++INLINE_SOURCES         = NO
++
++# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
++# doxygen to hide any special comment blocks from generated source code 
++# fragments. Normal C and C++ comments will always remain visible.
++
++STRIP_CODE_COMMENTS    = YES
++
++# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
++# then for each documented function all documented 
++# functions referencing it will be listed.
++
++REFERENCED_BY_RELATION = YES
++
++# If the REFERENCES_RELATION tag is set to YES (the default) 
++# then for each documented function all documented entities 
++# called/used by that function will be listed.
++
++REFERENCES_RELATION    = YES
++
++# If the USE_HTAGS tag is set to YES then the references to source code 
++# will point to the HTML generated by the htags(1) tool instead of doxygen 
++# built-in source browser. The htags tool is part of GNU's global source 
++# tagging system (see http://www.gnu.org/software/global/global.html). You 
++# will need version 4.8.6 or higher.
++
++USE_HTAGS              = NO
++
++# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
++# will generate a verbatim copy of the header file for each class for 
++# which an include is specified. Set to NO to disable this.
++
++VERBATIM_HEADERS       = YES
++
++#---------------------------------------------------------------------------
++# configuration options related to the alphabetical class index
++#---------------------------------------------------------------------------
++
++# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
++# of all compounds will be generated. Enable this if the project 
++# contains a lot of classes, structs, unions or interfaces.
++
++ALPHABETICAL_INDEX     = NO
++
++# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
++# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
++# in which this list will be split (can be a number in the range [1..20])
++
++COLS_IN_ALPHA_INDEX    = 5
++
++# In case all classes in a project start with a common prefix, all 
++# classes will be put under the same header in the alphabetical index. 
++# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
++# should be ignored while generating the index headers.
++
++IGNORE_PREFIX          = 
++
++#---------------------------------------------------------------------------
++# configuration options related to the HTML output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
++# generate HTML output.
++
++GENERATE_HTML          = @SOGUI_DOC_HTML@
++
++# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
++# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
++# put in front of it. If left blank `html' will be used as the default path.
++
++HTML_OUTPUT            = @sogui_html_dir@
++
++# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
++# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
++# doxygen will generate files with .html extension.
++
++HTML_FILE_EXTENSION    = .html
++
++# The HTML_HEADER tag can be used to specify a personal HTML header for 
++# each generated HTML page. If it is left blank doxygen will generate a 
++# standard header.
++
++HTML_HEADER            = @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/common/docs/doxygen/header.html
++
++# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
++# each generated HTML page. If it is left blank doxygen will generate a 
++# standard footer.
++
++HTML_FOOTER            = @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/common/docs/doxygen/footer.html
++
++# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
++# style sheet that is used by each HTML page. It can be used to 
++# fine-tune the look of the HTML output. If the tag is left blank doxygen 
++# will generate a default style sheet. Note that doxygen will try to copy 
++# the style sheet file to the HTML output directory, so don't put your own 
++# stylesheet in the HTML output directory as well, or it will be erased!
++
++HTML_STYLESHEET        = @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/common/docs/doxygen/stylesheet.css
++
++# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
++# files or namespaces will be aligned in HTML using tables. If set to 
++# NO a bullet list will be used.
++
++HTML_ALIGN_MEMBERS     = YES
++
++# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
++# will be generated that can be used as input for tools like the 
++# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
++# of the generated HTML documentation.
++
++GENERATE_HTMLHELP      = @SOGUI_DOC_HTML_HELP@
++
++# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
++# be used to specify the file name of the resulting .chm file. You 
++# can add a path in front of the file if the result should not be 
++# written to the html output directory.
++
++CHM_FILE               = @path_tag@@sogui_html_help_dir@/So at Gui@- at SOGUI_MAJOR_VERSION@.chm
++
++# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
++# be used to specify the location (absolute path including file name) of 
++# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
++# the HTML help compiler on the generated index.hhp.
++
++HHC_LOCATION           = @path_tag@@sim_ac_hhc_exe@
++
++# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
++# controls if a separate .chi index file is generated (YES) or that 
++# it should be included in the master .chm file (NO).
++
++GENERATE_CHI           = NO
++
++# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
++# controls whether a binary table of contents is generated (YES) or a 
++# normal table of contents (NO) in the .chm file.
++
++BINARY_TOC             = NO
++
++# The TOC_EXPAND flag can be set to YES to add extra items for group members 
++# to the contents of the HTML help documentation and to the tree view.
++
++TOC_EXPAND             = NO
++
++# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
++# top of each HTML page. The value NO (the default) enables the index and 
++# the value YES disables it.
++
++DISABLE_INDEX          = NO
++
++# This tag can be used to set the number of enum values (range [1..20]) 
++# that doxygen will group on one line in the generated HTML documentation.
++
++ENUM_VALUES_PER_LINE   = 4
++
++# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
++# generated containing a tree-like index structure (just like the one that 
++# is generated for HTML Help). For this to work a browser that supports 
++# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
++# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
++# probably better off using the HTML help feature.
++
++GENERATE_TREEVIEW      = NO
++
++# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
++# used to set the initial width (in pixels) of the frame in which the tree 
++# is shown.
++
++TREEVIEW_WIDTH         = 250
++
++#---------------------------------------------------------------------------
++# configuration options related to the LaTeX output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
++# generate Latex output.
++
++GENERATE_LATEX         = NO
++
++# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
++# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
++# put in front of it. If left blank `latex' will be used as the default path.
++
++LATEX_OUTPUT           = 
++
++# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
++# invoked. If left blank `latex' will be used as the default command name.
++
++LATEX_CMD_NAME         = latex
++
++# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
++# generate index for LaTeX. If left blank `makeindex' will be used as the 
++# default command name.
++
++MAKEINDEX_CMD_NAME     = makeindex
++
++# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
++# LaTeX documents. This may be useful for small projects and may help to 
++# save some trees in general.
++
++COMPACT_LATEX          = NO
++
++# The PAPER_TYPE tag can be used to set the paper type that is used 
++# by the printer. Possible values are: a4, a4wide, letter, legal and 
++# executive. If left blank a4wide will be used.
++
++PAPER_TYPE             = a4wide
++
++# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
++# packages that should be included in the LaTeX output.
++
++EXTRA_PACKAGES         = 
++
++# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
++# the generated latex document. The header should contain everything until 
++# the first chapter. If it is left blank doxygen will generate a 
++# standard header. Notice: only use this tag if you know what you are doing!
++
++LATEX_HEADER           = 
++
++# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
++# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
++# contain links (just like the HTML output) instead of page references 
++# This makes the output suitable for online browsing using a pdf viewer.
++
++PDF_HYPERLINKS         = NO
++
++# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
++# plain latex in the generated Makefile. Set this option to YES to get a 
++# higher quality PDF documentation.
++
++USE_PDFLATEX           = NO
++
++# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
++# command to the generated LaTeX files. This will instruct LaTeX to keep 
++# running if errors occur, instead of asking the user for help. 
++# This option is also used when generating formulas in HTML.
++
++LATEX_BATCHMODE        = NO
++
++# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
++# include the index chapters (such as File Index, Compound Index, etc.) 
++# in the output.
++
++LATEX_HIDE_INDICES     = NO
++
++#---------------------------------------------------------------------------
++# configuration options related to the RTF output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
++# The RTF output is optimized for Word 97 and may not look very pretty with 
++# other RTF readers or editors.
++
++GENERATE_RTF           = NO
++
++# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
++# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
++# put in front of it. If left blank `rtf' will be used as the default path.
++
++RTF_OUTPUT             = rtf
++
++# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
++# RTF documents. This may be useful for small projects and may help to 
++# save some trees in general.
++
++COMPACT_RTF            = NO
++
++# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
++# will contain hyperlink fields. The RTF file will 
++# contain links (just like the HTML output) instead of page references. 
++# This makes the output suitable for online browsing using WORD or other 
++# programs which support those fields. 
++# Note: wordpad (write) and others do not support links.
++
++RTF_HYPERLINKS         = NO
++
++# Load stylesheet definitions from file. Syntax is similar to doxygen's 
++# config file, i.e. a series of assignments. You only have to provide 
++# replacements, missing definitions are set to their default value.
++
++RTF_STYLESHEET_FILE    = 
++
++# Set optional variables used in the generation of an rtf document. 
++# Syntax is similar to doxygen's config file.
++
++RTF_EXTENSIONS_FILE    = 
++
++#---------------------------------------------------------------------------
++# configuration options related to the man page output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
++# generate man pages
++
++GENERATE_MAN           = @SOGUI_DOC_MAN@
++
++# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
++# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
++# put in front of it. If left blank `man' will be used as the default path.
++
++MAN_OUTPUT             = @sogui_man_dir@
++
++# The MAN_EXTENSION tag determines the extension that is added to 
++# the generated man pages (default is the subroutine's section .3)
++
++MAN_EXTENSION          = .3
++
++# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
++# then it will generate one additional man file for each entity 
++# documented in the real man page(s). These additional files 
++# only source the real man page, but without them the man command 
++# would be unable to find the correct page. The default is NO.
++
++MAN_LINKS              = NO
++
++#---------------------------------------------------------------------------
++# configuration options related to the XML output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_XML tag is set to YES Doxygen will 
++# generate an XML file that captures the structure of 
++# the code including all documentation.
++
++GENERATE_XML           = NO
++
++# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
++# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
++# put in front of it. If left blank `xml' will be used as the default path.
++
++XML_OUTPUT             = xml
++
++# The XML_SCHEMA tag can be used to specify an XML schema, 
++# which can be used by a validating XML parser to check the 
++# syntax of the XML files.
++
++XML_SCHEMA             = 
++
++# The XML_DTD tag can be used to specify an XML DTD, 
++# which can be used by a validating XML parser to check the 
++# syntax of the XML files.
++
++XML_DTD                = 
++
++# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
++# dump the program listings (including syntax highlighting 
++# and cross-referencing information) to the XML output. Note that 
++# enabling this will significantly increase the size of the XML output.
++
++XML_PROGRAMLISTING     = YES
++
++#---------------------------------------------------------------------------
++# configuration options for the AutoGen Definitions output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
++# generate an AutoGen Definitions (see autogen.sf.net) file 
++# that captures the structure of the code including all 
++# documentation. Note that this feature is still experimental 
++# and incomplete at the moment.
++
++GENERATE_AUTOGEN_DEF   = NO
++
++#---------------------------------------------------------------------------
++# configuration options related to the Perl module output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
++# generate a Perl module file that captures the structure of 
++# the code including all documentation. Note that this 
++# feature is still experimental and incomplete at the 
++# moment.
++
++GENERATE_PERLMOD       = NO
++
++# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
++# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
++# to generate PDF and DVI output from the Perl module output.
++
++PERLMOD_LATEX          = NO
++
++# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
++# nicely formatted so it can be parsed by a human reader.  This is useful 
++# if you want to understand what is going on.  On the other hand, if this 
++# tag is set to NO the size of the Perl module output will be much smaller 
++# and Perl will parse it just the same.
++
++PERLMOD_PRETTY         = YES
++
++# The names of the make variables in the generated doxyrules.make file 
++# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
++# This is useful so different doxyrules.make files included by the same 
++# Makefile don't overwrite each other's variables.
++
++PERLMOD_MAKEVAR_PREFIX = 
++
++#---------------------------------------------------------------------------
++# Configuration options related to the preprocessor   
++#---------------------------------------------------------------------------
++
++# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
++# evaluate all C-preprocessor directives found in the sources and include 
++# files.
++
++ENABLE_PREPROCESSING   = YES
++
++# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
++# names in the source code. If set to NO (the default) only conditional 
++# compilation will be performed. Macro expansion can be done in a controlled 
++# way by setting EXPAND_ONLY_PREDEF to YES.
++
++MACRO_EXPANSION        = YES
++
++# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
++# then the macro expansion is limited to the macros specified with the 
++# PREDEFINED and EXPAND_AS_PREDEFINED tags.
++
++EXPAND_ONLY_PREDEF     = NO
++
++# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
++# in the INCLUDE_PATH (see below) will be search if a #include is found.
++
++SEARCH_INCLUDES        = YES
++
++# The INCLUDE_PATH tag can be used to specify one or more directories that 
++# contain include files that are not input files but should be processed by 
++# the preprocessor.
++
++INCLUDE_PATH           = 
++
++# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
++# patterns (like *.h and *.hpp) to filter out the header-files in the 
++# directories. If left blank, the patterns specified with FILE_PATTERNS will 
++# be used.
++
++INCLUDE_FILE_PATTERNS  = 
++
++# The PREDEFINED tag can be used to specify one or more macro names that 
++# are defined before the preprocessor is started (similar to the -D option of 
++# gcc). The argument of the tag is a list of macros of the form: name 
++# or name=definition (no spaces). If the definition and the = are 
++# omitted =1 is assumed. To prevent a macro definition from being 
++# undefined via #undef or recursively expanded use the := operator 
++# instead of the = operator.
++
++PREDEFINED             = DOXYGEN_SKIP_THIS \
++                         __COIN_SO at GUI@__
++
++# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
++# this tag can be used to specify a list of macro names that should be expanded. 
++# The macro definition that is found in the sources will be used. 
++# Use the PREDEFINED tag if you want to use a different macro definition.
++
++EXPAND_AS_DEFINED      = 
++
++# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
++# doxygen's preprocessor will remove all function-like macros that are alone 
++# on a line, have an all uppercase name, and do not end with a semicolon. Such 
++# function macros are typically used for boiler-plate code, and will confuse 
++# the parser if not removed.
++
++SKIP_FUNCTION_MACROS   = YES
++
++#---------------------------------------------------------------------------
++# Configuration::additions related to external references   
++#---------------------------------------------------------------------------
++
++# The TAGFILES option can be used to specify one or more tagfiles. 
++# Optionally an initial location of the external documentation 
++# can be added for each tagfile. The format of a tag file without 
++# this location is as follows: 
++#   TAGFILES = file1 file2 ... 
++# Adding location for the tag files is done as follows: 
++#   TAGFILES = file1=loc1 "file2 = loc2" ... 
++# where "loc1" and "loc2" can be relative or absolute paths or 
++# URLs. If a location is present for each tag, the installdox tool 
++# does not have to be run to correct the links.
++# Note that each tag file must have a unique name
++# (where the name does NOT include the path)
++# If a tag file is not located in the directory in which doxygen 
++# is run, you must also specify the path to the tagfile here.
++
++TAGFILES               = 
++
++# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
++# a tag file that is based on the input files it reads.
++
++GENERATE_TAGFILE       = 
++
++# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
++# in the class index. If set to NO only the inherited external classes 
++# will be listed.
++
++ALLEXTERNALS           = NO
++
++# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
++# in the modules index. If set to NO, only the current project's groups will 
++# be listed.
++
++EXTERNAL_GROUPS        = YES
++
++# The PERL_PATH should be the absolute path and name of the perl script 
++# interpreter (i.e. the result of `which perl').
++
++PERL_PATH              = @sim_ac_perl_exe@
++
++#---------------------------------------------------------------------------
++# Configuration options related to the dot tool   
++#---------------------------------------------------------------------------
++
++# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
++# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
++# or super classes. Setting the tag to NO turns the diagrams off. Note that 
++# this option is superseded by the HAVE_DOT option below. This is only a 
++# fallback. It is recommended to install and use dot, since it yields more 
++# powerful graphs.
++
++CLASS_DIAGRAMS         = YES
++
++# If set to YES, the inheritance and collaboration graphs will hide 
++# inheritance and usage relations if the target is undocumented 
++# or is not a class.
++
++HIDE_UNDOC_RELATIONS   = NO
++
++# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
++# available from the path. This tool is part of Graphviz, a graph visualization 
++# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
++# have no effect if this option is set to NO (the default)
++
++HAVE_DOT               = NO
++
++# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
++# will generate a graph for each documented class showing the direct and 
++# indirect inheritance relations. Setting this tag to YES will force the 
++# the CLASS_DIAGRAMS tag to NO.
++
++CLASS_GRAPH            = YES
++
++# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
++# will generate a graph for each documented class showing the direct and 
++# indirect implementation dependencies (inheritance, containment, and 
++# class references variables) of the class with other documented classes.
++
++COLLABORATION_GRAPH    = YES
++
++# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
++# will generate a graph for groups, showing the direct groups dependencies
++
++GROUP_GRAPHS           = YES
++
++# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
++# collaboration diagrams in a style similar to the OMG's Unified Modeling 
++# Language.
++
++UML_LOOK               = NO
++
++# If set to YES, the inheritance and collaboration graphs will show the 
++# relations between templates and their instances.
++
++TEMPLATE_RELATIONS     = YES
++
++# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
++# tags are set to YES then doxygen will generate a graph for each documented 
++# file showing the direct and indirect include dependencies of the file with 
++# other documented files.
++
++INCLUDE_GRAPH          = YES
++
++# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
++# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
++# documented header file showing the documented files that directly or 
++# indirectly include this file.
++
++INCLUDED_BY_GRAPH      = YES
++
++# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
++# generate a call dependency graph for every global function or class method. 
++# Note that enabling this option will significantly increase the time of a run. 
++# So in most cases it will be better to enable call graphs for selected 
++# functions only using the \callgraph command.
++
++CALL_GRAPH             = NO
++
++# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
++# will graphical hierarchy of all classes instead of a textual one.
++
++GRAPHICAL_HIERARCHY    = YES
++
++# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
++# then doxygen will show the dependencies a directory has on other directories 
++# in a graphical way. The dependency relations are determined by the #include
++# relations between the files in the directories.
++
++DIRECTORY_GRAPH        = YES
++
++# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
++# generated by dot. Possible values are png, jpg, or gif
++# If left blank png will be used.
++
++DOT_IMAGE_FORMAT       = png
++
++# The tag DOT_PATH can be used to specify the path where the dot tool can be 
++# found. If left blank, it is assumed the dot tool can be found in the path.
++
++DOT_PATH               = 
++
++# The DOTFILE_DIRS tag can be used to specify one or more directories that 
++# contain dot files that are included in the documentation (see the 
++# \dotfile command).
++
++DOTFILE_DIRS           = 
++
++# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
++# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
++# this value, doxygen will try to truncate the graph, so that it fits within 
++# the specified constraint. Beware that most browsers cannot cope with very 
++# large images.
++
++MAX_DOT_GRAPH_WIDTH    = 1024
++
++# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
++# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
++# this value, doxygen will try to truncate the graph, so that it fits within 
++# the specified constraint. Beware that most browsers cannot cope with very 
++# large images.
++
++MAX_DOT_GRAPH_HEIGHT   = 1024
++
++# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
++# graphs generated by dot. A depth value of 3 means that only nodes reachable 
++# from the root by following a path via at most 3 edges will be shown. Nodes 
++# that lay further from the root node will be omitted. Note that setting this 
++# option to 1 or 2 may greatly reduce the computation time needed for large 
++# code bases. Also note that a graph may be further truncated if the graph's 
++# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH 
++# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), 
++# the graph is not depth-constrained.
++
++MAX_DOT_GRAPH_DEPTH    = 0
++
++# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
++# background. This is disabled by default, which results in a white background. 
++# Warning: Depending on the platform used, enabling this option may lead to 
++# badly anti-aliased labels on the edges of a graph (i.e. they become hard to 
++# read).
++
++DOT_TRANSPARENT        = NO
++
++# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
++# files in one run (i.e. multiple -o and -T options on the command line). This 
++# makes dot run faster, but since only newer versions of dot (>1.8.10) 
++# support this, this feature is disabled by default.
++
++DOT_MULTI_TARGETS      = NO
++
++# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
++# generate a legend page explaining the meaning of the various boxes and 
++# arrows in the dot generated graphs.
++
++GENERATE_LEGEND        = YES
++
++# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
++# remove the intermediate dot files that are used to generate 
++# the various graphs.
++
++DOT_CLEANUP            = YES
++
++#---------------------------------------------------------------------------
++# Configuration::additions related to the search engine   
++#---------------------------------------------------------------------------
++
++# The SEARCHENGINE tag specifies whether or not a search engine should be 
++# used. If set to NO the values of all tags below this one will be ignored.
++
++SEARCHENGINE           = NO
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/soguidefs.h.in
+@@ -0,0 +1,165 @@
++#ifndef SO at GUI@_INTERNALDEFS_H
++#define SO at GUI@_INTERNALDEFS_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/* ********************************************************************** */
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif /* HAVE_CONFIG_H */
++
++/* ********************************************************************** */
++
++#ifdef __FILE__
++#define SO at GUI@_STUB_FILE __FILE__
++#else
++/* FIXME: avoid this case by redefining the compilation rules to define the
++   current filename in some variable.  [20010919 larsa] */
++#define SO at GUI@_STUB_FILE ((char *)0L)
++#endif
++
++#ifdef __LINE__
++#define SO at GUI@_STUB_LINE __LINE__
++#else
++#define SO at GUI@_STUB_LINE 0
++#endif
++
++#ifdef __cplusplus
++#ifdef HAVE_CPP_COMPILER_FUNCTION_NAME_VAR
++#define SO at GUI@_STUB_FUNC HAVE_CPP_COMPILER_FUNCTION_NAME_VAR
++#else
++#define SO at GUI@_STUB_FUNC ((const char *)0L)
++#endif
++#else /* !__cplusplus */
++#ifdef HAVE_C_COMPILER_FUNCTION_NAME_VAR
++#define SO at GUI@_STUB_FUNC HAVE_C_COMPILER_FUNCTION_NAME_VAR
++#else
++#define SO at GUI@_STUB_FUNC ((const char *)0L)
++#endif
++#endif /* !__cplusplus */
++
++#if SO at GUI@_DEBUG
++
++#include <Inventor/errors/SoDebugError.h>
++
++/*
++  This stupid thing is here to silence some compilers that complain on
++  constant if-expressions.
++*/
++
++inline int so at gui@_not_null(const void * arg) { return (arg != NULL) ? 1 : 0; }
++
++
++/* Collects common code from SO at GUI@_STUB(), SO at GUI@_STUB()_ONCE and
++   SO at GUI@_OBSOLETED(). */
++
++#define SO at GUI@_FUNCTIONIDENTIFIER(SO at GUI@STR) \
++    SbString SO at GUI@STR(so at gui@_not_null(SO at GUI@_STUB_FILE) ? SO at GUI@_STUB_FILE : ""); \
++    if (SO at GUI@STR.getLength() > 0) { SO at GUI@STR += ':'; } \
++    SO at GUI@STR += SbString((int)SO at GUI@_STUB_LINE); SO at GUI@STR += ':'; \
++    SO at GUI@STR += so at gui@_not_null(SO at GUI@_STUB_FUNC) ? SO at GUI@_STUB_FUNC : ""
++
++/*
++  SO at GUI@_STUB(): a macro that prints out stub information.
++  Used where there is functionality missing.
++*/
++
++#define SO at GUI@_STUB() \
++  do { \
++    SO at GUI@_FUNCTIONIDENTIFIER(s); \
++    SoDebugError::postWarning(s.getString(), \
++                              "STUB: functionality not yet completed"); \
++  } while (0)
++
++/*
++  SO at GUI@_STUB_ONCE(): a macro that prints out stub information, but only on
++  the first pass.  Used where there is functionality missing that may be
++  called hundreds of times.
++*/
++
++#define SO at GUI@_STUB_ONCE() \
++  do { \
++    static int first = 1; \
++    if (first) { \
++      SO at GUI@_FUNCTIONIDENTIFIER(s); \
++      SoDebugError::postWarning(s.getString(), \
++                                "STUB: functionality not yet completed " \
++                                "(first and last warning)"); \
++      first = 0; \
++    } \
++  } while (0)
++
++/*
++  SO at GUI@_OBSOLETED(): a macro that prints out information about an obsoleted
++  function still being in use.
++*/
++
++#define SO at GUI@_OBSOLETED() \
++  do { \
++    SO at GUI@_FUNCTIONIDENTIFIER(s); \
++    SoDebugError::post(s.getString(), \
++                       "OBSOLETED: functionality no longer supported"); \
++  } while (0)
++
++#else /* !SO at GUI@_DEBUG */
++
++/* snub the stubs */
++#define SO at GUI@_STUB()      do { } while (0)
++#define SO at GUI@_STUB_ONCE() do { } while (0)
++#define SO at GUI@_OBSOLETED() do { } while (0)
++
++#endif /* !SO at GUI@_DEBUG */
++
++/*
++  GETTEXT support
++*/
++
++#if defined(ENABLE_NLS) && defined(HAVE_GETTEXT)
++#include <libintl.h>
++#define _(String) dgettext (PACKAGE, String)
++#define N_(String) (String)
++#else
++#define _(String) (String)
++#define N_(String) (String)
++#endif /* HAVE_GETTEXT && ENABLE_NLS */
++
++/* ********************************************************************** */
++
++#endif /* ! SO at GUI@_INTERNALDEFS_H */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/spwinput.h.in
+@@ -0,0 +1,53 @@
++#ifndef COIN_SPWINPUT_H
++#define COIN_SPWINPUT_H
++
++/* @configure_input@ */
++
++/*----------------------------------------------------------------------
++ * (C) 1999 Spacetec IMC Corporation ("Spacetec").
++ *
++ * Permission to use, copy, modify, and distribute this software for all
++ * purposes and without fees is hereby granted provided that this copyright
++ * notice appears in all copies. Permission to modify this software is granted
++ * and Spacetec will support such modifications only if said modifications are
++ * approved by Spacetec.
++ *
++ */
++
++#define SPW_INPUT_MAJOR    7
++#define SPW_INPUT_MINOR    6
++#define SPW_INPUT_UPDATE   0
++#define SPW_INPUT_BUILD    1
++#define SPW_INPUT_VERSION  "7.6.0.1"
++#define SPW_INPUT_DATE     _T("January 18, 1999")
++
++#define SPW_MAXBUF 80
++
++typedef enum {
++  SPW_InputMotionEvent=1, /* Event type is a motion event */
++  SPW_InputButtonPressEvent=2, /* Event type is a button press event */
++  SPW_InputButtonReleaseEvent=3 /* Event type is a button release event */
++} SPW_InputEventType;
++
++typedef struct {
++  unsigned int old; /* The last state of the buttons */
++  unsigned int current; /* The current state of the buttons */
++  unsigned int pressed; /* Which buttons were pressed */
++  unsigned int released; /* Which buttons were released */
++} SPW_InputButtonTable;
++
++typedef struct {
++  short int type; /* The type of event */
++  float fData[7]; /* The float Spaceball data */
++  short int sData[7]; /* The integer Spaceball data */
++  int buttonNumber; /* The button number for this event */
++  SPW_InputButtonTable buttonState; /* The state of the buttons */
++  char string[SPW_MAXBUF]; /* Extra data area */
++} SPW_InputEvent;
++
++/* These two methods should only be used under X */ 
++int SPW_CheckForSpaceballX11(void * display, int winid, char * product);
++int SPW_TranslateEventX11(void * display, void * xevent, SPW_InputEvent * sbEvent);
++/* FIXME: add two similar methods for WIN32. pederb, 20001114 */
++
++#endif /* COIN_SPWINPUT_H */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/spwinput_win32.c.in
+@@ -0,0 +1,1418 @@
++/* @configure_input@ */
++
++/*----------------------------------------------------------------------
++ * (C) 1998-2009 3Dconnexion. All rights reserved. 
++ * Permission to use, copy, modify, and distribute this software for all
++ * purposes and without fees is hereby grated provided that this copyright
++ * notice appears in all copies.  Permission to modify this software is granted
++ * and 3Dconnexion will support such modifications only is said modifications are
++ * approved by 3Dconnexion.
++ *
++ */
++/*
++ * The module contains interface routines to the Si library routines contained
++ * in the associated Dynamic Link Library.  The DLL is loaded explicitly when
++ * Si is initialized.  When the DLL is loaded, the initialization routine finds
++ * the addresses of the routines that it exposes to the world.  Once this is
++ * done the library routines are used as if they were part of the original
++ * source code. 
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif /* HAVE_CONFIG_H */
++
++#ifdef HAVE_WIN32_API /* Only compile this file when the Win32 API is available */
++
++#define SPW_DEFINE_COPYRIGHT
++#define SPW_DEFINE_GLOBALS
++
++#include <windows.h>
++#include <Inventor/@Gui@/devices/spwinput_win32.h>
++
++
++/* DLL library name */
++
++static LPCTSTR DllLibrary = "siappdll";
++
++
++/* names of DLL variables used in DLL */
++
++static LPCSTR strDLLRetVal          = "SpwErrorVal";
++
++/*typedef enum SpwRetVal SpwReturnValue;*/
++/* Names of functions contained in DLL; used to find their addresses at load
++   time */
++
++static LPCSTR fnSiBeep              = "SiBeep";
++static LPCSTR fnSiInitialize        = "SiInitialize";
++static LPCSTR fnSiTerminate         = "SiTerminate";
++static LPCSTR fnSiGetDeviceID       = "SiGetDeviceID";
++static LPCSTR fnSiGetNumDevices     = "SiGetNumDevices";
++static LPCSTR fnSiDeviceIndex       = "SiDeviceIndex";
++static LPCSTR fnSiDispatch          = "SiDispatch";
++static LPCSTR fnSiIsSpaceWareEvent  = "SiIsSpaceWareEvent";
++static LPCSTR fnSiOpenWinInit       = "SiOpenWinInit";
++static LPCSTR fnSiOpen              = "SiOpen";
++static LPCSTR fnSiClose             = "SiClose";
++static LPCSTR fnSiGetEventWinInit   = "SiGetEventWinInit";
++static LPCSTR fnSiGetEvent          = "SiGetEvent";
++static LPCSTR fnSiRezero            = "SiRezero";
++static LPCSTR fnSiGrabDevice        = "SiGrabDevice";
++static LPCSTR fnSiReleaseDevice     = "SiReleaseDevice";
++static LPCSTR fnSiButtonPressed     = "SiButtonPressed";
++static LPCSTR fnSiButtonReleased    = "SiButtonReleased";
++static LPCSTR fnSiSetUIMode         = "SiSetUiMode";
++static LPCSTR fnSiGetDevicePort     = "SiGetDevicePort";
++static LPCSTR fnSiGetDriverInfo     = "SiGetDriverInfo";
++static LPCSTR fnSiGetLibraryInfo    = "SiGetLibraryInfo";
++static LPCSTR fnSiGetDeviceInfo     = "SiGetDeviceInfo";
++static LPCSTR fnSpwErrorString      = "SpwErrorString";
++
++/* DLL initialization status */
++static enum InitResult gInitStatus = NOT_LOADED;
++
++/* DLL handle */
++HINSTANCE ghDll;
++enum SpwRetVal SpwErrorVal;
++
++/* Device handle */
++SiHdl Spw_DeviceHandle = SI_NO_HANDLE;
++
++/* Check to see if we can open a device handle to the spaceball */
++int SPW_SpaceBallExistsWin32(void)
++{
++  SiOpenData oData;
++  SiOpenWinInit(&oData,NULL);  
++  return (SiOpen("", SI_ANY_DEVICE, SI_NO_MASK, SI_EVENT, &oData) != SI_NO_HANDLE) ? TRUE : FALSE;
++}
++
++/* check if can open a handle to the spaceball, load the driver functions
++   and start receiving input from the spaceball */
++int SPW_CheckForSpaceballWin32(void * win)
++{
++  char classname[25];
++  SiOpenData oData;
++
++  if (Spw_DeviceHandle == SI_NO_HANDLE) {
++    if (SiInitialize() != SPW_DLL_LOAD_ERROR) {
++      GetClassName((HWND)win, classname, sizeof(classname));
++      SiOpenWinInit(&oData, (HWND)win);
++      
++      Spw_DeviceHandle = SiOpen(classname, SI_ANY_DEVICE, SI_NO_MASK, SI_EVENT, &oData);
++
++      if (Spw_DeviceHandle != SI_NO_HANDLE) {
++        SiSetUiMode(Spw_DeviceHandle, SI_UI_ALL_CONTROLS);
++        return TRUE;
++      }
++      else {
++        SiTerminate();
++        return FALSE;
++      }
++    }
++    else return FALSE;
++  } 
++  else return TRUE;
++}
++
++/* translates a Win32 event to a SPW_InputEvent. */
++int SPW_TranslateEventWin32(MSG * msg, SPW_InputEvent * sbEvent)
++{
++  SiSpwEvent spwEvent;
++  SiGetEventData eventdata;
++
++  if (Spw_DeviceHandle != SI_NO_HANDLE) {
++
++    SiGetEventWinInit (&eventdata, msg->message, msg->wParam, msg->lParam);
++    if (SiGetEvent (Spw_DeviceHandle, 0, &eventdata, &spwEvent) == SI_IS_EVENT) {
++
++      int i;
++      switch(spwEvent.type) {
++        case SI_MOTION_EVENT:
++          sbEvent->type = SPW_InputMotionEvent;      
++          for(i=0; i<6; i++) {
++            sbEvent->sData[i] = (short)spwEvent.u.spwData.mData[i];
++          }  
++          break;
++        case SI_BUTTON_EVENT:
++          sbEvent->type = SPW_InputButtonPressEvent;
++          sbEvent->buttonState.pressed = (SiButtonPressed(&spwEvent) != SI_NO_BUTTON);
++          sbEvent->buttonState.released = (SiButtonReleased(&spwEvent) != SI_NO_BUTTON);
++          break;
++      }
++      return TRUE;
++    }
++  }
++  return FALSE;
++}
++
++/* Stop receiving input from the spaceball */
++void SPW_disableSpaceBallWin32(void)
++{
++  SiClose(Spw_DeviceHandle);
++  SiTerminate();
++  Spw_DeviceHandle = SI_NO_HANDLE;
++}
++
++
++/*-----------------------------------------------------------------------------
++ *
++ *  void __SiAppInitialize(void)
++ *
++ *  Args:
++ *    None
++ *
++ *  Return Value:
++ *    None
++ *
++ *  Description:
++ *    This function opens up the DLL library and, if successful, loads a
++ *  function pointer table with exported UAPI functions contained in the DLL.
++ *
++ *---------------------------------------------------------------------------*/
++int __SiAppInitialize(void)
++{
++   enum InitResult nResult;      /* intialization result code */
++   enum ErrorCode nErrorCode;    /* function return code */
++
++   /* attempt to load the DLL */
++   if ((ghDll = LoadLibrary (DllLibrary)) != NULL)
++      {
++      /* preset variables and hope for success */
++      nResult = LOADED;
++      nErrorCode = NO_DLL_ERROR;
++
++      /* load up the global variable used by the DLL to return error info */
++
++      if ((pDllSpwRetVal = (enum SpwRetVal *)
++                           GetProcAddress(ghDll, strDLLRetVal)) == NULL)
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_VAR_LOAD_FAILURE;
++         }
++
++      /* load up function pointer table */
++      if ((pfnSiBeep = (PFNSI_BEEP)
++                           GetProcAddress(ghDll, fnSiBeep)) == NULL)
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++
++      if ((pfnSiInit = (PFNSI_INIT)
++                           GetProcAddress(ghDll, fnSiInitialize)) == NULL)      
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++        
++      if ((pfnSiTerminate = (PFNSI_TERMINATE)
++                           GetProcAddress(ghDll, fnSiTerminate)) == NULL)      
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++        
++      if ((pfnSiGetNumDevices = (PFNSI_GETNUMDEVICES)
++                           GetProcAddress(ghDll, fnSiGetNumDevices)) == NULL)      
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++     
++      if ((pfnSiGetDeviceID = (PFNSI_GETDEVICEID)
++                           GetProcAddress(ghDll, fnSiGetDeviceID)) == NULL)      
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++
++      if ((pfnSiDeviceIndex = (PFNSI_DEVICEINDEX)
++                           GetProcAddress(ghDll, fnSiDeviceIndex)) == NULL)      
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++        
++      if ((pfnSiDispatch = (PFNSI_DISPATCH)
++                           GetProcAddress(ghDll, fnSiDispatch)) == NULL)      
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++        
++      if ((pfnSiOpenWinInit = (PFNSI_OPENWININIT)
++                           GetProcAddress(ghDll, fnSiOpenWinInit)) == NULL)      
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++        
++      if ((pfnSiOpen = (PFNSI_OPEN)
++                           GetProcAddress(ghDll, fnSiOpen)) == NULL)      
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++        
++      if ((pfnSiClose = (PFNSI_CLOSE)
++                           GetProcAddress(ghDll, fnSiClose)) == NULL)      
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++        
++      if ((pfnSiGetEventWinInit = (PFNSI_GETEVENTWININIT)
++                           GetProcAddress(ghDll, fnSiGetEventWinInit)) == NULL)      
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++        
++      if ((pfnSiIsSpaceWareEvent = (PFNSI_ISSPACEWAREEVENT)
++                           GetProcAddress(ghDll, fnSiIsSpaceWareEvent)) == NULL)      
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++        
++      if ((pfnSiGetEvent = (PFNSI_GETEVENT)
++                           GetProcAddress(ghDll, fnSiGetEvent)) == NULL)      
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++        
++      if ((pfnSiRezero = (PFNSI_REZERO)
++                           GetProcAddress(ghDll, fnSiRezero)) == NULL)      
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++        
++      if ((pfnSiGrabDevice = (PFNSI_GRABDEVICE)
++                           GetProcAddress(ghDll, fnSiGrabDevice)) == NULL)      
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++        
++      if ((pfnSiReleaseDevice = (PFNSI_RELEASEDEVICE)
++                           GetProcAddress(ghDll, fnSiReleaseDevice)) == NULL)      
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++        
++      if ((pfnSiButtonPressed = (PFNSI_BUTTONPRESSED)
++                           GetProcAddress(ghDll, fnSiButtonPressed)) == NULL)      
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++        
++      if ((pfnSiButtonReleased = (PFNSI_BUTTONRELEASED)
++                           GetProcAddress(ghDll, fnSiButtonReleased)) == NULL)      
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++        
++      if ((pfnSiSetUiMode = (PFNSI_SETUIMODE)
++                           GetProcAddress(ghDll, fnSiSetUIMode)) == NULL)      
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++        
++      if ((pfnSiGetDevicePort = (PFNSI_GETDEVICEPORT)
++                           GetProcAddress(ghDll, fnSiGetDevicePort)) == NULL)      
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++        
++      if ((pfnSiGetDriverInfo = (PFNSI_GETDRIVERINFO)
++                           GetProcAddress(ghDll, fnSiGetDriverInfo)) == NULL)      
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++        
++      if ((pfnSiGetLibraryInfo = (PFNSI_GETLIBRARYINFO)
++                           GetProcAddress(ghDll, fnSiGetLibraryInfo)) == NULL)      
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++        
++      if ((pfnSiGetDeviceInfo = (PFNSI_GETDEVICEINFO)
++                           GetProcAddress(ghDll, fnSiGetDeviceInfo)) == NULL)      
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++        
++      if ((pfnSpwErrorString = (PFNSPW_ERRORSTRING)
++                           GetProcAddress(ghDll, fnSpwErrorString)) == NULL)      
++         {
++         nResult = FAILED;
++         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++         }
++      }
++   else  /* couldn't load DLL */
++      {
++      nResult = FAILED;
++      nErrorCode = DLL_LOAD_FAILURE;
++      }
++
++   /* set the global variable */
++
++   gInitStatus = nResult;
++  
++   return nErrorCode;
++}
++
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiInitialize (void)
++ *
++ * Args:
++ *
++ * Return Value:
++ *    SPW_NO_ERROR      No error
++ *    SPW_ERROR         Initialization error
++ *
++ * Description:
++ *    This function initializes the SpaceWare input library.  Since most input
++ *    functions require that the library be initialized, this function should
++ *    be called before any other input functions are called.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum SpwRetVal
++SiInitialize(void)
++{
++   enum SpwRetVal tmpRetVal;  /* temporary return value */
++
++   if (gInitStatus != LOADED)
++      {
++      __SiAppInitialize();
++      if (gInitStatus == FAILED)
++         {
++         return SPW_DLL_LOAD_ERROR;
++         }
++      }
++
++   tmpRetVal = pfnSiInit();
++   SpwErrorVal = *pDllSpwRetVal;
++   return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SiTerminate (void)
++ *
++ * Args:
++ *   None
++ *
++ * Return Value:
++ *   None
++ *
++ * Description:
++ *    This function must be called to properly shut down the SpaceWare input
++ *    library.  No other input functions (except SiInit) should be called
++ *    afterwards.
++ *
++ *---------------------------------------------------------------------------*/
++
++void
++SiTerminate(void)
++{
++   /* It is unlikely that the function table will not have been loaded by the
++      time this is called, but we'll cover the bases anyhow */
++   if (gInitStatus != LOADED)
++      {
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         SpwErrorVal = SPW_DLL_LOAD_ERROR;  /* global variable */
++         return;
++         }
++  
++      /* if we weren't returning void, we'd do error handling here */
++      }
++
++   pfnSiTerminate();
++   SpwErrorVal = *pDllSpwRetVal;
++
++   /* Unload the DLL to prevent memory leaks */
++   FreeLibrary(ghDll);
++
++   /* change status in case someone reinitializes */
++   gInitStatus = NOT_LOADED;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SiGetNumDevices (void)
++ *
++ * Args:
++ *
++ * Return Value:
++ *    If the SpaceWare input library is initialized, the number of devices is
++ *    returned and SpwErrorVal is set to SPW_NO_ERROR.  Otherwise, the return
++ *    code is -1 and SpwErrorVal is set to either SI_UNINITIALIZED or one of
++ *    the other standard error codes.
++ *
++ * Description:
++ *    This function returns the number of input devices detected by the
++ *    driver.
++ *
++ *---------------------------------------------------------------------------*/
++
++int
++SiGetNumDevices (void)
++{
++   int tmpRetVal;  /* temporary return value */
++
++   if (gInitStatus != LOADED)
++      {
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         SpwErrorVal = SPW_DLL_LOAD_ERROR;  /* global variable */
++         return -1;
++         }
++      }
++
++   tmpRetVal = pfnSiGetNumDevices();
++   SpwErrorVal = *pDllSpwRetVal;
++   return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * SiDevID SiGetDeviceID (SiHdl hdl)
++ *
++ * Args:
++ *    hdl      (r/o) SpaceWare handle
++ *
++ * Return Value:
++ *    If there is no error, the device ID is returned and SpwErrorVal is set
++ *    to SPW_NO_ERROR.  Otherwise, the return value is SI_NO_DEVICE and
++ *    SpwErrorVal is set to either SI_BAD_HANDLE (if the SpaceWare handle is
++ *    invalid) or one of the other standard error codes.
++ *
++ * Description:
++ *    Given a SpaceWare handle, this function returns the ID of the
++ *    associated device.
++ *
++ *---------------------------------------------------------------------------*/
++
++SiDevID
++SiGetDeviceID (SiHdl hdl)
++{
++   SiDevID tmpRetVal;  /* temporary return value */
++
++   if (gInitStatus != LOADED)
++      {
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         SpwErrorVal = SPW_DLL_LOAD_ERROR;  /* global variable */
++         return SI_NO_DEVICE;
++         }
++      }
++
++   tmpRetVal = pfnSiGetDeviceID(hdl);
++   SpwErrorVal = *pDllSpwRetVal;
++   return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * SiDevID SiDeviceIndex (int idx)
++ *
++ * Args:
++ *    idx   (r/o) Device index (zero relative)
++ *
++ * Return Value:
++ *    If there is no error, the device ID is returned and SpwErrorVal is set
++ *    to SPW_NO_ERROR.  Otherwise, the return value is SI_NO_DEVICE and
++ *    SpwErrorVal is set to either SPW_ERROR (if the device index is invalid),
++ *    SI_UNINITIALIZED, or SI_NO_DRIVER.
++ *
++ * Description:
++ *    Given a device index, SiDeviceIndex returns the associated device ID.
++ *    This routine is particularly useful with the function SiGetDevicePort.
++ *
++ *---------------------------------------------------------------------------*/
++
++SiDevID
++SiDeviceIndex (int idx)
++{
++   SiDevID tmpRetVal;  /* temporary return value */
++
++   if (gInitStatus != LOADED)
++      {
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         SpwErrorVal = SPW_DLL_LOAD_ERROR;  /* global variable */
++         return SI_NO_DEVICE;
++         }
++      }
++
++   tmpRetVal = pfnSiDeviceIndex(idx);
++   SpwErrorVal = *pDllSpwRetVal;
++   return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SiDispatch (SiHdl hdl, SiGetEventData *pData, SiSpwEvent *pEvent,
++ *    SiSpwHandlers *pHandlers)
++ *
++ * Args:
++ *    hdl         (r/o) SpaceWare handle
++ *    pData       (r/o) Pntr to platform specific data (as passed to SiGetEvent)
++ *    pEvent      (r/o) Pntr to SpaceWare event (as returned by SiGetEvent)
++ *    pHandlers   (r/o) Pntr to SpaceWare event handlers
++ *
++ * Return Value:
++ *    Value returned by called event handler or zero if handler not defined.
++ *
++ * Description:
++ *    Provided as a companion to SiGetEvent, this function calls the appro-
++ *    priate handler to process the SpaceWare event returned by SiGetEvent.
++ *    The SiSpwHandlers structure contains one handler for each event type.
++ *    An event type can be ignored by setting the func member of the appro-
++ *    priate SiEventHandler structure to NULL.  Unlike the handler for
++ *    SiGetEvent, there is no specific use for the function return value of
++ *    these handlers -- the interpretation is entirely the caller's.
++ *
++ *---------------------------------------------------------------------------*/
++
++int
++SiDispatch (SiHdl hdl, SiGetEventData *pData,
++                SiSpwEvent *pEvent, SiSpwHandlers *pDHandlers)
++{
++   int tmpRetVal;  /* temporary return value */
++
++   if (gInitStatus != LOADED)
++      {
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         return 0;
++         }
++      }
++
++   tmpRetVal = pfnSiDispatch(hdl, pData, pEvent, pDHandlers);
++   SpwErrorVal = *pDllSpwRetVal;
++   return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SiOpenWinInit (SiOpenData *pData, HWND hWnd)
++ *
++ * Args:
++ *    pData (w/o) Pointer to storage for returned platform specific data
++ *    hWnd  (r/o) Window handle
++ *
++ * Return Value:
++ *    Nothing
++ *
++ * Description:
++ *    This function initializes the Windows platform specific data for a
++ *    subsequent call to SiOpen.
++ *
++ *---------------------------------------------------------------------------*/
++
++void
++SiOpenWinInit (SiOpenData *pData, HWND hWnd)
++{
++   if (gInitStatus != LOADED)
++      {
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         pData = NULL;
++         hWnd = NULL;
++         return;
++         }
++      }
++
++   pfnSiOpenWinInit(pData, hWnd);
++   SpwErrorVal = *pDllSpwRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * SiHdl SiOpen (char *pAppName, SiDevID devID, SiTypeMask *pTMask, int mode,
++ *    SiOpenData *pData)
++ *
++ * Args:
++ *    pAppName (r/o) Pointer to application name
++ *    devID    (r/o) Device ID or SI_ANY_DEVICE
++ *    pTMask   (r/o) Pointer to device type mask or SI_NO_MASK
++ *    mode     (r/o) SpaceWare event retrieval method:  SI_EVENT or SI_POLL
++ *    pData    (r/o) Pointer to platform specific data if mode is SI_EVENT
++ *
++ * Return Value:
++ *    SpaceWare handle or SI_NO_HANDLE if error.  SpwErrorVal is set to one
++ *    of the following:
++ *
++ *    SPW_NO_ERROR      No error
++ *    SPW_ERROR         Device could not be opened
++ *    SI_BAD_ID         Invalid device ID
++ *    SI_BAD_VALUE      Invalid argument
++ *    SI_UNSUPPORTED    Specified retrieval method is unsupported
++ *
++ * Description:
++ *    SiOpen is called to open a device for input and (sometimes) output
++ *    access.  The device in which to open is indicated via the device ID
++ *    (devID) and a device type mask (pTMask).  If the ID of a particular
++ *    device is known, it is passed in devID.  If the ID is not known or the
++ *    application simply doesn't care which device is selected, devID is passed
++ *    as SI_ANY_DEVICE.
++ *
++ *    Irrespective of the device ID, the device type mask indicates which
++ *    device types are permitted.  The type may be constrained to particular
++ *    devices, classes, or any combination thereof.  The mask is created via
++ *    the function SiSetTypeMask (see the definition of that function for more
++ *    information).  If the application doesn't wish to constrain the selection
++ *    to any particular types or classes, pTMask may be passed as SI_NO_MASK.
++ *    This is the equivalent of passing a mask set to SI_ALL_TYPES.
++ *
++ *    The following table shows how a device is selected based on the device ID
++ *    and type mask.  In those cases where SI_ANY_DEVICE is specified, the
++ *    order in which the devices are searched is the same order as indexed by
++ *    the function SiDevIndex.
++ *
++ *    devID            pTMask          Device selected
++ *
++ *    SI_ANY_DEVICE    SI_NO_MASK      The first available device in the list.
++ *
++ *    A device ID      SI_NO_MASK      The device matching the specified ID if
++ *                                     it's available.
++ *
++ *    SI_ANY_DEVICE    A type mask     The first available device in the list
++ *                                     with a type or class that is specified
++ *                                     in the mask.
++ *
++ *    A device ID      A type mask     The device matching the specified ID if
++ *                                     its type or class matches one specified
++ *                                     in the mask and it's available.
++ *
++ *    Note that some SpaceWare implementations will run only if all of the
++ *    configured devices are attached and working properly.  Thus, all of the
++ *    devices are available.  Other implementations may run with some devices
++ *    not working.  These constitute unavailable devices.
++ *
++ *    The mode argument specifies how the application intends to retrieve
++ *    data from the device.  SI_EVENT indicates that the application should
++ *    be informed, via a system event message, whenever device data is
++ *    pending.  The message is acknowledged by a call to SiGetEvent. When
++ *    this mode is selected, pData points to the platform specific informa-
++ *    tion necessary for the API to generate system event messages.  The mode
++ *    SI_POLL indicates that the application will check for data from the
++ *    device by calling SiGetEvent regularly.  For this mode, pData is passed
++ *    as NULL.
++ *
++ *---------------------------------------------------------------------------*/
++
++SiHdl
++SiOpen (char *pAppName, SiDevID devID, SiTypeMask *pTMask, int mode,
++              SiOpenData *pData)
++{
++   SiHdl tmpRetVal;  /* temporary return value */
++
++   if (gInitStatus != LOADED)
++      {
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         SpwErrorVal = SPW_DLL_LOAD_ERROR;
++         return NULL;
++         }
++      }
++
++   tmpRetVal = pfnSiOpen(pAppName, devID, pTMask, mode, pData);
++   SpwErrorVal = *pDllSpwRetVal;
++   return tmpRetVal;
++
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiClose (SiHdl hdl)
++ *
++ * Args:
++ *    hdl   (r/o) SpaceWare handle
++ *
++ * Return Value:
++ *    SPW_NO_ERROR      No error
++ *    SPW_ERROR         Close error
++ *    SI_BAD_HANDL      Invalid SpaceWare handle
++ *
++ * Description:
++ *    This function closes a device.   Once closed, the SpaceWare handle is
++ *    no longer valid.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum
++SpwRetVal SiClose (SiHdl hdl)
++{
++   enum SpwRetVal tmpRetVal;  /* temporary return value */
++
++   if (gInitStatus != LOADED)
++      {
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         return SPW_DLL_LOAD_ERROR;
++         }
++      }
++
++   tmpRetVal = pfnSiClose(hdl);
++   SpwErrorVal = *pDllSpwRetVal;
++   return tmpRetVal;
++
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * SPWbool SiIsSpaceWareEvent (SiGetEventData *pData, SiHdl *pHdl)
++ *
++ * Args:
++ *    pData (r/o) Pointer to platform specific data
++ *    pHdl  (w/o) Pointer to storage for returned SpaceWare handle
++ *
++ * Return Value:
++ *    SPW_TRUE if pData refers to a SpaceWare event, otherwise SPW_FALSE.
++ *
++ * Description:
++ *    This function determines whether or not the data addressed by pData per-
++ *    tains to a SpaceWare event.  If so, the handle for which the event is
++ *    intended is returned.
++ *
++ * Notes:
++ *    NULL may be passed for pHdl if the return of the intended handle is not
++ *    required.
++ *
++ *---------------------------------------------------------------------------*/
++
++SPWbool
++SiIsSpaceWareEvent(SiGetEventData *pData, SiHdl *pHdl)
++{
++   SPWbool tmpRetVal;  /* temporary return value */
++
++   if (gInitStatus != LOADED)
++      {
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         return SPW_FALSE;
++         }
++      }
++
++   tmpRetVal = pfnSiIsSpaceWareEvent(pData, pHdl);
++   SpwErrorVal = *pDllSpwRetVal;
++   return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SiGetEventWinInit (SiGetEventData *pData,
++ *    UINT msg, WPARAM wParam, LPARAM lParam)
++ *
++ * Args:
++ *    pData    (w/o) Pointer to storage for returned platform specific data
++ *    msg      (r/o) Windows message
++ *    wParam   (r/o) Parameter #1
++ *    lParam   (r/o) Parameter #2
++ *
++ * Return Value:
++ *    Nothing
++ *
++ * Description:
++ *    This function initializes the Windows platform specific data for a
++ *    subsequent call to SiGetEvent.
++ *
++ *---------------------------------------------------------------------------*/
++
++void
++SiGetEventWinInit (SiGetEventData *pData, UINT msg, WPARAM wParam,
++                   LPARAM lParam)
++{
++   if (gInitStatus != LOADED)
++      {
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         return;
++         }
++      }
++
++   pfnSiGetEventWinInit(pData, msg, wParam, lParam);
++   SpwErrorVal = *pDllSpwRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiGetEvent (SiHdl hdl, int flags,
++ *    SiGetEventData *pData, SiSpwEvent *pEvent)
++ *
++ * Args:
++ *    hdl      (r/o) SpaceWare handle
++ *    flags    (r/o) Processing flags
++ *    pData    (r/o) Pointer to platform specific data
++ *    pEvent   (w/o) Pointer to storage for returned SpaceWare event
++ *
++ * Return Value:
++ *    SI_BAD_HANDLE     Invalid SpaceWare handle
++ *    SI_NOT_EVENT      The event is not a SpaceWare event or no event pending
++ *    SI_IS_EVENT       The event is a SpaceWare event
++ *    SI_SKIP_EVENT     The event is a SpaceWare event but it should be skipped
++ *
++ * Description:
++ *    This function determines if device data is pending and if so, returns
++ *    the data as a SpaceWare event.  See the "SpaceWare Universal API"
++ *    specification for a complete description of this function.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum SpwRetVal
++SiGetEvent (SiHdl hdl, int flags, SiGetEventData *pData,
++                           SiSpwEvent *pEvent)
++{
++   enum SpwRetVal tmpRetVal;  /* temporary return value */
++
++   if (gInitStatus != LOADED)
++      {
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         return SPW_DLL_LOAD_ERROR;
++         }
++      }
++
++   tmpRetVal = pfnSiGetEvent(hdl, flags, pData, pEvent);
++   SpwErrorVal = *pDllSpwRetVal;
++   return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiBeep (SiHdl hdl, char *pString)
++ *
++ * Args:
++ *    hdl      (r/o) SpaceWare handle
++ *    pString  (r/o) Pointer to beep description string
++ *
++ * Return Value:
++ *    SPW_NO_ERROR      No error
++ *    SI_BAD_HANDLE     Invalid SpaceWare handle
++ *    SI_BAD_VALUE      Bad string
++ *
++ * Description:
++ *    If supported, this function causes the input device to emit a sequence
++ *    of tones and pauses.  Each character of the string represents either a
++ *    tone or a delay.  Lowercase letters [a-z] represent a tone, uppercase
++ *    letters [A-Z] represent a pause.  The closer the letter is to the
++ *    beginning of the alphabet the shorter the pause or tone ('a' or 'A' is
++ *    1/32 second, 'b' or 'B' is 2/32 second, etc).  Up to 14 characters in
++ *    a string are processed, additional characters are ignored.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum SpwRetVal
++SiBeep(SiHdl hdl, char *pString)
++{
++   enum SpwRetVal tmpRetVal;  /* temporary return value */
++
++   if (gInitStatus != LOADED)
++      {
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         return SPW_DLL_LOAD_ERROR;
++         }
++      }
++
++   tmpRetVal = pfnSiBeep(hdl, pString);
++   SpwErrorVal = *pDllSpwRetVal;
++   return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiRezero (SiHdl hdl)
++ *
++ * Args:
++ *    hdl   (r/o) SpaceWare handle
++ *
++ * Return Value:
++ *    SPW_NO_ERROR      No error
++ *    SI_BAD_HANDLE     Invalid SpaceWare handle
++ *
++ * Description:
++ *    This function causes the input device's current setting to be defined
++ *    as the rest position.  Movement away from this position will cause
++ *    motion events. This can be used to eliminate drift or to set up a
++ *    constant motion.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum SpwRetVal
++SiRezero (SiHdl hdl)
++{
++   enum SpwRetVal tmpRetVal;  /* temporary return value */
++
++   if (gInitStatus != LOADED)
++      {
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         return SPW_DLL_LOAD_ERROR;
++         }
++      }
++
++   tmpRetVal = pfnSiRezero(hdl);
++   SpwErrorVal = *pDllSpwRetVal;
++   return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiGrabDevice (SiHdl hdl, SPWbool exclusive)
++ *
++ * Args:
++ *    hdl         (r/o) SpaceWare handle
++ *    exclusive   (r/o) Exclusive grab flag
++ *
++ * Return Value:
++ *    SPW_NO_ERROR      No error
++ *    SPW_ERROR         Grab failed
++ *    SI_BAD_HANDLE     Invalid SpaceWare handle
++ *
++ * Description:
++ *    This function is used to "grab" or capture a device in multi-tasking
++ *    environments.  For an exclusive capture, the application retains control
++ *    of the device regardless of which window has the focus.  For a non-
++ *    exclusive capture, the application retains control of the device only if
++ *    no other application, sharing the same device, has the focus.  Some
++ *    SpaceWare implementations only allow one non-exclusive grab.  Others
++ *    allow multiple non-exclusive grabs and provide an interface for inter-
++ *    actively selecting the current non-exclusive grab application.  An exclu-
++ *    sive grab fails if another application has already exclusively captured
++ *    the device.  A non-exclusive grab fails if the SpaceWare implementation
++ *    only allows one non-exclusive grab and another application has already
++ *    non-exclusively captured the device.  Note that an exclusive grab should
++ *    be used sparingly if at all.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum SpwRetVal
++SiGrabDevice (SiHdl hdl, SPWbool exclusive)
++{
++   enum SpwRetVal tmpRetVal;  /* temporary return value */
++
++   if (gInitStatus != LOADED)
++      {
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         return SPW_DLL_LOAD_ERROR;
++         }
++      }
++
++   tmpRetVal = pfnSiGrabDevice(hdl, exclusive);
++   SpwErrorVal = *pDllSpwRetVal;
++   return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiReleaseDevice (SiHdl hdl)
++ *
++ * Args:
++ *    hdl   (r/o) SpaceWare handle
++ *
++ * Return Value:
++ *    SPW_NO_ERROR      No error
++ *    SPW_ERROR         Device not captured
++ *    SI_BAD_HANDLE     Invalid SpaceWare handle
++ *
++ * Description:
++ *    This function releases a device that has been captured via the routine
++ *    SiGrabDevice.  A captured device is automatically released when closed.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum SpwRetVal
++SiReleaseDevice (SiHdl hdl)
++{
++   enum SpwRetVal tmpRetVal;  /* temporary return value */
++
++   if (gInitStatus != LOADED)
++      {
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         return SPW_DLL_LOAD_ERROR;
++         }
++      }
++
++   tmpRetVal = pfnSiReleaseDevice(hdl);
++   SpwErrorVal = *pDllSpwRetVal;
++   return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SiButtonPressed (SiSpwEvent *pEvent)
++ *
++ * Args:
++ *    pEvent   (r/o) Pointer to SpaceWare event
++ *
++ * Return Value:
++ *    Button number or SI_NO_BUTTON if not a button or combo event or no
++ *    button was pressed.  If it's not a button or combo event, SpwErrorVal
++ *    is set to SPW_ERROR otherwise SpwErrorVal is SPW_NO_ERROR.
++ *
++ * Description:
++ *    Given a button or combo event, this function returns the number of the
++ *    button pressed.  In the event that multiple buttons are pressed, the
++ *    lowest button number is returned.
++ *
++ *---------------------------------------------------------------------------*/
++
++int
++SiButtonPressed (SiSpwEvent *pEvent)
++{
++   int tmpRetVal;  /* temporary return value */
++
++   if (gInitStatus != LOADED)
++      {
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         SpwErrorVal = SPW_DLL_LOAD_ERROR;
++         return SI_NO_BUTTON;
++         }
++      }
++
++   tmpRetVal = pfnSiButtonPressed(pEvent);
++   SpwErrorVal = *pDllSpwRetVal;
++   return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SiButtonReleased (SiSpwEvent *pEvent)
++ *
++ * Args:
++ *    pEvent   (r/o) Pointer to SpaceWare event
++ *
++ * Return Value:
++ *    Button number or SI_NO_BUTTON if not a button or combo event or no
++ *    button was released. If it's not a button or combo event, SpwErrorVal
++ *    is set to SPW_ERROR otherwise SpwErrorVal is SPW_NO_ERROR.
++ *
++ * Description:
++ *    Given a button or combo event, this function returns the number of the
++ *    button released.  In the event that multiple buttons are released, the
++ *    lowest button number is returned.
++ *
++ *---------------------------------------------------------------------------*/
++
++int
++SiButtonReleased (SiSpwEvent *pEvent)
++{
++   int tmpRetVal;  /* temporary return value */
++
++   if (gInitStatus != LOADED)
++      {
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         SpwErrorVal = SPW_DLL_LOAD_ERROR;
++         return SI_NO_BUTTON;
++         }
++      }
++
++   tmpRetVal = pfnSiButtonReleased(pEvent);
++   SpwErrorVal = *pDllSpwRetVal;
++   return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiSetUiMode (SiHdl hdl, SPWuint32 mode)
++ *
++ * Args:
++ *    hdl   (r/o) SpaceWare handle or SI_ALL_HANDLES
++ *    mode  (r/o) UI mode
++ *
++ * Return Value:
++ *    SPW_NO_ERROR      No error
++ *    SI_BAD_HANDLE     Invalid SpaceWare handle
++ *
++ * Description:
++ *    This function sets the current User Interface (UI) mode bit mask for a
++ *    specified device.  If hdl is SI_ALL_HANDLES, the mask for each open
++ *    device is set.  This option is useful if an app uses the same UI mode
++ *    for more than one device.  Each set bit in the mask indicates that a
++ *    particular feature is enabled.  The bits are defined as follows.
++ *
++ *       SI_UI_ALL_CONTROLS      All controls
++ *       SI_UI_NO_CONTROLS       No controls
++ *       SI_UI_FILTERS           Filter controls
++ *       SI_UI_FUNC_BUTTONS      Function buttons
++ *       SI_UI_RESET_BUTTONS     Reset buttons
++ *       SI_UI_SENSITIVITY       Sensitivity control
++ *       SI_UI_TUNING            Tuning control
++ *       SI_UI_DIALOG_POPUP      Dialog popup button (on device)
++ *
++ *    Note that for SI_UI_ALL_CONTROLS, all bits are set; for SI_UI_NO_CONTROLS,
++ *    no bits are set.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum SpwRetVal
++SiSetUiMode (SiHdl hdl, SPWuint32 mode)
++{
++   enum SpwRetVal tmpRetVal;  /* temporary return value */
++
++   if (gInitStatus != LOADED)
++      {
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         return SPW_DLL_LOAD_ERROR;
++         }
++      }
++
++   tmpRetVal = pfnSiSetUiMode(hdl, mode);
++   SpwErrorVal = *pDllSpwRetVal;
++   return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiSetTypeMask (SiTypeMask *pTMask, int type1, ...,
++ *    SI_END_ARGS)
++ *
++ * Args:
++ *    pTMask   (w/o) Pointer to storage for returned device type mask
++ *    type1    (r/o) First device type
++ *    ...      (r/o) Additional device types
++ *
++ * Return Value:
++ *    SPW_NO_ERROR   No error
++ *
++ * Description:
++ *   This function provides compatibility with older software.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum SpwRetVal
++SiSetTypeMask (SiTypeMask *pTMask, int type1, ...)
++{
++   if (gInitStatus != LOADED)
++      {
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         return SPW_DLL_LOAD_ERROR;
++         }
++      }
++
++   /* stub function -> return a happy value */
++   return SPW_NO_ERROR;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiGetDevicePort (SiDevID devID, SiDevPort *pPort)
++ *
++ * Args:
++ *    devID (r/o) Device ID
++ *    pPort (w/o) Pointer to storage for returned device port info
++ *
++ * Return Value:
++ *    SPW_NO_ERROR      No error
++ *    SI_BAD_ID         Invalid device ID
++ *
++ * Description:
++ *    The purpose of this function is to provide a correlation between the
++ *    devices and the system ports to which they are connected.  Each call
++ *    to SiGetDevicePort returns information for one device.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum SpwRetVal
++SiGetDevicePort (SiDevID devID, SiDevPort *pPort)
++{
++   enum SpwRetVal tmpRetVal;  /* temporary return value */
++
++   if (gInitStatus != LOADED)
++      {
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         return SPW_DLL_LOAD_ERROR;
++         }
++      }
++
++   tmpRetVal = pfnSiGetDevicePort(devID, pPort);
++   SpwErrorVal = *pDllSpwRetVal;
++   return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiGetDriverInfo (SiVerInfo *pInfo)
++ *
++ * Args:
++ *    pInfo (w/o) Pointer to storage for returned driver version info
++ *
++ * Return Value:
++ *    SPW_NO_ERROR  No error
++ *    SPW_ERROR     This version of the SpaceWare library does not use a driver
++ *
++ * Description:
++ *    SiGetDriverInfo returns driver version information.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum SpwRetVal
++SiGetDriverInfo (SiVerInfo *pInfo)
++{
++   enum SpwRetVal tmpRetVal;  /* temporary return value */
++
++   if (gInitStatus != LOADED)
++      {
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         return SPW_DLL_LOAD_ERROR;
++         }
++      }
++
++   tmpRetVal = pfnSiGetDriverInfo(pInfo);
++   SpwErrorVal = *pDllSpwRetVal;
++   return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SiGetLibraryInfo (SiVerInfo *pInfo)
++ *
++ * Args:
++ *    pInfo (w/o) Pointer to storage for returned library version info
++ *
++ * Return Value:
++ *    Nothing.  SpwErrorVal is always set to SPW_NO_ERROR by this function.
++ *
++ * Description:
++ *    SiGetLibraryInfo returns library version information.
++ *
++ *---------------------------------------------------------------------------*/
++
++void
++SiGetLibraryInfo (SiVerInfo *pInfo)
++{
++   if (gInitStatus != LOADED)
++      {  
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         pInfo = NULL;
++         return;
++         }
++
++      }
++
++   pfnSiGetLibraryInfo(pInfo);
++   SpwErrorVal = *pDllSpwRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiGetDeviceInfo (SiHdl hdl, SiDevInfo *pInfo)
++ *
++ * Args:
++ *    hdl   (r/o) SpaceWare handle
++ *    pInfo (w/o) Pointer to storage for returned device information
++ *
++ * Return Value:
++ *    SPW_NO_ERROR      No error
++ *    SI_BAD_HANDLE     Invalid SpaceWare handle
++ *
++ * Description:
++ *    This function returns all sorts of information on the specified device.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum SpwRetVal
++SiGetDeviceInfo (SiHdl hdl, SiDevInfo *pInfo)
++{
++   enum SpwRetVal tmpRetVal;  /* temporary return value */
++
++   if (gInitStatus != LOADED)
++      {
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         return SPW_DLL_LOAD_ERROR;
++         }
++   }
++
++   tmpRetVal = pfnSiGetDeviceInfo(hdl, pInfo);
++   SpwErrorVal = *pDllSpwRetVal;
++   return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * char *SpwErrorString (enum SpwRetVal val)
++ *
++ * Parameters:
++ *    val   (r/o) Error value
++ *
++ * Return:
++ *    Pointer to string containing error message.
++ *
++ * Description:
++ *    This function returns a pointer to the error message string associated
++ *    with the given error value.  Note that the returned pointer points to
++ *    static memory that is overridden each time SpwErrorString is called.
++ *
++ *---------------------------------------------------------------------------*/
++
++char *
++SpwErrorString (enum SpwRetVal val)
++{
++
++   if (gInitStatus != LOADED)
++      {
++      SiInitialize();
++      if (gInitStatus == FAILED)
++         {
++         return NULL;
++         }
++      }
++
++   return (char *) pfnSpwErrorString(val);
++}
++
++#endif /* HAVE_WIN32_API */
++
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/spwinput_win32.h.in
+@@ -0,0 +1,511 @@
++#ifndef SPWINPUT_WIN32_H
++#define SPWINPUT_WIN32_H
++
++/* @configure_input@ */
++
++/*----------------------------------------------------------------------
++ * (C) 1998-2009 3Dconnexion. All rights reserved. 
++ * Permission to use, copy, modify, and distribute this software for all
++ * purposes and without fees is hereby grated provided that this copyright
++ * notice appears in all copies.  Permission to modify this software is granted
++ * and 3Dconnexion will support such modifications only is said modifications are
++ * approved by 3Dconnexion.
++ *
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif /* HAVE_CONFIG_H */
++
++#include <Inventor/@Gui@/devices/spwinput.h>
++
++#ifndef HAVE_WIN32_API
++#error "Do not include this file unless HAVE_WIN32_API is set."
++#endif /* !HAVE_WIN32_API */
++
++#include <tchar.h>
++
++/* some enumerated types used in spwinput_win32.cpp */
++enum InitResult 
++   {
++   NOT_LOADED, 
++   FAILED, 
++   LOADED
++   };
++
++enum ErrorCode 
++   {
++   NO_DLL_ERROR=0,
++   DLL_LOAD_FAILURE,
++   DLL_FUNCTION_LOAD_FAILURE,
++   DLL_VAR_LOAD_FAILURE
++   };
++
++enum SpwRetVal             /* Error return values.                           */
++   {
++   SPW_NO_ERROR,           /* No error.                                      */
++   SPW_ERROR,              /* Error -- function failed.                      */
++   SI_BAD_HANDLE,          /* Invalid SpaceWare handle.                      */
++   SI_BAD_ID,              /* Invalid device ID.                             */
++   SI_BAD_VALUE,           /* Invalid argument value.                        */
++   SI_IS_EVENT,            /* Event is a SpaceWare event.                    */
++   SI_SKIP_EVENT,          /* Skip this SpaceWare event.                     */
++   SI_NOT_EVENT,           /* Event is not a SpaceWare event.                */
++   SI_NO_DRIVER,           /* SpaceWare driver is not running.               */
++   SI_NO_RESPONSE,         /* SpaceWare driver is not responding.            */
++   SI_UNSUPPORTED,         /* The function is unsupported by this version.   */
++   SI_UNINITIALIZED,       /* SpaceWare input library is uninitialized.      */
++   SI_WRONG_DRIVER,        /* Driver is incorrect for this SpaceWare version.*/
++   SI_INTERNAL_ERROR,      /* Internal SpaceWare error.                      */
++   SI_BAD_PROTOCOL,        /* The transport protocol is unknown.             */
++   SI_OUT_OF_MEMORY,       /* Unable to malloc space required.               */
++   SPW_DLL_LOAD_ERROR,     /* Could not load siapp dlls                      */
++   SI_NOT_OPEN,            /* Spaceball device not open                      */
++   SI_ITEM_NOT_FOUND	   /* Item not found                                 */
++   };
++
++static enum SpwRetVal *pDllSpwRetVal;
++
++/* some macros */
++#define SPW_FALSE   (0)
++#define SPW_TRUE    (!SPW_FALSE)
++
++#define SPW_MAX(a,b)   (((a)>(b))?(a):(b))
++#define SPW_MIN(a,b)   (((a)<(b))?(a):(b))
++
++#define SPW_ABS(a)   (((a)<0)?(-(a)):(a))
++
++#define SPW_SIGN(a)  ((a)>=0?1:-1)
++
++#define SPW_BIND(min,n,max)   (SPW_MIN((max),SPW_MAX((min),(n))))
++
++#define SPW_NUM_ELEMENTS_IN(a)   (sizeof(a)/sizeof((a)[0]))
++
++#define SPW_PI   3.14159265358979324f
++
++#define SPW_DEG_TO_RAD(d)   ((d)*SPW_PI/180.0f)
++#define SPW_RAD_TO_DEG(r)   ((r)*180.0f/SPW_PI)
++
++#define SPW_LENGTH_OF(a)   (sizeof(a)/sizeof((a)[0]))
++
++#define SPW_END_OF(a)   (&(a)[SPW_LENGTH_OF(a)-1])
++
++#define SPW_SQ(a)   ((a)*(a))
++
++#define SPW_ABSDIFF(a, b) (fabs((double) (a) - (b)))
++
++/* the accepted datatypes for spacetec products */
++
++#define tchar_t				_TCHAR
++#define char_t				char
++#define uint32_t			unsigned long
++#define sint32_t			long
++#define boolean_t			unsigned char  
++#define void_t				void
++#define window_handle_t		HWND
++
++
++typedef long               SPWint32;
++typedef short              SPWint16;
++typedef char               SPWint8;
++typedef int                SPWbool;
++typedef unsigned long      SPWuint32;
++typedef unsigned short     SPWuint16;
++typedef unsigned char      SPWuint8;
++typedef _TCHAR             SPWchar;
++typedef _TCHAR*            SPWstring;
++typedef float              SPWfloat32;
++typedef double             SPWfloat64;
++
++/*
++ * UI modes 
++ */
++#define SI_UI_ALL_CONTROLS    0xffffffffL
++#define SI_UI_NO_CONTROLS     0x00000000L
++
++/*
++ *  These UI modes are left here for legacy applications.
++ */
++#define SI_UI_FILTERS         0x00000001L
++#define SI_UI_FUNC_BUTTONS    0x00000002L
++#define SI_UI_RESET_BUTTONS   0x00000004L
++#define SI_UI_SENSITIVITY     0x00000008L
++#define SI_UI_TUNING          0x00000010L
++#define SI_UI_DIALOG_POPUP    0x00000020L
++
++/*
++ * Device types and classes 
++ */
++typedef enum
++   {
++   SI_ALL_TYPES           = -1,
++   SI_UNKNOWN_DEVICE      =  0,
++   SI_SPACEBALL_2003      =  1,
++   SI_SPACEBALL_3003      =  2,
++   SI_SPACE_CONTROLLER    =  3,
++   SI_AVENGER             =  4,
++   SI_SPACEORB_360        =  5,
++   SI_NAVIGATOR           =  6,
++   SI_SPACEBALL_2003A     =  7,
++   SI_SPACEBALL_2003B     =  8,
++   SI_SPACEBALL_2003C     =  9,
++   SI_SPACEBALL_3003A     =  10,
++   SI_SPACEBALL_3003B     =  11,
++   SI_SPACEBALL_3003C     =  12,
++   SI_SPACEBALL_4000      =  13,
++   SI_SPACEMOUSE_CLASSIC  =  14, 
++   SI_SPACEMOUSE_PLUS     =  15,
++   SI_SPACEMOUSE_XT       =  16,
++   SI_PUCKMAN             =  17,
++   SI_CADMAN              =  18,
++   SI_NUM_DEV_TYPES  /* Leave this last, add before it */
++   } SiDevType;
++
++/*
++ *  These defintions of device classes are left in for legacy applications.
++ */
++#define SI_HIGH_END           63
++#define SI_MED_END            62
++#define SI_LOW_END            61
++
++/*
++ * Data retrieval mode, only SI_EVENT is currently supported.
++ */
++#define SI_EVENT              0x0001
++#define SI_POLL               0x0002
++
++/*
++ * Get event flags
++ */
++#define SI_AVERAGE_EVENTS     0x0001
++
++/*
++ * This is an INTERNAL flag used by the polling mechanism, user applications
++ * should NOT send this flag.
++ */
++#define SI_POLLED_REQUEST     0x0100 
++
++/*
++ * SpaceWare event types
++ */
++typedef enum
++   {
++   SI_BUTTON_EVENT = 1,
++   SI_MOTION_EVENT,
++   SI_COMBO_EVENT, /* Not implemented */
++   SI_ZERO_EVENT,
++   SI_EXCEPTION_EVENT,
++   SI_OUT_OF_BAND,
++   SI_ORIENTATION_EVENT,
++   SI_KEYBOARD_EVENT,
++   SI_LPFK_EVENT
++   } SiEventType;
++
++/*
++ * Data modes
++ */
++#define SI_MODE_NORMALIZE     0x0001
++#define SI_MODE_COMPRESS      0x0002
++#define SI_MODE_SENSITIVITY   0x0004
++#define SI_MODE_TUNING        0x0008
++
++/*
++ * Motion data offsets
++ */
++#define SI_TX                 0              /* Translation X value */
++#define SI_TY                 1              /* Translation Y value */
++#define SI_TZ                 2              /* Translation Z value */
++#define SI_RX                 3              /* Rotation X value */
++#define SI_RY                 4              /* Rotation Y value */
++#define SI_RZ                 5              /* Rotation Z value */
++
++/*
++ * Reserved buttons
++ */
++
++#define SI_RESET_BIT          0x00000001L
++#define SI_PICK_BIT           0x80000000L
++#define SI_DIALOG_BIT         0x40000000L
++
++#define SI_RESET_BUTTON       0
++#define SI_PICK_BUTTON        31
++#define SI_DIALOG_BUTTON      30
++
++/*
++ * Miscellaneous
++ */
++#define SI_END_ARGS           0
++#define SI_NO_HANDLE          ((SiHdl) NULL)
++#define SI_ALL_HANDLES        ((SiHdl) NULL)
++#define SI_ANY_HANDLE         ((SiHdl) NULL)
++#define SI_NO_TRANSCTL        ((SiTransCtl) NULL)
++#define SI_NO_MASK            ((SiTypeMask *) NULL)
++#define SI_ANY_DEVICE         -1
++#define SI_NO_DEVICE          -1
++#define SI_NO_TYPE            -1
++#define SI_NO_LIST            -1
++#define SI_NO_BUTTON          -1
++#define SI_STRSIZE            128
++#define SI_MAXBUF             128
++#define SI_KEY_MAXBUF         5120
++
++typedef int SiDevID;          /* Device ID */
++typedef void *SiHdl;          /* SpaceWare handle */
++typedef void *SiTransCtl;     /* SpaceWare transport control handle */
++
++typedef struct                /* Open data */
++   {
++
++   HWND hWnd;               /* Window handle for SpaceWare messages.        */
++   SiTransCtl transCtl;     /* SpaceWare transport control handle. Reserved */
++                            /* for the s80 transport mechanism.             */
++   DWORD processID;         /* The process ID for this application.         */
++   char exeFile[MAX_PATH];  /* The executable name of the process.          */
++   SPWint32 libFlag;        /* Library version flag.                        */
++   } SiOpenData;
++
++typedef struct                /* Get event Data */
++   {
++
++   UINT msg;
++   WPARAM wParam;
++   LPARAM lParam;
++   } SiGetEventData;
++
++typedef struct                /* Device type mask */
++   {
++   unsigned char mask[8];
++   } SiTypeMask;
++
++typedef struct                /* Device port information */
++   {
++   SiDevID devID;             /* Device ID */
++   int devType;               /* Device type */
++   int devClass;              /* Device class */
++   char devName[SI_STRSIZE];  /* Device name */
++   char portName[SI_STRSIZE]; /* Port name */
++   } SiDevPort;
++
++typedef struct                /* Device information */
++   {
++   char firmware[SI_STRSIZE]; /* Firmware version */
++   int devType;               /* Device type */
++   int numButtons;            /* Number of buttons */
++   int numDegrees;            /* Number of degrees of freedom */
++   SPWbool canBeep;           /* Device beeps */
++   int majorVersion;          /* Major version number */
++   int minorVersion;          /* Minor version number */
++   } SiDevInfo;
++
++typedef struct                /* Version information */
++   {
++   int major;                 /* Major version number */
++   int minor;                 /* Minor version number */
++   int build;                 /* Build number */
++   char version[SI_STRSIZE];  /* Version string */
++   char date[SI_STRSIZE];     /* Date string */
++   } SiVerInfo;
++
++typedef struct                /* Sensitivity parameters */
++   {
++   char dummy;
++   } SiSensitivity;
++
++typedef struct                /* Tuning parameters */
++   {
++   char dummy;
++   } SiTuning;
++
++typedef struct
++   {
++   SPWuint8 code;                 /* Out of band message code */
++   SPWuint8 message[SI_MAXBUF-1]; /* The actual message       */
++   } SiSpwOOB;
++
++typedef struct
++   {
++   SPWuint8 string[SI_KEY_MAXBUF];  /* String for keyboard data */
++   } SiKeyboardData;
++
++typedef struct
++   {
++   SPWuint32 lpfk;            /* LPFK number to send */
++   } SiLpfkData;
++
++typedef enum
++   {
++   SI_LEFT = 0,
++   SI_RIGHT
++   } SiOrientation;
++
++typedef struct                /* Bitmasks of button states */
++   {
++   SPWuint32 last;            /* Buttons pressed as of last event */
++   SPWuint32 current;         /* Buttons pressed as of this event */
++   SPWuint32 pressed;         /* Buttons pressed this event */
++   SPWuint32 released;        /* Buttons released this event */
++   } SiButtonData;
++
++typedef struct                /* SpaceWare data */
++   {
++   SiButtonData bData;        /* Button data */
++   long mData[6];             /* Motion data (index via SI_TX, etc) */
++   long period;               /* Period (milliseconds) */
++   } SiSpwData;
++
++typedef struct                /* SpaceWare event */
++   {
++   int type;                  /* Event type */
++   union
++      {
++      SiSpwData spwData;           /* Button, motion, or combo data        */
++      SiSpwOOB spwOOB;             /* Out of band message                  */
++      SiOrientation spwOrientation;/* Which hand orientation is the device */
++      char exData[SI_MAXBUF];      /* Exception data                       */
++      SiKeyboardData spwKeyData;   /* String for keyboard data             */
++      SiLpfkData spwLpfkData;      /* LPFK data                            */
++      } u;
++   } SiSpwEvent;
++
++typedef struct                /* Event handler (for SiDispatch) */
++   {
++   int (*func) (SiOpenData *, SiGetEventData *, SiSpwEvent *, void *);
++   void *data;
++   } SiEventHandler;
++
++typedef struct                /* SpaceWare event handlers */
++   {
++   SiEventHandler button;     /* Button event handler */
++   SiEventHandler motion;     /* Motion event handler */
++   SiEventHandler combo;      /* Combo event handler */
++   SiEventHandler zero;       /* Zero event handler */
++   SiEventHandler exception;  /* Exception event handler */
++   } SiSpwHandlers;
++
++
++enum SpwRetVal SiAndTypeMask (SiTypeMask *pTMaskA, SiTypeMask *pTMaskB);
++
++
++
++/* interface specifications define parameter passing to DLL functions */
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++typedef enum SpwRetVal (WINAPI *PFNSI_INIT) (void);
++typedef void (WINAPI *PFNSI_TERMINATE) (void);
++typedef void (WINAPI *PFNSI_OPENWININIT) (SiOpenData *pData, HWND hWnd);
++typedef int (WINAPI *PFNSI_GETNUMDEVICES) (void);
++typedef SiDevID (WINAPI *PFNSI_GETDEVICEID) (SiHdl hdl);
++typedef int (WINAPI *PFNSI_DISPATCH) (SiHdl hdl, SiGetEventData *pData,
++                SiSpwEvent *pEvent, SiSpwHandlers *pDHandlers);
++typedef SiHdl (WINAPI *PFNSI_OPEN) (char *pAppName, SiDevID devID, SiTypeMask *pTMask, int mode, 
++              SiOpenData *pData);
++typedef enum SpwRetVal (WINAPI *PFNSI_CLOSE) (SiHdl hdl);
++typedef SPWbool (WINAPI *PFNSI_ISSPACEWAREEVENT) (SiGetEventData *pData, SiHdl *pHdl);
++typedef void (WINAPI *PFNSI_GETEVENTWININIT) (SiGetEventData *pData, UINT msg, WPARAM wParam, LPARAM lParam);
++typedef enum SpwRetVal (WINAPI *PFNSI_GETEVENT) (SiHdl hdl, int flags, SiGetEventData *pData, 
++                           SiSpwEvent *pEvent);
++typedef enum SpwRetVal (WINAPI *PFNSI_BEEP) (SiHdl hdl, char *pString);
++typedef enum SpwRetVal (WINAPI *PFNSI_REZERO) (SiHdl hdl);
++typedef enum SpwRetVal (WINAPI *PFNSI_GRABDEVICE) (SiHdl hdl, SPWbool exclusive);
++typedef enum SpwRetVal (WINAPI *PFNSI_RELEASEDEVICE) (SiHdl hdl);
++typedef int (WINAPI *PFNSI_BUTTONPRESSED) (SiSpwEvent *pEvent);
++typedef int (WINAPI *PFNSI_BUTTONRELEASED) (SiSpwEvent *pEvent);
++typedef enum SpwRetVal (WINAPI *PFNSI_SETUIMODE) (SiHdl hdl, SPWuint32 mode);
++typedef enum SpwRetVal (WINAPI *PFNSI_SETTYPEMASK) (SiTypeMask *pTMask, int type1, ...);
++typedef enum SpwRetVal (WINAPI *PFNSI_GETDEVICEPORT) (SiDevID devID, SiDevPort *pPort);
++typedef enum SpwRetVal (WINAPI *PFNSI_GETDRIVERINFO) (SiVerInfo *pInfo);
++typedef void (WINAPI *PFNSI_GETLIBRARYINFO) (SiVerInfo *pInfo);
++typedef enum SpwRetVal (WINAPI *PFNSI_GETDEVICEINFO) (SiHdl hdl, SiDevInfo *pInfo);
++typedef char* (WINAPI *PFNSPW_ERRORSTRING) (enum SpwRetVal val);
++typedef SiDevID (WINAPI *PFNSI_DEVICEINDEX) (int idx);
++
++#ifdef __cplusplus
++}
++#endif
++
++/* function pointers to functions in DLL */
++static PFNSI_INIT              pfnSiInit;
++static PFNSI_TERMINATE         pfnSiTerminate;
++static PFNSI_OPENWININIT       pfnSiOpenWinInit;
++static PFNSI_GETNUMDEVICES     pfnSiGetNumDevices;
++static PFNSI_GETDEVICEID       pfnSiGetDeviceID;
++static PFNSI_DISPATCH          pfnSiDispatch;
++static PFNSI_OPEN              pfnSiOpen;
++static PFNSI_CLOSE             pfnSiClose;
++static PFNSI_DEVICEINDEX       pfnSiDeviceIndex;
++static PFNSI_GETEVENTWININIT   pfnSiGetEventWinInit;
++static PFNSI_GETEVENT          pfnSiGetEvent;
++static PFNSI_ISSPACEWAREEVENT  pfnSiIsSpaceWareEvent;
++static PFNSI_BEEP              pfnSiBeep;
++static PFNSI_REZERO            pfnSiRezero;
++static PFNSI_GRABDEVICE        pfnSiGrabDevice;
++static PFNSI_RELEASEDEVICE     pfnSiReleaseDevice;
++static PFNSI_BUTTONPRESSED     pfnSiButtonPressed;
++static PFNSI_BUTTONRELEASED    pfnSiButtonReleased;
++static PFNSI_SETUIMODE         pfnSiSetUiMode;
++static PFNSI_SETTYPEMASK       pfnSiSetypeMask;
++static PFNSI_GETDEVICEPORT     pfnSiGetDevicePort;
++static PFNSI_GETDRIVERINFO     pfnSiGetDriverInfo;
++static PFNSI_GETLIBRARYINFO    pfnSiGetLibraryInfo;
++static PFNSI_GETDEVICEINFO     pfnSiGetDeviceInfo;
++static PFNSPW_ERRORSTRING      pfnSpwErrorString;
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++/* externally used functions */
++int SiGetPortList (SiDevPort **ppPort);
++void SiFreePortList (SiDevPort *pPort);
++void SiTune2003 (SiSpwEvent *pEvent);
++void SiTuneSC (SiSpwEvent *pEvent);
++
++enum SpwRetVal SiInitialize(void);
++void           SiTerminate(void);
++int            SiGetNumDevices (void);
++SiDevID        SiDeviceIndex (int idx);
++int            SiDispatch (SiHdl hdl, SiGetEventData *pData,
++                           SiSpwEvent *pEvent, SiSpwHandlers *pDHandlers);
++void           SiOpenWinInit (SiOpenData *pData, HWND hWnd);
++SiHdl          SiOpen (char *pAppName, SiDevID devID, SiTypeMask *pTMask, int mode, 
++                       SiOpenData *pData);
++enum SpwRetVal SiClose (SiHdl hdl);
++void           SiGetEventWinInit (SiGetEventData *pData,
++                                  UINT msg, WPARAM wParam, LPARAM lParam);
++enum SpwRetVal SiGetEvent (SiHdl hdl, int flags, SiGetEventData *pData, 
++                           SiSpwEvent *pEvent);
++enum SpwRetVal SiBeep (SiHdl hdl, char *string);
++enum SpwRetVal SiRezero (SiHdl hdl);
++enum SpwRetVal SiGrabDevice (SiHdl hdl, SPWbool exclusive);
++enum SpwRetVal SiReleaseDevice (SiHdl hdl);
++int            SiButtonPressed (SiSpwEvent *pEvent);
++int            SiButtonReleased (SiSpwEvent *pEvent);
++enum SpwRetVal SiSetUiMode (SiHdl hdl, SPWuint32 mode);
++enum SpwRetVal SiSetTypeMask (SiTypeMask *pTMask, int type1, ...);
++enum           SpwRetVal SiGetDevicePort (SiDevID devID, SiDevPort *pPort);
++enum           SpwRetVal SiGetDriverInfo (SiVerInfo *pInfo);
++void           SiGetLibraryInfo (SiVerInfo *pInfo);
++enum           SpwRetVal SiGetDeviceInfo (SiHdl hdl, SiDevInfo *pInfo);
++char * SpwErrorString (enum SpwRetVal val);
++
++#ifdef __cplusplus
++}
++#endif
++
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++  
++int SPW_CheckForSpaceballWin32(void * win);
++int SPW_TranslateEventWin32(MSG * msg, SPW_InputEvent * sbEvent);
++void SPW_disableSpaceBallWin32(void);
++int SPW_SpaceBallExistsWin32(void);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* #ifndef SIAPP_H */
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/spwinput_x11.cpp.in
+@@ -0,0 +1,1982 @@
++/* @configure_input@ */
++
++/*-----------------------------------------------------------------------------
++ *
++ * (C) 1998 Spacetec IMC Corporation ("Spacetec").
++ *
++ * Permission to use, copy, modify, and distribute this software for all
++ * purposes and without fees is hereby granted provided that this copyright
++ * notice appears in all copies. Permission to modify this software is granted
++ * and Spacetec will support such modifications only if said modifications are
++ * approved by Spacetec.
++ *
++ */
++
++/* Some code cleanup by the Coin team. Also added configure tests for
++ * header files and added two methods:
++ *
++ * int SPW_CheckForSpaceballX11(void * display, int winid, char * product);
++ * int SPW_TranslateEventX11(void * display, void * xevent, SPW_InputEvent * sbEvent);
++ */
++
++/* FIXME: isn't this really "pure" C code? If so, don't use a C++
++   suffix on the file -- so we don't get tempted to pollute
++   it. 20010821 mortene. */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif /* HAVE_CONFIG_H */
++
++#if SO at GUI@_DEBUG && 0 // debug
++#define SPW_DEBUG 1
++#endif // debug
++
++#include "spwinput.h"
++
++/* The setting of this define needs to be added manually to
++   configure.in for all relevant projects. */
++#ifndef HAVE_X11_AVAILABLE
++
++/* just provide empty methods if X is not available */
++int 
++SPW_CheckForSpaceballX11(void *, int, char *)
++{
++  return 0;
++}
++
++int 
++SPW_TranslateEventX11(void *, void *, SPW_InputEvent *)
++{
++  return 0;
++}
++
++#else /* HAVE_X11_AVAILABLE */
++
++#include <ctype.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <time.h>
++
++#ifdef HAVE_UNISTD_H
++#include <unistd.h>
++#endif // HAVE_UNISTD_H
++#ifdef HAVE_NETINET_IN_H
++#include <netinet/in.h>
++#endif /* HAVE_NETINET_IN_H */
++#ifdef HAVE_SYS_TIME_H
++#include <sys/time.h>
++#endif /* HAVE_SYS_TIME_H */
++#ifdef HAVE_SYS_TYPES_H
++#include <sys/types.h>
++#endif /* HAVE_SYS_TYPES_H */
++#ifdef HAVE_SELECT_H
++#include <select.h>
++#endif /* HAVE_SELECT_H */
++
++#define XLIB_ILLEGAL_ACCESS
++#include <X11/Xlib.h>
++#include <X11/Xutil.h>
++
++#ifdef HAVE_X11_EXTENSIONS_SGIMISC_H
++#include <X11/extensions/SGIMisc.h>
++#elif HAVE_X11_XPROTO_H
++#include <X11/Xproto.h>
++#endif /* HAVE_X11_XPROTO */
++
++
++#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
++#include <X11/extensions/XInput.h>
++#endif /* HAVE_X11_EXTENSIONS_XINPUT_H */
++
++
++/* Callbacks for handling motion and button events */
++typedef void (*SPW_InputMotionEventHandler)(Display *,float *,void *);
++typedef void (*SPW_InputButtonEventHandler)(Display *,int,void *);
++typedef int  (*SPW_InputOtherEventHandler)(Display *,XEvent *,void *);
++
++/* Dispatch structure for SPW_InputDispatch */
++typedef struct {
++  Display                    * display;
++  XEvent                     * xevent;
++  SPW_InputEvent             * spwevent;
++  int                         delay;
++  SPW_InputMotionEventHandler handle_motion;
++  SPW_InputButtonEventHandler handle_bpress;
++  SPW_InputButtonEventHandler handle_brelease;
++  SPW_InputOtherEventHandler  handle_other;
++  void                       * pMotionAppData;
++  void                       * pButtonAppData;
++  void                       * pOtherAppData;
++} SPW_InputDispatchStruct;
++
++/* ------------------------------------------------------------------------ */
++
++static int SPW_InputCheckForSpaceball(Display *, Window, char *);
++static int SPW_InputIsSpaceballEvent (Display *, XEvent *, 
++                                          SPW_InputEvent *);
++static int SPW_InputXPending (Display *, int);
++static void SPW_InputInitDispatchStruct (SPW_InputDispatchStruct *);
++static int SPW_InputDispatch (SPW_InputDispatchStruct *);
++static int SPW_InputDispatchEx (SPW_InputDispatchStruct *);
++
++static void SPW_InputBeep (Display *, char *);
++static void SPW_InputRezero (Display *);
++static int SPW_GrabDevice(Display *display, Window window,
++                                 int exclusive);
++static int SPW_ReleaseDevice(Display * display);
++
++#define SPW_InputDefaultDelay       0 /* 0 Hz update */
++
++/*
++  Wrapper function which makes it possible to avoid including X11 in the 
++  header file.
++*/
++int 
++SPW_CheckForSpaceballX11(void * display, int winid, char * product)
++{
++  return SPW_InputCheckForSpaceball((Display*) display, (Window) winid, product);
++}
++
++/*
++  If xevent is a spaceball event, translates xevent to sbEvent and return 1.
++  If xevent is not a spaceball event returns 0. void * pointers are 
++  passed to avoid including the X header files in the spwinput.h header file.
++*/
++int
++SPW_TranslateEventX11(void * display, void * xevent, SPW_InputEvent * sbEvent)
++{
++  return SPW_InputIsSpaceballEvent((Display*) display, (XEvent*) xevent, sbEvent);
++}
++
++/*
++ *  This is the number of events before we stop asking the
++ *  driver for handshaking information.
++ *
++ *  25 events/sec * 60 sec * 1 min = 1500  
++ */
++#define SPW_MaxEventCount 1500
++
++/* these are all the Spaceball XCM atom names */
++#define SPW_InputMotionAtomName           "SpaceballMotionEventType"
++#define SPW_InputButtonPressAtomName      "SpaceballButtonPressEventType"
++#define SPW_InputButtonReleaseAtomName    "SpaceballButtonReleaseEventType"
++#define SPW_InputPassThruAtomName         "SpaceWarePassThruCommandEventType"
++
++/* found the spaceball */
++static int SpaceballFound = 0;
++
++/* the spaceball is using XIE */
++static int SpaceballInputExtension = 0;
++
++/* the spaceball is using XCM */
++static int SpaceWareAtomsDefined = 0;
++
++/* the magic XCM window used for communication */
++static Window SpaceWareXCMWindowID = 0;
++
++/* the window ID that the spaceball data is sent to */
++static Window ReturnWindowID = 0;
++
++/* XSendEvent uses these types and Atoms to communicate with the driver */
++static int SPW_DevMotionEventType;         /* Spaceball motion type */
++static int SPW_DevButtonPressEventType;    /* Spaceball button press type */
++static int SPW_DevButtonReleaseEventType;  /* Spaceball button release type */
++static Atom SPW_InputMotionAtom;           /* Spaceball motion Atom */
++static Atom SPW_InputButtonPressAtom;      /* Spaceball button press Atom */
++static Atom SPW_InputButtonReleaseAtom;    /* Spaceball button release Atom */
++static Atom SPW_InputPassThruAtom;  /* Main daemon communication Atom */
++
++static Atom WM_SAVE_YOURSELF;               /* Atoms daemon will use */
++
++#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
++
++static XID SpaceballDevID = 0;                 /* XIE ID for the Spaceball device */
++static XDevice *pSpaceballDev = NULL;          /* The spaceball XIE structure */
++static XEventClass SPW_SpaceballEventClass[3]; /* XIE Events classes          */
++
++#endif /* HAVE_X11_EXTENSIONS_XINPUT_H */
++
++
++static char strData[19];      /* buffer used to store the string that 
++                                 is to be sent to XCM daemon  */ 
++static int SPW_strLength = 0; /* length of the strData string */
++
++
++/*-----------------------------------------------------------------------------
++ *
++ * static Window FindXCMWindow (Display *display)
++ *
++ * Args:
++ *    display     (r/o)  The display on which to search for the XCM window
++ *
++ * Return Value:
++ *    The window ID of the XCM window.
++ *
++ * Description:
++ *     Finds the window named "sballd_XCM" and returns it's window ID
++ *
++ * Notes:
++ *     None.
++ *
++ *---------------------------------------------------------------------------*/
++static Window 
++FindXCMWindow (Display *display)
++{
++  Window root;      /* the root window for the display */
++  Window parent;    /* parent window in the search tree */
++  Window *children;  /* children windows of the parrent window */
++  unsigned int  nChildren; /* number of children the parent window has */
++  int i;         /* counter */
++
++  /* if we already have the daemon window don't look again */
++  if (SpaceWareXCMWindowID != 0) {
++    return SpaceWareXCMWindowID;
++  }
++
++  XQueryTree(display, RootWindowOfScreen(DefaultScreenOfDisplay(display)),
++             &root, &parent, &children, &nChildren);
++
++  for (i = 0;  i < (int) nChildren; i++){
++    char *name;
++    int found = 0;
++
++    XFetchName (display, children[i], &name);
++    if (name) {
++#ifdef SPW_DEBUG
++      fprintf(stderr,"FindXCMWindow: %s\n", name);
++#endif
++      if (strcmp(name, "sballd_XCM") == 0) {
++        found = 1;
++      }
++      XFree(name);
++    }
++     
++    if (found == 1) {
++      break;
++    }
++  }
++   
++  if (i == (int)nChildren) {
++    SpaceWareXCMWindowID = 0;
++  }
++  else {
++    SpaceWareXCMWindowID = children[i];
++  }
++   
++  XFree((char *) children);
++   
++  if (SpaceWareXCMWindowID == 0)  {
++    return False;
++  }
++  else  {
++    return SpaceWareXCMWindowID;
++  }
++} /* end of FindXCMWindow */
++
++
++/*-----------------------------------------------------------------------------
++ *
++ * static void StringFlush (Display *display, Window win)
++ *
++ * Args:
++ *    display (r/o)  The X Display of which the XCM window is a resident
++ *    win     (r/o)  The window that the XCM daemon replies to
++ *
++ * Return Value:
++ *    None.
++ *
++ * Description:
++ *    This function sends the string that is in the strData buffer to the
++ *    XCM window.  Once it is send it clears the strData buffer.
++ *
++ * Notes:
++ *    None.
++ *
++ *---------------------------------------------------------------------------*/
++static void StringFlush (Display *display, Window win)
++{
++  XClientMessageEvent event; /* event used to send string to XCM daemon */
++  int i;                     /* counter used to step through the string */
++   
++  /* if we don't already have the XCM window id find it */
++  if (SpaceWareXCMWindowID == 0) {
++    FindXCMWindow (display);
++  }
++  if (SpaceWareXCMWindowID == 0) {
++    return;
++  }
++
++  if (SPW_strLength == 0) { /* if the string is empty do nothing */
++    return;
++  }
++   
++  /* set up the event structure for sending */
++  event.type = ClientMessage;
++  event.display = display;
++  event.window = SpaceWareXCMWindowID;
++  event.message_type = SPW_InputPassThruAtom;
++  event.format = 8;
++ 
++  /* copy the string into the event */ 
++  for (i = 0; i < 15; i++) {
++    event.data.b[i] = strData[i];
++  }
++  if (SPW_strLength > 15) {
++    SPW_strLength = 15;
++  }
++   
++  /* force zero on end of data */
++  event.data.b[SPW_strLength] = 0;
++
++  event.data.l[4] = (long)htonl(win);
++  
++#ifdef SPW_DEBUG
++  fprintf (stderr,"StringFlush %s\n", event.data.b);
++#endif
++
++  /* send the string to the XCM daemon */
++  if (XSendEvent (display, SpaceWareXCMWindowID, True, 0,
++                  (XEvent *)&event) == 0) {
++#ifdef SPW_DEBUG
++    fprintf (stderr, "SPW_Input: XSendEvent failed!\n");
++#endif
++  }
++  XSync (display,False);
++   
++  /* clear the buffer */
++  SPW_strLength = 0;
++} /* end of StringFlush */
++
++/*-----------------------------------------------------------------------------
++ *
++ * static void SendString (Display *display, char *string)
++ *
++ * Args:
++ *    display (r/o)  The X Display of which the XCM window is a resident
++ *    string  (r/o)  The string that is sent to the XCM daemon
++ *
++ * Return Value:
++ *    None.
++ *
++ * Description:
++ *    This function sends string to the XCM window and flushs the
++ *    internal buffer.
++ *
++ * Notes:
++ *    To flush the string call StringFlush.
++ *
++ *---------------------------------------------------------------------------*/
++static void SendString (Display *display, char *string)
++{
++  int i; /* counter used to step through the string */
++  
++  /* copy the string into strData and send strData to the XCM driver */
++  for (i = 0; i < (int) strlen (string); i++) {
++    strData[SPW_strLength++] = string[i];
++  }
++  StringFlush (display, ReturnWindowID);
++} /* end of String */
++
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SPW_InputString (Display *display, char *string)
++ *
++ * Args:
++ *    display (r/o)  The X Display of which the XCM window is a resident
++ *    string  (r/o)  The string that is sent to the XCM daemon
++ *
++ * Return Value:
++ *    None.
++ *
++ * Description:
++ *    This function sends string to the XCM window using SendString.
++ *
++ * Notes:
++ *    None.
++ *
++ *---------------------------------------------------------------------------*/
++
++void SPW_InputString (Display *display, char *string)
++{
++  SPW_strLength = 0;                     /* flush the internal buffer */
++  SendString (display, string);          /* setup the string for sending */
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SPW_InputResetGlobalVars (void)
++ *
++ * Args:
++ *    None.
++ *
++ * Return Value:
++ *    None.
++ *
++ * Description:
++ *    This function resets all the static global variable used in the Spaceball
++ *    input function.
++ *
++ * Notes:
++ *    None.
++ *
++ *---------------------------------------------------------------------------*/
++void SPW_InputResetGlobalVars (void)
++{
++  SpaceballFound = 0;
++  SpaceballInputExtension = 0;
++  SpaceWareAtomsDefined = 0;
++  SpaceWareXCMWindowID = 0;
++} /* end of SPW_InputResetGlobalVars */
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SPW_InputResetSpaceball (Display *display)
++ *
++ * Args:
++ *    display (r/o)  The X Display of which the XCM window is a resident
++ *
++ * Return Value:
++ *    None.
++ *
++ * Description:
++ *    This function resets the Spaceball attached to the display defined in
++ *    the display variable. The daemon will reset all internal Spaceball
++ *    variables to their default and rezeros the Spaceball itself.
++ *
++ * Notes:
++ *    None.
++ *
++ *---------------------------------------------------------------------------*/
++void SPW_InputResetSpaceball (Display *display)
++{
++  SPW_strLength = 0;
++  static char RESET[] = "RESET";
++  SendString (display, RESET);
++} /* end of SPW_InputResetSpaceball */
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SPW_InputCloseXIE (Display *display)
++ *
++ * Args:
++ *    display (r/o)  The X Display to which the Spaceball is attached
++ *
++ * Return Value:
++ *    None.
++ *
++ * Description:
++ *    This function closes all comunication with the Spaceball XIE driver.
++ *
++ * Notes:
++ *    When the XIE driver is closed the Spaceball may lose power.
++ *
++ *---------------------------------------------------------------------------*/
++void SPW_InputCloseXIE (Display *display)
++{
++#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
++  if (SpaceballInputExtension == 1) {
++    XCloseDevice (display, pSpaceballDev);
++    
++    SpaceballInputExtension = 0;
++    SpaceballFound = 0;
++  }
++#endif
++} /* end of SPW_InputCloseXIE */
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SPW_InputIsXIE (void)
++ *
++ * Args:
++ *    None.
++ *
++ * Return Value:
++ *    0 if XIE is disabled or 1 if it is enabled.
++ *
++ * Description:
++ *    This function determines if the Spaceball XIE driver is enabled.
++ *
++ * Notes:
++ *    This is exported from this library so users of this library
++ *    can determine the method of communication used.
++ *
++ *---------------------------------------------------------------------------*/
++int SPW_InputIsXIE (void)
++{
++  return SpaceballInputExtension;
++} /* end of SPW_InputIsXIE */
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SPW_InputIsXCM (void)
++ *
++ * Args:
++ *    None.
++ *
++ * Return Value:
++ *    0 if XCM is disabled or 1 if it is enabled.
++ *
++ * Description:
++ *    This function determines f the Spaceball XCM driver is enabled.
++ *
++ * Notes:
++ *    This is exported from this library so users of this library
++ *    can determine the method of communication used.
++ *
++ *---------------------------------------------------------------------------*/
++int SPW_InputIsXCM (void)
++{
++  return SpaceWareAtomsDefined;
++} /* end of SPW_InputIsXCM */
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SPW_InputSelectExtensionEvent (Display *display, Window window)
++ *
++ * Args:
++ *    display (r/o)  The X Display to which the Spaceball is attached
++ *    window  (r/o)  What window to check for extension events
++ *
++ * Return Value:
++ *    None.
++ *
++ * Description:
++ *    Check to see if the Spaceball XInput Extension is enabled.
++ *
++ * Notes:
++ *    None.
++ *
++ *---------------------------------------------------------------------------*/
++void SPW_InputSelectExtensionEvent (Display *display, Window window)
++{
++
++#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
++  XSelectExtensionEvent (display, window, SPW_SpaceballEventClass, 3);
++#endif
++
++} /* end of SPW_InputSelectExtensionEvent */
++
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SPW_SendHandshake(Display *display)
++ *
++ * Args:
++ *    display     (r/o)  The display on which to send the message
++ *
++ * Return Value:
++ *    None
++ *
++ * Description:
++ *    Sends a handshaking packet to the Xdaemon with what version of
++ *    the software we are running.  Eventually we may even use this
++ *    information.  Right now it's mainly to make sure that the soft
++ *    button window gets the correct cache values.
++ *
++ * Notes:
++ *    This function returns nothing, but sends a message to the Xdaemon.
++ *    The message is sent to guaranty the daemon gets the window id
++ *    of the application.
++ *
++ *---------------------------------------------------------------------------*/
++void SPW_SendHandshake (Display *display)
++{
++  static char pHandshake[20]; /* store some space */
++   
++  if (SpaceWareXCMWindowID != 0) /* using daemon */
++    {
++      SPW_strLength = 0;
++      pHandshake[0] = '\0';
++      strcat (pHandshake, "~~SLIM V");
++      strcat (pHandshake, SPW_INPUT_VERSION);
++      strcat (pHandshake, "\r");
++
++      SendString (display, pHandshake);
++    } 
++} /* end of SPW_SendHandshake */
++
++
++/*-----------------------------------------------------------------------------
++ *
++ *  int SPW_GrabDevice(Display *display, Window window, int exclusive)
++ *
++ * Args:
++ *    display     (r/o) The current display pointer
++ *    window      (r/o) The window to send to
++ *    exclusive   (r/o) Specify if the grab is exclusive
++ *
++ * Return Value:
++ *    None
++ *
++ * Description:
++ *    This function is used to signal the driver that the application wishes
++ *    to "grab" the Spaceball device.  This prevents other applications from
++ *    getting data from the device.  There are two possible grab modes: An
++ *    exclusive grab forces the driver to send data to the application window
++ *    regardless of what window has focus.  A non-exclusive grab forces the
++ *    driver to send Spaceball data to the application window when no other
++ *    Spaceball enabled window has focus.
++ *
++ * Notes:
++ *    This function does not work with XIE.
++ *    It is recommended that exclusive grab not be used.
++ *    This function will change the ReturnWindowID if the window parameter
++ *    is not NULL.
++ *
++ *---------------------------------------------------------------------------*/
++int SPW_GrabDevice(Display *display, Window window,
++                      int exclusive)
++{
++  if (window != 0) {
++      ReturnWindowID = window;
++  }
++
++  if ((ReturnWindowID == 0) ||  /* return window not set */
++      (SpaceWareXCMWindowID == 0)) {/* daemon not running */
++    return 0;
++  }
++
++  SPW_strLength = 0;
++
++  if (exclusive == 1)
++    {
++      static char hard[] = "~hard";
++      SendString (display, hard);
++    }
++  else
++    {
++      static char soft[] = "~soft";
++      SendString (display, soft);
++    }
++
++  return 1;
++} /* end of SPW_GrabDevice */
++
++
++/*-----------------------------------------------------------------------------
++ *
++ *  void SPW_ReleaseDevice(Display *display)
++ *
++ * Args:
++ *    display     (r/o) The current display pointer
++ *
++ * Return Value:
++ *    None
++ *
++ * Description:
++ *    This function is used to release a grabbed device.  This frees the
++ *    driver to send data to the application with focus regardless if it has
++ *    been Spaceball enabled.
++ *
++ * Notes:
++ *    This function does not work with XIE.
++ *
++ *---------------------------------------------------------------------------*/
++int SPW_ReleaseDevice(Display *display)
++{
++  if ((ReturnWindowID == 0) ||  /* return window not set */
++      (SpaceWareXCMWindowID == 0)) /* daemon not running */
++    {
++      return 0;
++    }
++
++  SPW_strLength = 0;
++  static char relgrab[] = "~relgrab";
++  SendString (display, relgrab); 
++  return 1;
++} /* end of SPW_ReleaseDevice */
++
++
++/*-----------------------------------------------------------------------------
++ *
++ * static int FindXCMAtoms (Display *display)
++ *
++ * Args:
++ *    display     (r/o)  The display on which to search for the XCM atoms
++ *
++ * Return Value:
++ *    1 if the XCM atoms were found, 0 if not.
++ *
++ * Description:
++ *     Returns True if all the XCM atoms are found.
++ *
++ * Notes:
++ *      Has the side effect of looking up the atoms and putting the
++ *      values in the SPW_Input...Atom variables
++ *
++ *---------------------------------------------------------------------------*/
++static int FindXCMAtoms (Display *display)
++{
++  /* if we already have the atoms don't look again */
++  if (SpaceWareAtomsDefined == 1)
++    {
++      return 1;
++    }
++
++  /* 
++    *  Try to find the atoms; if X does not find the atoms it will try to 
++    *  create them.
++    */
++  SPW_InputMotionAtom = XInternAtom(display, SPW_InputMotionAtomName, True);
++  SPW_InputButtonPressAtom = XInternAtom(display, SPW_InputButtonPressAtomName,
++                                         True);
++  SPW_InputButtonReleaseAtom = XInternAtom(display, 
++                                           SPW_InputButtonReleaseAtomName,True);
++
++  SPW_InputPassThruAtom = XInternAtom(display,
++                                      SPW_InputPassThruAtomName, True);
++
++#ifdef SPW_DEBUG
++  fprintf(stderr,"SPW_InputMotionAtom %d\n", SPW_InputMotionAtom);
++  fprintf(stderr,"SPW_InputButtonPressAtom %d\n", SPW_InputButtonPressAtom);
++  fprintf(stderr,"SPW_InputButtonReleaseAtom %d\n",SPW_InputButtonReleaseAtom);
++  fprintf(stderr,"SPW_InputPassThruAtom %d\n", SPW_InputPassThruAtom);
++#endif
++
++  /* if any one of the atoms does not exist return a failure */
++  if ((SPW_InputMotionAtom == None) ||
++      (SPW_InputButtonPressAtom == None) ||
++      (SPW_InputButtonReleaseAtom == None) ||
++      (SPW_InputPassThruAtom == None))
++    {
++      return 0;
++    }
++
++  /* set the global that tells us the atoms are defined and found */
++  SpaceWareAtomsDefined = 1;
++  return 1;
++} /* end of FindXCMAtoms */
++
++/*-----------------------------------------------------------------------------
++ *
++ * static int FindXCM (Display *display)
++ *
++ * Args:
++ *    display      (r/o)  The display on which to search for the XCM window
++ *
++ * Return Value:
++ *     Returns 1 if the XCM driver is found, 0 if not.
++ *
++ * Description:
++ *     Find the XCM driver (window and atoms).  This function is used
++ *     to check if the driver is running because if the atoms exist
++ *     then the driver is running. 
++ *
++ * Notes:
++ *     None.
++ *
++ *---------------------------------------------------------------------------*/
++static int FindXCM (Display *display)
++{
++  unsigned long win;   /* the XCM window */
++  int atom;  /* boolean that tell us if we found the atoms */
++  
++  win = FindXCMWindow (display);
++  atom = FindXCMAtoms (display);
++
++#ifdef SPW_DEBUG
++  fprintf(stderr, "win %d atom %d\n", win, atom);
++#endif
++
++  if ((win != 0) && (atom == 1)) {
++      return 1;
++  }
++  
++  return 0;
++} /* end of FindXCM */
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SPW_FindXIE (Display *display)
++ *
++ * Args:
++ *    display      (r/o)  The display on which to search for the XCM window
++ *
++ * Return Value:
++ *     1 if the XIE driver was found, 0 if not.
++ *
++ * Description:
++ *     Find the XIE Spaceball extension.
++ *
++ * Notes:
++ *     None.
++ *
++ *---------------------------------------------------------------------------*/
++
++int SPW_FindXIE (Display *display)
++{
++#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
++  int          ieMajor;      
++  int          ieFirstEvent; 
++  int          ieFirstError; 
++  int          nDev;         
++  XDeviceInfo *pDev;         
++  int          i,j;          
++  char        *ptr;          
++
++  /* if we have already found the XIE driver don't look again */
++  if (SpaceballInputExtension == 1)
++    {
++      return 1;
++    }
++
++  /* See if XIE is configured */
++  if (XQueryExtension (display, "XInputExtension", &ieMajor,
++                       &ieFirstEvent, &ieFirstError) == 0)
++    {
++      return 0;
++    }
++
++#ifdef SPW_DEBUG
++  fprintf (stderr, "SPW_FindXIE()  Extension found\n");
++#endif
++
++  /* get a list of available XIE devices */
++  pDev = XListInputDevices (display, &nDev);
++
++  /* Make sure there are valid devices */
++  if (pDev == 0) {
++      return 0;
++  }
++
++  /* Try to find the Spaceball device in the list */
++  for (i = 0; i < nDev; i++) {
++#ifdef SPW_DEBUG
++    fprintf (stderr, "SPW_FindXIE()  device %s\n", pDev[i].name);
++#endif
++    /* Compare against type name per device */
++    if (strcmp(pDev[i].name, XI_SPACEBALL) == 0) break;
++  }
++
++  /*
++   * if we have gone past the end of the list then no Spaceball XIE
++   * driver was found
++   */
++  if (i == nDev) {
++    XFreeDeviceList (pDev);
++    return 0;
++  }
++  
++  /* record all necessary info on the Spaceball XIE driver */
++  SpaceballDevID = pDev[i].id;
++  pSpaceballDev = XOpenDevice (display, SpaceballDevID);
++  
++  /* clean up the device list */ 
++  XFreeDeviceList (pDev);
++
++  /* enable the Spaceball callbacks */
++  DeviceMotionNotify (pSpaceballDev, SPW_DevMotionEventType, 
++                      SPW_SpaceballEventClass[0]);
++  DeviceButtonPress (pSpaceballDev, SPW_DevButtonPressEventType, 
++                     SPW_SpaceballEventClass[1]);
++  DeviceButtonRelease (pSpaceballDev, SPW_DevButtonReleaseEventType, 
++                       SPW_SpaceballEventClass[2]);
++  SpaceballInputExtension = 1;
++
++  return 1;
++#else 
++  return 0;
++#endif /* HAVE_X11_EXTENSIONS_XINPUT_H */
++} /* end of SPW_FindXIE */
++
++/*-----------------------------------------------------------------------------
++ *
++ * static void InitializeSpaceball (Display *display, char *version)
++ *
++ * Args:
++ *    display      (r/o)  The display on which to search for the XCM window
++ *    version      (r/o)  the XCM driver version.
++ *
++ * Return Value:
++ *     None.
++ *
++ * Description:
++ *     Find the Spaceball via XIE or XCM.
++ *
++ * Notes:
++ *     The returnWindow parameter is not set if the Spaceball is configured
++ *     using XIE.
++ *
++ *---------------------------------------------------------------------------*/
++static void InitializeSpaceball (Display *display, char *version)
++{
++  /* if we already found the Spaceball don't search again */
++  if (SpaceballFound == 1) {
++    return;
++  }
++
++  /* Create some more Atoms the Daemon uses  */
++  (void)XInternAtom (display, "WM_PROTOCOLS", False);
++  (void)XInternAtom (display, "WM_DELETE_WINDOW", False);
++
++   /* search for the XIE driver first */
++  if (SPW_FindXIE (display) == 1) {
++    SpaceballFound = 1;
++#ifdef SPW_DEBUG
++    fprintf(stderr, "\n");
++    fprintf(stderr, "Spaceball (R) device found,");
++    fprintf(stderr, " using SpaceWare (R) XIE interface.\n");
++    fprintf(stderr, "SpaceWare Version %s\n", version);
++    fprintf(stderr, "Copyright (c) 1998 Spacetec IMC Corporation\n");
++    fprintf(stderr, "All Rights Reserved\n");
++#endif
++  }  
++  /* if we don't find the XIE driver search for the XCM driver */
++  else if (FindXCM (display) == 1) {
++    SpaceballFound = 1;
++#ifdef SPW_DEBUG
++    fprintf(stderr, "\n");
++    fprintf(stderr, "Spaceball (R) device found,");
++    fprintf(stderr, " using SpaceWare (R) XCM interface.\n");
++    fprintf(stderr, "SpaceWare Version %s\n", version);
++    fprintf(stderr, "Copyright (c) 1998 Spacetec IMC Corporation\n");
++    fprintf(stderr, "All Rights Reserved\n");
++#endif
++  }  
++} /* end of InitializeSpaceball */
++
++
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SPW_InputCheckForSpaceball (Display *display, Window window,
++ *                                     char *product)
++ *
++ * Args:
++ *    display   (r/o)  The display on which to search for the XCM window
++ *    window    (r/o)  the window on the application side to send messages to.
++ *    product   (r/o)  name of the application that is opening the Spaceball.
++ *
++ * Return Value:
++ *     1 if the Spaceball was opened, 0 if not.
++ *
++ * Description:
++ *     Find the Spaceball via XIE or XCM.
++ *
++ * Notes:
++ *     The window parameter is not set if the Spaceball is configured
++ *     using XIE.
++ *
++ *---------------------------------------------------------------------------*/
++int SPW_InputCheckForSpaceball (Display *display, 
++                                   Window window,
++                                   char *product)
++{
++  char version[256]; /* The version of SpaceWare */
++  int productlen;    /* length of the product string */
++
++#ifdef SPW_DEBUG
++  fprintf(stderr, "SPW_InputCheckForSpaceball window 0x%x product %s\n",
++          window, product);
++#endif
++
++  /* check to make sure the corect parameters were passed */
++  if ((display == NULL) || (window == 0)) {
++      return 0;
++  }
++
++  /* build the SpaceWare version and product info string */
++  strcpy (version, SPW_INPUT_VERSION);
++  if (product != NULL) {
++    productlen = strlen (product);
++    if ((productlen > 0) && (productlen < 200)) {
++      strcat(version, ".");
++      strcat(version, product);
++    }
++  }
++
++  /* save off the application window for future reference */ 
++  if (ReturnWindowID == 0) {
++    ReturnWindowID = window;
++  }
++  
++  /* try to open the Spaceball */
++  InitializeSpaceball (display, version);
++  if (SpaceballFound == 0) {
++    return 0;
++  }
++
++#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
++
++  /* If we're using XIE, try to enable Spaceball events */
++
++  if (SPW_FindXIE (display) == 1) {
++    XSelectExtensionEvent (display, window, SPW_SpaceballEventClass, 3);
++  }
++#endif /* HAVE_X11_EXTENSIONS_XINPUT_H */
++
++  /* Send version info to the daemon */
++  SPW_SendHandshake (display);
++
++  /* we found the Spaceball so return a success message */
++  return 1;
++
++} /* end of SPW_InputCheckForSpaceball */
++
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SPW_InputIsSpaceballEvent (Display *display, XEvent *event, 
++ *                                SPW_InputEvent *spwev)
++ *
++ * Args:
++ *    display (r/o)  The display the Spaceball is attached to
++ *    event   (r/o)  The event that we want to check
++ *    spwev   (w/o)  The spaceball return structure contaning the spaceball data
++ *
++ * Return Value:
++ *     True if the event is a spaceball event, False if not.
++ *
++ * Description:
++ *     Determine if the event is a spaceball event and pack it into
++ *     the spwev_ret structure.
++ *
++ * Notes:
++ *     This function handles XCM as well as XIE events.
++ *
++ *---------------------------------------------------------------------------*/
++int SPW_InputIsSpaceballEvent (Display *display, XEvent *event, 
++                               SPW_InputEvent *spwev)
++{
++  static int shake_count = 0;     /* how many events have passed without */
++  /* the daemon sending us a handshake   */
++  static int last_shake = 0;      /* the last time we sent a handshake   */
++  static int shake_delay = 7;     /* number of events we wait before     */
++  /* sending another handshake message   */
++  int isSpaceball=0;
++  static int have_handshake = 0; /* did we get a handshake
++                                        from daemon? */
++  static int have_tune = 0; /* do we have the tune data yet */
++  static float sbtune[6];      /* the tune multipliers */
++  char *scaleVar;                   /* environment variable containg
++                                       tune data */
++  int  i;                           /* counter */
++
++  /* if the event, display or spwev variables are not allocated then return */
++  if ((display == NULL) || (event == NULL) || (spwev == NULL)) {
++    return 0;
++  }
++
++#ifdef SPW_DEBUG
++  fprintf(stderr,"SPW_InputIsSpaceballEvent type %d\n", event->type);
++#endif
++
++  /* the event is a spaceball event so deal with it */
++  if (event->type == ClientMessage) {
++    XClientMessageEvent *clientMessage = (XClientMessageEvent *) event;
++#ifdef SPW_DEBUG
++    fprintf(stderr,"   message_type %d\n", clientMessage->message_type);
++#endif
++
++    /* the event is a motion event */
++    if (clientMessage->message_type == SPW_InputMotionAtom) {
++      
++      /* specify we found a spaceball event */
++      isSpaceball = 1;
++
++      /* specify the spaceball event is a motion event */
++      spwev->type = SPW_InputMotionEvent;
++      
++      /* copy the spaceball data out of the event into the spwev structure */
++      for (i = 0; i < 7; i++) {
++        spwev->sData[i] = clientMessage->data.s[i + 2];
++        spwev->fData[i] = (float) ((int) clientMessage->data.s[i + 2]);
++      }
++    }
++      
++    /* if the event is a button press event process it */
++    else if (clientMessage->message_type == SPW_InputButtonPressAtom) {
++      /* specify we found a spaceball event */
++      isSpaceball = 1;
++      
++      /* specify the spaceball event is a button event */
++      spwev->type = SPW_InputButtonPressEvent;
++      
++      /* copy the spaceball data out of the event into the spwev structure */
++      spwev->buttonNumber = clientMessage->data.s[2];
++      
++    }
++    
++    /* if the event is a button release event process it */
++    else if (clientMessage->message_type == SPW_InputButtonReleaseAtom) {
++      /* specify we found a spaceball event */
++      isSpaceball = 1;
++      
++      /* specify the spaceball event is a button event */
++      spwev->type = SPW_InputButtonReleaseEvent;
++      
++      /* copy the spaceball data out of the event into the spwev structure */
++      spwev->buttonNumber = clientMessage->data.s[2];
++      
++    }
++    
++    /* the event is a pass through event */
++    else if (clientMessage->message_type == SPW_InputPassThruAtom) {
++      char *str = clientMessage->data.b; /* data in the passthrough event */
++      
++      /* check if the pass through event is handshaking from the daemon */
++      if ((str[0] == '~') && (str[1] == '~')) {
++        have_handshake = 1;
++      }
++    }
++    
++    /* if we did get a spaceball event save the window ID we got it from */
++    if (isSpaceball == 1) {
++      /* if we don't know what the XCM window is yet save it off */
++      if (SpaceWareXCMWindowID == 0) {
++        SpaceWareXCMWindowID = ntohl(clientMessage->data.l[0]);
++      }    
++    }
++  }  /* if (event->type == ClientMessage */
++
++#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
++  /* check to see if the event is a spaceball XIE motion event */
++  else if ((event->type == SPW_DevMotionEventType) &&
++           (((XDeviceMotionEvent *)event)->deviceid == SpaceballDevID)) {
++    /* cast the event to a XIE event */
++    XDeviceMotionEvent *motion = (XDeviceMotionEvent *)event;
++    int i;                                     /* Counter loop index */
++    static float sbData[7];                    /* the spaceball data */
++
++    /*
++     * There is not enough room in an SGI X Input Extension event for all
++     * 7 motion values (6 DOF data + period) the Spaceball produces.
++     * Therefore, when we implement the Spaceball XIE we say it has
++     * 7 axes and we send them in two separate XIE events.  The
++     * period, axis 6, is sent alone in the first event; the 6 dof data
++     * are sent in the next event.  First_axis and axes_count are set
++     * correctly so the client code can figure out when it has a
++     * complete event.
++     *
++     * This function returns 1 to indicate it was a Spaceball event.
++     * In other words, it was not some other type of event the application
++     * should handle.  BUT the spwev.type is set to 0 if it is not a
++     * complete Spaceball motion event.  This should cause the switch
++     * statement that is suppose to follow a call to this function to
++     * ignore the event.
++     */
++    
++    /* specify we found a spaceball event */
++    isSpaceball = 1;
++    
++    /* specify the event is a motion event */
++    spwev->type = SPW_InputMotionEvent;
++    
++    /* extract the spaceball motion data from the event */
++    for (i = 0; i < (int) (motion->axes_count); i++) {
++      sbData[motion->first_axis+i] = motion->axis_data[i];
++    }
++    
++    /* the first axis will always be one, so this will work */
++    if (motion->first_axis != 6) {
++      for (i = 0; i < 7; i++) {
++        spwev->fData[i] = sbData[i];
++        spwev->sData[i] = (short)((int)sbData[i]);
++      }
++    }
++    else {
++      /* Only the period has been received, ignore event */
++      spwev->type = 0;
++    }
++  }
++  
++  /* check to see if the event is a spaceball XIE button press event */
++  else if ((event->type == SPW_DevButtonPressEventType) &&
++           (((XDeviceButtonEvent *)event)->deviceid == SpaceballDevID)) {
++    /* cast the event to a XIE event */
++    XDeviceButtonEvent *button = (XDeviceButtonEvent *) event;  
++    
++    /* specify we found a spaceball message */
++    isSpaceball = 1;
++    
++    /* specify the message was a button press event */
++    spwev->type = SPW_InputButtonPressEvent;
++    
++    /* copy the button data out of the event */
++    spwev->buttonNumber = button->button;
++    
++  }
++  
++  /* check to see if the event is a spaceball XIE button release event */
++  else if ((event->type==SPW_DevButtonReleaseEventType) &&
++           (((XDeviceButtonEvent *)event)->deviceid == SpaceballDevID)) {
++    /* cast the event to a XIE event */
++    XDeviceButtonEvent *button = (XDeviceButtonEvent *) event;  
++      
++    /* specify we found a spaceball message */
++    isSpaceball = 1;
++    
++    /* specify the message was a button press event */
++    spwev->type = SPW_InputButtonReleaseEvent;
++    
++    /* specify the message was a button release event */
++    spwev->buttonNumber = button->button;
++    
++  }
++#endif /* HAVE_X11_EXTENSIONS_XINPUT_H */
++  
++  /*
++   * if after all that we haven't determined the event to be a spaceball
++   * event return a failure
++   */
++  if (isSpaceball == 0) {
++    return 0;
++  }
++  
++  /*
++   *   If we haven't gotten a handshake packet from the daemon
++   *   and it's still early in the process try again, otherwise
++   *   say the daemon must be earlier than 7.0.  Basically we'll
++   *   have sent out SPW_MaxEventCount/shake_delay handshake messages to the
++   *   daemon without a response.
++   */
++  if ((have_handshake == 0) && (shake_count < SPW_MaxEventCount)) {
++    if ((last_shake + shake_delay) == shake_count) {
++      SPW_SendHandshake (display);
++      last_shake = shake_count;
++    }
++    shake_count++;
++  }
++  
++  /*  
++   *  Tuning:  we want to have the option to tune an application without
++   *  having to recompile it each time.  We will do this by setting the
++   *  SBALL_TUNING variable and scaling the data by it.  This should only
++   *  be used to get the constants to acutally put into the application.
++   */
++
++  if (spwev->type == SPW_InputMotionEvent) {
++    if (have_tune == 0) {
++      scaleVar = getenv("SBALL_TUNING");
++      if (scaleVar != NULL) {
++        sscanf(scaleVar, "%f %f %f %f %f %f", &sbtune[0],
++               &sbtune[1],
++               &sbtune[2],
++                     &sbtune[3],
++               &sbtune[4],
++               &sbtune[5]);
++      }
++      else {          
++        sbtune[0] = 1.0f;
++        sbtune[1] = 1.0f;
++        sbtune[2] = 1.0f;
++        sbtune[3] = 1.0f;
++        sbtune[4] = 1.0f;
++        sbtune[5] = 1.0f;
++      }
++      have_tune = 1;
++    }
++
++    spwev->fData[0] *= sbtune[0];
++    spwev->fData[1] *= sbtune[1];
++    spwev->fData[2] *= sbtune[2];
++    spwev->fData[3] *= sbtune[3];
++    spwev->fData[4] *= sbtune[4];
++    spwev->fData[5] *= sbtune[5];
++    
++    spwev->sData[0] = (int)(spwev->sData[0] * sbtune[0]);
++    spwev->sData[1] = (int)(spwev->sData[1] * sbtune[1]);
++    spwev->sData[2] = (int)(spwev->sData[2] * sbtune[2]);
++    spwev->sData[3] = (int)(spwev->sData[3] * sbtune[3]);
++    spwev->sData[4] = (int)(spwev->sData[4] * sbtune[4]);
++    spwev->sData[5] = (int)(spwev->sData[5] * sbtune[5]);
++  }
++  
++  return 1;
++} /* end of SPW_InputIsSpaceballEvent */
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SPW_InputBeep (Display *display, char *string)
++ *
++ * Args:
++ *    display (r/o)  The X Display of which the XCM window is a resident
++ *    string  (r/o)  the Spaceball beep string
++ *
++ * Return Value:
++ *    None.
++ *
++ * Description:
++ *    This function send a string to the XCM driver that will cause
++ *    the spaceball to beep.  Each lower case character (a-z) results
++ *    in a tone, and each upper case character (A-Z) results in a pause
++ *    between tones.
++ *    Example: cCcC - cause the ball to beep twice.
++ *
++ * Notes:
++ *    None.
++ *
++ *---------------------------------------------------------------------------*/
++void SPW_InputBeep (Display *display, char *string)
++{
++  char sndStr[15];  /* the control string to be sent to the driver */
++
++#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
++  /* if we are connected via XIE use that to beep the ball */
++  if (SpaceballInputExtension == 1) {
++#ifdef HAVE_X11_EXTENSIONS_SGIMISC_H
++    /* SGI beep */
++    int slen = strlen (string);
++    static char buf[32];
++    char *cp = buf;
++    
++    if (slen > 29) slen = 29;
++    *cp++ = '\r';
++    *cp++ = 'B';
++    strcpy (cp, string);
++    cp  += slen;
++    *cp++ = '\r';
++    *cp  = NULL;
++    XSGIDeviceControl (display, (int)SpaceballDevID, "sbprivate", buf);
++    XFlush (display);
++    
++#elif HAVE_X11_XPROTO_H 
++    /* HP beep */
++    int i = 0;
++    int slen = strlen (string);
++    XBellFeedbackControl cntrl;
++
++#if defined(__cplusplus) || defined(c_plusplus)
++    cntrl.c_class = BellFeedbackClass;
++#else /* ! __cplusplus */
++    cntrl.class = BellFeedbackClass;
++#endif /* __cplusplus */
++    cntrl.pitch = 'B';
++    cntrl.percent = 0;
++    while (i < slen) {
++      cntrl.duration = (short) string[i++];
++      XChangeFeedbackControl(display, pSpaceballDev,
++                             DvPercent | DvPitch | DvDuration,
++                             (XFeedbackControl *)(void *)&cntrl);
++        }
++#endif /* HAVE_XCHANGEFEEDBACKCONTROL */
++    }
++#endif /* HAVE_X11_EXTENSIONS_XINPUT_H */
++
++  /* if we are not using XIE use XCM to communicate with the ball */
++  if (SpaceballInputExtension == 0) {
++    /* setup the string to be sent */
++    SPW_strLength = 0;
++    sndStr[0] = '\0';
++    strcat (sndStr, "B");
++    strcat (sndStr, string);
++    strcat (sndStr, "\r");
++    
++    /* send the string */
++    SendString (display, sndStr);
++  }
++} /* end of SPW_InputBeep */
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SPW_InputRezero (Display *display)
++ *
++ * Args:
++ *    display (r/o)  The X Display of which the XCM window is a resident
++ *
++ * Return Value:
++ *    None.
++ *
++ * Description:
++ *    This function causes the Spaceball to rezero at its current location.
++ *
++ * Notes:
++ *    None.
++ *
++ *---------------------------------------------------------------------------*/
++void SPW_InputRezero (Display *display)
++{
++#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
++  /* if we are connected via XIE use that to rezero the ball */
++  if (SpaceballInputExtension == 1)
++    {
++#ifdef HAVE_X11_EXTENSIONS_SGIMISC_H
++      /* SGI rezero */
++      static char *cmd = "\rZ\r";
++
++      XSGIDeviceControl (display, (int)SpaceballDevID, "sbprivate", cmd);
++      XFlush (display);
++
++#elif HAVE_X11_XPROTO_H
++      XBellFeedbackControl cntrl;
++
++#if defined(__cplusplus) || defined(c_plusplus)
++      cntrl.c_class = BellFeedbackClass;
++#else /* ! __cplusplus */
++      cntrl.class = BellFeedbackClass;
++#endif /* __cplusplus */
++      cntrl.pitch = 'Z';
++      cntrl.percent = 0;
++      cntrl.duration = 0;
++      XChangeFeedbackControl (display, pSpaceballDev,
++                              DvPercent | DvPitch | DvDuration, 
++                              (XFeedbackControl *)(void *)&cntrl);
++#endif /* HAVE_X11_XPROTO_H */
++    }
++#endif /* HAVE_X11_EXTENSIONS_XINPUT_H */
++
++  /* if we are not using XIE use XCM to communicate with the ball */
++  if (SpaceballInputExtension == 0) {
++    /* setup the rezero string and send it */
++    SPW_strLength = 0;
++    static char Z[] = "Z\r";
++    SendString (display, Z);
++  }
++} /* end of SPW_InputRezero */
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SPW_InputSetPulseRate (Display *display, unsigned short rate)
++ *
++ * Args:
++ *    display (r/o)  The X Display of which the XCM window is a resident
++ *    rate    (r/o)  The rate at which the spaceball data is sent
++ *
++ * Return Value:
++ *    None.
++ *
++ * Description:
++ *    This function sets the Spaceball transmission rate.  Currently
++ *    it is just stubed out since we don't want the transmission rate
++ *    of the Spaceball to change.
++ *
++ * Notes:
++ *    None.
++ *
++ *---------------------------------------------------------------------------*/
++void SPW_InputSetPulseRate (Display *display, unsigned short rate)
++{
++
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SPW_InputXPending (Display *display, int delay)
++ *
++ * Args:
++ *    display (r/o)  The X Display on which the queue is resident
++ *    delay   (r/o)  amount of time to wait for the next event in microseconds
++ *
++ * Return Value:
++ *    Returns the number of event on the X queue.
++ *
++ * Description: 
++ *    Wait for another Spaceball event to come in within the time delay.
++ *
++ * Notes:
++ *    If delay is less than or equal to zero this just checks the queue
++ *    without waiting.
++ *
++ *---------------------------------------------------------------------------*/
++int SPW_InputXPending (Display *display, int delay)
++{
++  int            numevents;  /* the number of event on the X queue */
++  struct timeval short_wait; /* time struct needed for select call */
++
++  fd_set Xfds;
++
++#ifdef SPW_DEBUG
++  fprintf(stderr,"SPW_InputXPending\n");
++#endif
++
++  /* get the number of event waiting on the event queue */
++  numevents = XPending (display);
++
++#ifdef SPW_DEBUG
++  fprintf(stderr,"   numevents %d delay %d\n", numevents, delay);
++#endif
++
++  /*
++   * if there are already event waiting or we have exceded the delay
++   *  return the number of events on the queue
++   */
++  if ((numevents > 0) || (delay <= 0)) {
++    return numevents;
++  }
++
++  /* use select to wait for the designated delay period */
++  short_wait.tv_sec = 0;
++  short_wait.tv_usec = (long) delay;
++  FD_ZERO (&Xfds);
++  FD_SET (ConnectionNumber (display), &Xfds);
++
++  (void)select (ConnectionNumber (display) + 1, &Xfds, NULL,
++                NULL, &short_wait);
++
++  /* check the event queue again */
++  numevents = XPending (display);
++
++#ifdef SPW_DEBUG 
++  fprintf(stderr,"   numevents %d\n", numevents);
++#endif
++
++  /* return the number of event on the queue */
++  return numevents;
++} /* end of SPW_InputXPending*/
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SPW_InputInitDispatchStruct (SPW_InputDispatchStruct *ds)
++ *
++ * Args: 
++ *   ds     (w/o)  - input dispatch structure
++ *
++ * Return Value:
++ *   None
++ *
++ * Description:
++ *   Zeroizes a new dispatch structure and sets the default delay.
++ *
++ * Notes:
++ *
++ *----------------------------------------------------------------------------*/
++void SPW_InputInitDispatchStruct (SPW_InputDispatchStruct * ds)
++{
++  memset(ds, (unsigned char)0, sizeof(SPW_InputDispatchStruct));
++  ds->delay = SPW_InputDefaultDelay;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SPW_InputDispatch (SPW_InputDispatchStruct *ds)
++ *
++ * Args: 
++ *   ds     (r/o)  - input dispatch structure
++ *
++ * Return Value:
++ *   1 if a redraw is required, 0 if a redraw is not required.
++ *
++ * Description:
++ *   Determines what type of event has been returned by the Spaceball and calls
++ *   the appropriate dispatch routine.
++ *   SPW_InputMotionEventHandler - called if a motion event occured
++ *   SPW_InputButtonEventHandler - called if a button event occured
++ *   SPW_InputOtherEventHandler - called if a non-spaceball event occured
++ *
++ * Notes:
++ *   if SPW_InputOtherEventHandler return a non-zero SPW_InputDispatch
++ *   will dispose of the event and continue processing events.
++ *
++ *----------------------------------------------------------------------------*/
++
++int SPW_InputDispatch (SPW_InputDispatchStruct *ds)
++{
++  float    data[7];          /* place to store Spaceball event data */
++  int      i;                /* loop counter */
++  int      motion_events;    /* flag tells if we have motion event*/
++  int  event_pending;    /* flag tells if ther's an event pending */
++  int      all_zero_event;   /* flag set if there's an all zero event */
++  int  redraw;           /* redraw flag */
++  int  continue_loop;    /* flag to keep while loop running */
++
++  /* initialize variable */
++  redraw = 0;
++  motion_events=0;
++  event_pending=1;
++  all_zero_event=0;
++  redraw = 0;
++  continue_loop=1;
++
++#ifdef SPW_DEBUG
++  fprintf(stderr,"SPW_InputDispatch\n");   /* show where we are */
++#endif
++
++  /* if dispatch struct is empty, return to caller */
++  if (ds == NULL)  
++    {
++      return 0;
++    }
++
++  /* initialize local event data structure */
++  for (i = 0; i < 7; i++) 
++    {
++      data[i] = 0.0f;
++    }
++
++  /* compress event data while it keeps on coming */
++  while (continue_loop == 1)
++    {
++
++#ifdef SPW_DEBUG
++      fprintf(stderr,"   spwevent type %d\n", ds->spwevent->type);
++#endif
++
++      /* see what type of event we have */
++      switch(ds->spwevent->type) 
++        {
++        case SPW_InputMotionEvent:
++          motion_events++;
++
++          /* Check for a no motion event */
++          if ((ds->spwevent->fData[0] == 0.0) && 
++              (ds->spwevent->fData[1] == 0.0) &&
++              (ds->spwevent->fData[2] == 0.0) && 
++              (ds->spwevent->fData[3] == 0.0) &&
++              (ds->spwevent->fData[4] == 0.0) && 
++              (ds->spwevent->fData[5] == 0.0))
++            {
++              all_zero_event++; /* keep track of how many we have */
++            }
++
++          /* add data into local structure */
++          for (i = 0; i < 7; i++)
++            {
++              data[i] += ds->spwevent->fData[i];
++            }
++
++#ifdef SPW_DEBUG
++          fprintf(stderr,"   %f %f %f %f %f %f %f\n", data[0],data[1],data[2],
++                  data[3],data[4],data[5],data[6]);
++#endif
++
++          break;
++        case SPW_InputButtonPressEvent:    /* button press event */
++          /* if button press event handler function pointer is present */
++          if (ds->handle_bpress != 0) 
++            {
++              (*(ds->handle_bpress)) (ds->display, ds->spwevent->buttonNumber,
++                                      ds->pButtonAppData);
++            }
++
++          /* check for rezero button */
++          if (ds->spwevent->buttonNumber == 9)
++            {
++              for (i = 0; i < 6; i++)
++                {
++                  data[i] = 0.0f;   /* zero data structure */
++                }
++              motion_events = 0;   /* reset number of motion events */
++            }
++          break;
++        case SPW_InputButtonReleaseEvent:    /* button release event */
++
++          if (ds->handle_brelease != 0)
++            {
++              (*(ds->handle_brelease)) (ds->display,ds->spwevent->buttonNumber,
++                                        ds->pButtonAppData);
++            }
++          /* check for rezero button */
++          if (ds->spwevent->buttonNumber == 9)
++            {
++              for (i = 0; i < 6; i++)
++                {
++                  data[i] = 0.0f;      /* clear local data */
++                }
++              motion_events = 0;      /* reset number of motion events */
++              redraw = 1;
++            }
++          break;
++        default:
++          break;
++        }  /* end of case statement */
++
++      /* check if input is pending */
++      if (SPW_InputXPending (ds->display, ds->delay))  
++        {
++          XNextEvent (ds->display, ds->xevent);         /* get an event */
++
++          /* if it's not a Spaceball event see if we should continue */
++          if (SPW_InputIsSpaceballEvent (ds->display, ds->xevent,
++                                         ds->spwevent) == 0)
++            {
++              /* if we have an event handler...*/
++              if (ds->handle_other != 0)
++                {
++                  /* handle event and get loop status */
++                  continue_loop = (ds->handle_other)
++                    (ds->display, ds->xevent, ds->pOtherAppData);
++                }
++              else
++                {
++                  continue_loop = 0; /* no event handler -> bail */
++                }
++            }
++        }
++      else  /* no more events to compress */
++        {
++          event_pending = 0;
++          continue_loop = 0;   
++        }
++    } /* end of while loop */
++
++#ifdef SPW_DEBUG
++  fprintf(stderr,"   event_pending %d motion_events %d all_zero_event %d\n",
++          event_pending, motion_events, all_zero_event);
++#endif
++
++  /* push unwanted event back onto the stack */
++  if (event_pending == 1)
++    {
++      XPutBackEvent(ds->display, ds->xevent);
++    }
++
++  /* average event data by the period of the Spaceball data */
++  if (data[6] != 0.0)
++    {
++      for (i = 0; i < 6; i++)
++        {
++          data[i] /= data[6];
++        }
++    }
++
++#ifdef SPW_DEBUG
++  fprintf(stderr,"ave %f %f %f %f %f %f\n\n", data[0], data[1], data[2], 
++          data[3], data[4], data[5]);
++#endif
++
++  /* if we have a motion event handler... */
++  if (ds->handle_motion != 0)
++    {
++      /* if there are motion events, handle them and force a redraw */
++      if (motion_events != 0) 
++        {
++          (*(ds->handle_motion)) (ds->display, data, ds->pMotionAppData);
++          redraw = 1;
++        }
++      
++      if ((all_zero_event != 0) && (motion_events > 1))
++        {
++          for (i = 0; i < 6; i++)
++            {
++              data[i] = 0.0f;   /* reset data */
++            }
++
++          /* handle motion and force a redraw */
++          (ds->handle_motion) (ds->display, data, ds->pMotionAppData);
++          redraw = 1;
++        }
++    }
++
++  return redraw;
++} /* end of SPW_InputDispatch */
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SPW_InputDispatchEx (SPW_InputDispatchStruct *ds)
++ *
++ * Args: 
++ *   ds     (r/o)  - input dispatch structure
++ *
++ * Return Value:
++ *   1 if a redraw is required, 0 if a redraw is not required.
++ *
++ * Description:
++ *   Determines what type of event has been returned by the Spaceball and calls
++ *   the appropriate dispatch routine.
++ *   SPW_InputMotionEventHandler - called if a motion event occured
++ *   SPW_InputButtonEventHandler - called if a button event occured
++ *   SPW_InputOtherEventHandler - called if a non-spaceball event occured
++ *
++ * Notes:
++ *   An optimized and more cooperative version of SPW_InputDispatch().
++ *   if SPW_InputOtherEventHandler returns non-zero, SPW_InputDispatchEx
++ *   will dispose of the event and continue compressing motion events.
++ *   If zero is returned, this function will dump all accumalated motion
++ *   events (unlike its predecessor) and quickly return control back to 
++ *   the app.  Also, the standard Xlib call XPending() is used instead of
++ *   SPW_InputXPending().
++ *
++ *----------------------------------------------------------------------------*/
++
++int SPW_InputDispatchEx (SPW_InputDispatchStruct *ds)
++{
++  float data[7]; /* place to store Spaceball event data */
++  int i; /* loop counter */
++  int motion_events; /* flag tells if we have motion event*/
++  int all_zero_event; /* flag set if there's an all zero event */
++  int redraw; /* redraw flag */
++  int continue_loop; /* flag to keep while loop running */
++
++  /* initialize variable */
++  redraw = 0;
++  motion_events=0;
++  all_zero_event=0;
++  redraw = 0;
++  continue_loop=1;
++
++#ifdef SPW_DEBUG
++  fprintf(stderr,"SPW_InputDispatch\n");  /* show where we are */
++#endif
++
++  /* if dispatch struct is empty, return to caller */
++  if (ds == NULL)
++    {
++      return 0;
++    }
++
++  /* initialize local event data structure */
++  for (i = 0; i < 7; i++)
++    {
++      data[i] = 0.0f;
++    }
++
++  /* compress event data while it keeps on coming */
++  while (continue_loop == 1)
++    {
++
++#ifdef SPW_DEBUG
++      fprintf(stderr,"   spwevent type %d\n", ds->spwevent->type);
++#endif
++
++      /* make sure we have ball data */
++      SPW_InputIsSpaceballEvent (ds->display, ds->xevent, ds->spwevent);
++
++      /* see what type of event we have */
++      switch(ds->spwevent->type)
++        {
++        case SPW_InputMotionEvent:
++          motion_events++;
++
++          /* Check for a no motion event */
++          if ((ds->spwevent->fData[0] == 0.0) &&
++              (ds->spwevent->fData[1] == 0.0) &&
++              (ds->spwevent->fData[2] == 0.0) &&
++              (ds->spwevent->fData[3] == 0.0) &&
++              (ds->spwevent->fData[4] == 0.0) &&
++              (ds->spwevent->fData[5] == 0.0))
++            {
++              all_zero_event++; /* keep track of how many we have */
++            }
++
++          /* add data into local structure */
++          for (i = 0; i < 7; i++)
++            {
++              data[i] += ds->spwevent->fData[i];
++            }
++
++#ifdef SPW_DEBUG
++          fprintf(stderr,"   %f %f %f %f %f %f %f\n",
++                  data[0],data[1],data[2],
++                  data[3],data[4],data[5],data[6]);
++#endif
++
++          break;
++        case SPW_InputButtonPressEvent:    /* button press event */
++          /* if button press event handler function pointer is present */
++          if (ds->handle_bpress != 0)
++            {
++              (*(ds->handle_bpress)) (ds->display, ds->spwevent->buttonNumber,
++                                      ds->pButtonAppData);
++            }
++
++          /* check for rezero button */
++          if (ds->spwevent->buttonNumber == 9)
++            {
++              for (i = 0; i < 6; i++)
++                {
++                  data[i] = 0.0f;   /* zero data structure */
++                }
++              motion_events = 0;   /* reset number of motion events */
++            }
++          break;
++        case SPW_InputButtonReleaseEvent:    /* button release event */
++
++          if (ds->handle_brelease != 0)
++            {
++              (*(ds->handle_brelease)) (ds->display,ds->spwevent->buttonNumber,
++                                        ds->pButtonAppData);
++            }
++          /* check for rezero button */
++          if (ds->spwevent->buttonNumber == 9)
++            {
++              for (i = 0; i < 6; i++)
++                {
++                  data[i] = 0.0f;      /* clear local data */
++                }
++              motion_events = 0;      /* reset number of motion events */
++              redraw = 1;
++            }
++          break;
++        default:
++          break;
++        }  /* end of case statement */
++
++      /* check if input is pending */
++      if (XPending (ds->display) > 0)
++        {
++          XPeekEvent (ds->display, ds->xevent);         /* look at an event */
++          if (SPW_InputIsSpaceballEvent (ds->display, ds->xevent,
++                                         ds->spwevent) == 1)
++            {
++              XEvent throw_away;
++              XNextEvent (ds->display, &throw_away);   /* remove the event */
++            }
++          else    /* if it's not a Spaceball event see if we should continue */
++            {
++              /* if we have an event handler...*/
++              if (ds->handle_other != NULL)
++                {
++                  /* handle event and get loop status */
++                  continue_loop = (ds->handle_other)
++                    (ds->display, ds->xevent, ds->pOtherAppData);
++                  if (continue_loop == 1)
++                    {
++                      XNextEvent (ds->display, ds->xevent);  /* get next event */
++                    }
++                  else
++                    {
++                      motion_events = 0;  /* app needs control back, fast! */
++                    }
++                }
++              else
++                {
++                  continue_loop = 0; /* no event handler -> bail */
++                }
++            }
++        }
++      else  /* no more events to compress */
++        {
++          continue_loop = 0;
++        }
++    } /* end of while loop */
++
++#if defined(SPW_DEBUG) && 0 
++  fprintf(stderr,"   event_pending %d motion_events %d all_zero_event %d\n",
++          event_pending, motion_events, all_zero_event);
++#endif
++
++  /* average event data by the period of the Spaceball data */
++  if (data[6] != 0.0)
++    {
++      for (i = 0; i < 6; i++)
++        {
++          data[i] /= data[6];
++        }
++    }
++
++#ifdef SPW_DEBUG
++  fprintf(stderr,"ave %f %f %f %f %f %f\n\n", data[0], data[1],
++          data[2],
++          data[3], data[4], data[5]);
++#endif
++
++  /* if we have a motion event handler... */
++  if (ds->handle_motion != 0)
++    {
++      /* if there are motion events, handle them and force a redraw */
++      if (motion_events != 0)
++        {
++          (*(ds->handle_motion)) (ds->display, data, ds->pMotionAppData);
++          redraw = 1;
++        }
++
++      if ((all_zero_event != 0) && (motion_events > 1))
++        {
++          for (i = 0; i < 6; i++)
++            {
++              data[i] = 0.0f;   /* reset data */
++            }
++
++          /* handle motion and force a redraw */
++          (ds->handle_motion) (ds->display, data, ds->pMotionAppData);
++          redraw = 1;
++        }
++    }
++
++  return redraw;
++
++} /* end of SPW_InputDispatchEx */
++
++#endif /* HAVE_X11_AVAILABLE */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiConstrainedViewer.cpp.in
+@@ -0,0 +1,299 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/*!
++  \class So at Gui@ConstrainedViewer Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.h
++  \brief The So at Gui@ConstrainedViewer class is the superclass for viewers with constrains on the viewpoint.
++  \ingroup components viewers
++
++  This abstract viewer class adds new methods to keep the camera in an
++  upright position according to some arbitrary up-direction. The
++  up-direction can be decided by either the application programmer (by
++  using So at Gui@ConstrainedViewer::setUpDirection()) or the end-user,
++  through interaction mechanisms defined by the subclasses.
++*/
++
++#include <Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.h>
++#include <Inventor/actions/SoRayPickAction.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/SoPickedPoint.h>
++#include <Inventor/nodes/SoCamera.h>
++#include <so at gui@defs.h>
++
++// ************************************************************************
++
++#ifndef DOXYGEN_SKIP_THIS
++
++class So at Gui@ConstrainedViewerP {
++public:
++  So at Gui@ConstrainedViewerP(So at Gui@ConstrainedViewer * owner) {
++    this->publ = owner;
++  }
++
++  void rotateCamera(const float delta) const;
++
++  SbVec3f upvechome;
++  SbVec3f upvector; // The camera's "up" vector is contrained to be in this direction.
++
++private:
++  So at Gui@ConstrainedViewer * publ;
++};
++
++#define PRIVATE(o) (o->pimpl)
++#define PUBLIC(o) (o->publ)
++
++void
++So at Gui@ConstrainedViewerP::rotateCamera(const float delta) const
++{
++  SoCamera * const camera = PUBLIC(this)->getCamera();
++  if (camera == NULL) { return; } // if there's no scenegraph, for instance
++
++  camera->orientation = camera->orientation.getValue() *
++    SbRotation(PUBLIC(this)->getUpDirection(), -delta);
++}
++
++#endif // DOXYGEN_SKIP_THIS
++
++// ************************************************************************
++
++SO at GUI@_OBJECT_ABSTRACT_SOURCE(So at Gui@ConstrainedViewer);
++
++// ************************************************************************
++
++/*!
++  Constructor.
++*/
++So at Gui@ConstrainedViewer::So at Gui@ConstrainedViewer(@WIDGET@ parent,
++                                                   const char * const name,
++                                                   SbBool embed,
++                                                   So at Gui@FullViewer::BuildFlag flag,
++                                                   So at Gui@Viewer::Type type,
++                                                   SbBool build)
++  : inherited(parent, name, embed, flag, type, FALSE)
++{
++  PRIVATE(this) = new So at Gui@ConstrainedViewerP(this);
++
++  this->setClassName("So at Gui@ConstrainedViewer");
++  this->setLeftWheelString("Tilt");
++  this->setBottomWheelString("Rotate");
++  this->setRightWheelString("Dolly");
++
++  PRIVATE(this)->upvector = SbVec3f(0.0f, 1.0f, 0.0f);
++  PRIVATE(this)->upvechome = PRIVATE(this)->upvector;
++
++  if (build) {
++    @WIDGET@ viewer = this->buildWidget(this->getParentWidget());
++    this->setBaseWidget(viewer);
++  }
++}
++
++// ************************************************************************
++
++/*!
++  Virtual destructor.
++*/
++So at Gui@ConstrainedViewer::~So at Gui@ConstrainedViewer()
++{
++  delete PRIVATE(this);
++}
++
++// ************************************************************************
++
++/*!
++  Set up-direction vector for the camera viewpoint.
++*/
++void
++So at Gui@ConstrainedViewer::setUpDirection(const SbVec3f & dir)
++{
++  SbRotation change(PRIVATE(this)->upvector, dir);
++  PRIVATE(this)->upvector = dir;
++
++  SoCamera * cam = this->getCamera();
++  if (cam == NULL) { return; } // can happen for empty scene, for instance
++
++  cam->orientation = change * cam->orientation.getValue();
++  this->checkForCameraUpConstrain();
++}
++
++// ************************************************************************
++
++/*!
++  Return up-direction vector for the camera viewpoint.
++*/
++const SbVec3f &
++So at Gui@ConstrainedViewer::getUpDirection(void) const
++{
++  return PRIVATE(this)->upvector;
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@ConstrainedViewer::setCamera(SoCamera * newcam)
++{
++  inherited::setCamera(newcam);
++  if (newcam != NULL) { this->checkForCameraUpConstrain(); }
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@ConstrainedViewer::saveHomePosition(void)
++{
++  inherited::saveHomePosition();
++  PRIVATE(this)->upvechome = PRIVATE(this)->upvector;
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@ConstrainedViewer::resetToHomePosition(void)
++{
++  inherited::resetToHomePosition();
++  PRIVATE(this)->upvector = PRIVATE(this)->upvechome;
++  // should be unnecessary to reset camera position here (camera
++  // should have been in a valid state on the last saveHomePosition()
++  // call)
++}
++
++// ************************************************************************
++
++/*!
++  This method tilts the camera \a delta degrees closer to the up
++  direction.
++*/
++void
++So at Gui@ConstrainedViewer::tiltCamera(float delta)
++{
++  SoCamera * const camera = this->getCamera();
++  if (camera == NULL) { return; } // if there's no scenegraph, for instance
++
++  SbVec3f camdir;
++  camera->orientation.getValue().multVec(SbVec3f(0, 0, -1), camdir);
++  camera->orientation = camera->orientation.getValue() *
++    SbRotation(this->getUpDirection().cross(camdir), delta);
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@ConstrainedViewer::bottomWheelMotion(float value)
++{
++  PRIVATE(this)->rotateCamera(value - this->getBottomWheelValue());
++  inherited::bottomWheelMotion(value);
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@ConstrainedViewer::leftWheelMotion(float value)
++{
++  this->tiltCamera( this->getLeftWheelValue() - value);
++  inherited::leftWheelMotion(value);
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@ConstrainedViewer::changeCameraValues(SoCamera * camera)
++{
++  inherited::changeCameraValues(camera);
++  this->checkForCameraUpConstrain();
++}
++
++// ************************************************************************
++
++/*!
++  Executes a raypick at the given mousepointer location and sets the
++  viewer's camera up-vector direction to the normal vector of the
++  picked geometry.
++*/
++void
++So at Gui@ConstrainedViewer::findUpDirection(SbVec2s mouselocation)
++{
++  SoRayPickAction rp(this->getViewportRegion());
++  rp.setPoint(mouselocation);
++
++  // Use the full scenegraph, not just the user-set scenegraph (which
++  // is what So at Gui@ConstrainedViewer::getSceneGraph() would return).
++  SoNode * realroot = this->getSceneManager()->getSceneGraph();
++  rp.apply(realroot);
++
++  SoPickedPoint * point = rp.getPickedPoint();
++  if (point == NULL) { return; } // missed all geometry
++
++  SbVec3f normvec = point->getNormal();
++  // FIXME: need to flip normal if we hit the backside of a
++  // polygon. 20010925 mortene.
++  this->setUpDirection(normvec);
++}
++
++// ************************************************************************
++
++/*!
++  If necessary, "tilts" the camera sideways so the up-direction is
++  heeded.
++*/
++void
++So at Gui@ConstrainedViewer::checkForCameraUpConstrain(void)
++{
++  SoCamera * cam = this->getCamera();
++  assert(cam);
++
++  SbRotation camorient = cam->orientation.getValue();
++
++  SbVec3f campointdir;
++  camorient.multVec(SbVec3f(0, 0, -1), campointdir);
++  SbVec3f camrightdir;
++  camorient.multVec(SbVec3f(1, 0, 0), camrightdir);
++
++  SbVec3f correctrightdir = campointdir.cross(PRIVATE(this)->upvector);
++  if (correctrightdir.length() == 0.0f) { return; } // upvector == pointdir
++
++  SbRotation r(camrightdir, correctrightdir);
++  SbRotation newcamorient = camorient * r;
++  cam->orientation = newcamorient;
++}
++
++// ************************************************************************
++
++#undef PRIVATE
++#undef PUBLIC
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiConstrainedViewer.h.in
+@@ -0,0 +1,77 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_CONSTRAINEDVIEWER_H
++#define SO at GUI@_CONSTRAINEDVIEWER_H
++
++#include <Inventor/@Gui@/viewers/So at Gui@FullViewer.h>
++
++// ************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@ConstrainedViewer : public So at Gui@FullViewer {
++  SO at GUI@_OBJECT_ABSTRACT_HEADER(So at Gui@ConstrainedViewer, So at Gui@FullViewer);
++
++public:
++  void setUpDirection(const SbVec3f & dir);
++  const SbVec3f & getUpDirection(void) const;
++
++  virtual void setCamera(SoCamera * newcam);
++  virtual void saveHomePosition(void);
++  virtual void resetToHomePosition(void);
++
++protected:
++  So at Gui@ConstrainedViewer(@WIDGET@ parent,
++                           const char * const name,
++                           SbBool embed,
++                           So at Gui@FullViewer::BuildFlag flag, 
++                           So at Gui@Viewer::Type type, 
++                           SbBool build);
++
++  ~So at Gui@ConstrainedViewer();
++
++  virtual void tiltCamera(float delta);
++  virtual void bottomWheelMotion(float value);
++  virtual void leftWheelMotion(float value);
++
++  virtual void changeCameraValues(SoCamera * camera);
++  void findUpDirection(SbVec2s mouselocation);
++  void checkForCameraUpConstrain(void);
++
++private:
++  class So at Gui@ConstrainedViewerP * pimpl;
++};
++
++// ************************************************************************
++
++#endif // ! SO at GUI@_CONSTRAINEDVIEWER_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiExaminerViewer.cpp.in
+@@ -0,0 +1,1301 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// This file contains the generic, "templatize-able" parts of the
++// So*ExaminerViewer sourcecode.
++
++// *************************************************************************
++
++/*!
++  \class So at Gui@ExaminerViewer So at Gui@ExaminerViewer.h Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.h
++  \brief The So at Gui@ExaminerViewer class is a 3D-model examination viewer.
++  \ingroup components viewers
++
++  This class is the viewer considered to be the most "general purpose"
++  viewer, and it is often used in rapid prototyping to examine simple
++  models aswell as complete scenes (although for the latter, you might
++  be better off with one of the other viewer classes).
++
++  <center>
++  <img src="http://doc.coin3d.org/images/SoLibs/viewers/examinerviewer.png">
++  </center>
++
++  Here is a complete, stand-alone example that shows how to set up an
++  So at Gui@ExaminerViewer as a model viewer that loads Inventor and VRML
++  files from disk and places them inside the viewer for the end-user
++  to examine:
++
++  \code
++  #include <Inventor/@Gui@/So at Gui@.h>
++  #include <Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.h>
++  #include <Inventor/nodes/SoBaseColor.h>
++  #include <Inventor/nodes/SoCone.h>
++  #include <Inventor/nodes/SoSeparator.h>
++  
++  int
++  main(int argc, char ** argv)
++  {
++    if (argc < 2) {
++      (void)fprintf(stderr, "\n\n\tUsage: %s <modelfilename>\n\n",
++                    argc > 0 ? argv[0] : "viewerapp");
++      exit(1);
++    }
++  
++    // Initialize So at Gui@ and Inventor API libraries. This returns a main
++    // window to use.
++    @WIDGET@ mainwin = So at Gui@::init(argc, argv, argv[0]);
++  
++    // Open the argument file..
++    SoInput in;
++    SbBool ok = in.openFile(argv[1]);
++    if (!ok) { exit(1); }
++  
++    // ..and import it.
++    SoSeparator * root = SoDB::readAll(&in);
++    if (root == NULL) { exit(1); }
++    root->ref();
++  
++    // Use the ExaminerViewer, for a nice interface for 3D model
++    // inspection.
++    So at Gui@ExaminerViewer * viewer = new So at Gui@ExaminerViewer(mainwin);
++    viewer->setSceneGraph(root);
++    viewer->show();
++  
++    // Pop up the main window.
++    So at Gui@::show(mainwin);
++    // Loop until exit.
++    So at Gui@::mainLoop();
++  
++    // Clean up resources.
++    delete viewer;
++    root->unref();
++  
++    return 0;
++  }
++  \endcode
++
++  So at Gui@ExaminerViewer has a convenient interface for repositioning
++  and reorientation of the camera, by panning, rotating and zooming
++  it's position. The following controls can be used:
++
++  <ul>
++
++  <li>hold down left mousebutton and move mouse pointer to rotate the
++  camera around it's current focal point (the focal point can be
++  changed by doing a seek operation)</li>
++
++  <li>hold middle mousebutton to pan (or a CTRL-key plus left
++  mousebutton, or a SHIFT-key plus left mousebutton)</li>
++
++  <li>hold down left + middle mousebutton to zoom / dolly, or CTRL +
++  middle mousebutton, or CTRL + SHIFT + the left mousebutton</li>
++
++  <li>click 's', then pick with the left mousebutton to seek</li>
++
++  <li>right mousebutton opens the popup menu</li>
++
++  <li>click 'ESC' key to switch to and from 'camera interaction' mode
++  and 'scenegraph interaction' mode (see setViewing()
++  documentation)</li>
++
++  <!-- 
++    FIXME: This functionality has been disabled. See FIXME comment
++    20050202 larsa below.
++      
++  <li>hold down the 'ALT' key to temporary toggle from
++  camera-interaction mode to scenegraph-interaction mode</li>
++
++  //-->
++
++  <li>'q' quits the application</li>
++
++  </ul>
++
++  The So at Gui@ExaminerViewer provides a user decoration's button for
++  toggling between orthographic or perspective camera view volumes and
++  projection methods. This is the bottom-most click button on the
++  right decoration border.
++
++  It also inherits the decoration buttons from the So at Gui@FullViewer:
++  the arrow for switching to "scenegraph interaction" mode, the hand
++  for setting back to "camera interaction" mode, the house for "reset
++  camera to home position", the blueprint house for "set new camera
++  home position", the eye for "zoom camera out to view full scene" and
++  the flashlight for setting "click to seek" mode.
++
++  Note that a common faulty assumption about all the viewer-classes is
++  that user interaction (in the "examine"-mode, not the
++  scenegraph-interaction mode) influences the model or 3D-scene in the
++  view. This is not correct, as it is always the viewer's \e camera
++  that is translated and rotated.
++
++  The initial position of the camera is placed such that all of the
++  scenegraph's geometry fits within it's view.
++
++  \sa So at Gui@FlyViewer, So at Gui@PlaneViewer
++*/
++
++// *************************************************************************
++
++// Documentation shared between So* toolkits follows below.
++
++/*!
++  \fn So at Gui@ExaminerViewer::So at Gui@ExaminerViewer(@WIDGET@ parent, const char * name, SbBool embed, So at Gui@FullViewer::BuildFlag flag, So at Gui@Viewer::Type type)
++
++  Constructor.  See parent class for explanation of arguments.
++  Calling this constructor will make sure the examiner viewer widget
++  will be built immediately.
++*/
++
++/*!
++  \fn So at Gui@ExaminerViewer::So at Gui@ExaminerViewer(@WIDGET@ parent, const char * name, SbBool embed, So at Gui@FullViewer::BuildFlag flag, So at Gui@Viewer::Type type, SbBool build)
++
++  Constructor. See parent class for explanation of arguments.
++*/
++
++// *************************************************************************
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <assert.h>
++#include <math.h>
++
++#include <Inventor/SbTime.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/nodes/SoOrthographicCamera.h>
++#include <Inventor/nodes/SoPerspectiveCamera.h>
++#include <Inventor/projectors/SbSphereSheetProjector.h>
++#include <Inventor/projectors/SbSpherePlaneProjector.h>
++#include <Inventor/events/SoKeyboardEvent.h>
++#include <Inventor/events/SoMouseButtonEvent.h>
++#include <Inventor/events/SoLocation2Event.h>
++#include <Inventor/events/SoMotion3Event.h>
++
++#include <so at gui@defs.h>
++
++#include <Inventor/@Gui@/common/gl.h>
++#include <Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.h>
++#include <Inventor/@Gui@/viewers/So at Gui@ExaminerViewerP.h>
++
++#include <Inventor/@Gui@/So at Gui@Basic.h>
++#include <Inventor/@Gui@/So at Gui@Cursor.h>
++#include <Inventor/@Gui@/viewers/SoGuiFullViewerP.h> // for pan() and zoom()
++
++#define PRIVATE(obj) ((obj)->pimpl)
++#define PUBLIC(obj) ((obj)->pub)
++
++static const int MOUSEPOSLOGSIZE = 16;
++
++// Bitmap representations of an "X", a "Y" and a "Z" for the axis cross.
++static GLubyte xbmp[] = { 0x11,0x11,0x0a,0x04,0x0a,0x11,0x11 };
++static GLubyte ybmp[] = { 0x04,0x04,0x04,0x04,0x0a,0x11,0x11 };
++static GLubyte zbmp[] = { 0x1f,0x10,0x08,0x04,0x02,0x01,0x1f };
++
++// ************************************************************************
++
++/*!
++  Decide if it should be possible to start a spin animation of the
++  model in the viewer by releasing the mouse button while dragging.
++
++  If the \a enable flag is \c FALSE and we're currently animating, the
++  spin will be stopped.
++
++  \sa isAnimationEnabled
++*/
++void
++So at Gui@ExaminerViewer::setAnimationEnabled(const SbBool enable)
++{
++  PRIVATE(this)->spinanimatingallowed = enable;
++  if (!enable && this->isAnimating()) { this->stopAnimating(); }
++}
++
++// *************************************************************************
++
++/*!
++  Query whether or not it is possible to start a spinning animation by
++  releasing the left mouse button while dragging the mouse.
++
++  \sa setAnimationEnabled
++*/
++
++SbBool
++So at Gui@ExaminerViewer::isAnimationEnabled(void) const
++{
++  return PRIVATE(this)->spinanimatingallowed;
++}
++
++// *************************************************************************
++
++/*!
++  Stop the model from spinning.
++*/
++
++void
++So at Gui@ExaminerViewer::stopAnimating(void)
++{
++  if (PRIVATE(this)->currentmode != SoGuiExaminerViewerP::SPINNING) {
++#if SO at GUI@_DEBUG
++    SoDebugError::postWarning("So at Gui@ExaminerViewer::stopAnimating",
++                              "not animating");
++#endif // SO at GUI@_DEBUG
++    return;
++  }
++  PRIVATE(this)->setMode(this->isViewing() ?
++                         SoGuiExaminerViewerP::IDLE :
++                         SoGuiExaminerViewerP::INTERACT);
++}
++
++// *************************************************************************
++
++/*!
++  Query if the model in the viewer is currently in spinning mode after
++  a user drag.
++*/
++
++SbBool
++So at Gui@ExaminerViewer::isAnimating(void) const
++{
++  return PRIVATE(this)->currentmode == SoGuiExaminerViewerP::SPINNING;
++}
++
++// ************************************************************************
++
++/*!
++  Set the flag deciding whether or not to show the axis cross.
++
++  \sa isFeedbackVisible, getFeedbackSize, setFeedbackSize
++*/
++
++void
++So at Gui@ExaminerViewer::setFeedbackVisibility(const SbBool enable)
++{
++  if (enable == PRIVATE(this)->axiscrossEnabled) {
++#ifdef SO at GUI@_EXTRA_DEBUG
++    SoDebugError::postWarning("So at Gui@ExaminerViewer::setFeedbackVisibility",
++                              "feedback visibility already set to %s", enable ? "TRUE" : "FALSE");
++#endif // SO at GUI@_EXTRA_DEBUG
++    return;
++  }
++  PRIVATE(this)->axiscrossEnabled = enable;
++
++  if (this->isViewing()) { this->scheduleRedraw(); }
++}
++
++/*!
++  Check if the feedback axis cross is visible.
++
++  \sa setFeedbackVisibility, getFeedbackSize, setFeedbackSize
++*/
++
++SbBool
++So at Gui@ExaminerViewer::isFeedbackVisible(void) const
++{
++  return PRIVATE(this)->axiscrossEnabled;
++}
++
++// ************************************************************************
++
++/*!
++  Set the size of the feedback axiscross.  The value is interpreted as
++  an approximate percentage chunk of the dimensions of the total
++  canvas.
++
++  \sa getFeedbackSize, isFeedbackVisible, setFeedbackVisibility
++*/
++void
++So at Gui@ExaminerViewer::setFeedbackSize(const int size)
++{
++#if SO at GUI@_DEBUG
++  if (size < 1) {
++    SoDebugError::postWarning("So at Gui@ExaminerViewer::setFeedbackSize",
++                              "the size setting should be larger than 0");
++    return;
++  }
++#endif // SO at GUI@_DEBUG
++
++  PRIVATE(this)->axiscrossSize = size;
++
++  if (this->isFeedbackVisible() && this->isViewing()) {
++    this->scheduleRedraw();
++  }
++}
++
++/*!
++  Return the size of the feedback axis cross. Default is 25.
++
++  \sa setFeedbackSize, isFeedbackVisible, setFeedbackVisibility
++*/
++
++int
++So at Gui@ExaminerViewer::getFeedbackSize(void) const
++{
++  return PRIVATE(this)->axiscrossSize;
++}
++
++// *************************************************************************
++
++// Documented in superclass.
++SbBool
++So at Gui@ExaminerViewer::processSoEvent(const SoEvent * const ev)
++{
++#if SO at GUI@_DEBUG && 0 // debug
++  SoDebugError::postInfo("So at Gui@ExaminerViewer::processSoEvent",
++                          "[invoked], event '%s'",
++                          ev->getTypeId().getName().getString());
++#endif // debug
++
++  // We're in "interact" mode (ie *not* the camera modification mode),
++  // so don't handle the event here. It should either be forwarded to
++  // the scenegraph, or caught by So at Gui@Viewer::processSoEvent() if
++  // it's an ESC or ALT press (to switch modes).
++  if (!this->isViewing()) { return inherited::processSoEvent(ev); }
++    
++  // Events when in "ready-to-seek" mode are ignored, except those
++  // which influence the seek mode itself -- these are handled further
++  // up the inheritance hierarchy.
++  if (this->isSeekMode()) { return inherited::processSoEvent(ev); }
++
++  const SoType type(ev->getTypeId());
++
++  const SbVec2s size(this->getGLSize());
++  const SbVec2f prevnormalized = PRIVATE(this)->lastmouseposition;
++  const SbVec2s pos(ev->getPosition());
++  const SbVec2f posn((float) pos[0] / (float) So at Gui@Max((int)(size[0] - 1), 1),
++                     (float) pos[1] / (float) So at Gui@Max((int)(size[1] - 1), 1));
++
++  PRIVATE(this)->lastmouseposition = posn;
++
++  // Set to TRUE if any event processing happened. Note that it is not
++  // necessary to restrict ourselves to only do one "action" for an
++  // event, we only need this flag to see if any processing happened
++  // at all.
++  SbBool processed = FALSE;
++
++  const SoGuiExaminerViewerP::ViewerMode currentmode = PRIVATE(this)->currentmode;
++  SoGuiExaminerViewerP::ViewerMode newmode = currentmode;
++
++  PRIVATE(this)->ctrldown = ev->wasCtrlDown();
++  PRIVATE(this)->shiftdown = ev->wasShiftDown();
++
++  // Mouse Button / Spaceball Button handling
++
++  if (type.isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) {
++    processed = TRUE;
++
++    const SoMouseButtonEvent * const event = (const SoMouseButtonEvent *) ev;
++    const int button = event->getButton();
++    const SbBool press = event->getState() == SoButtonEvent::DOWN ? TRUE : FALSE;
++
++    switch (button) {
++    case SoMouseButtonEvent::BUTTON1:
++      PRIVATE(this)->button1down = press;
++      if (press && (currentmode == SoGuiExaminerViewerP::SEEK_WAIT_MODE)) {
++        newmode = SoGuiExaminerViewerP::SEEK_MODE;
++        this->seekToPoint(pos); // implicitly calls interactiveCountInc()
++      }
++      break;
++    case SoMouseButtonEvent::BUTTON2:
++      processed = FALSE; // pass on to superclass, so popup menu is shown
++      break;
++    case SoMouseButtonEvent::BUTTON3:
++      PRIVATE(this)->button3down = press;
++      break;
++#ifdef HAVE_SOMOUSEBUTTONEVENT_BUTTON5
++    case SoMouseButtonEvent::BUTTON4:
++      if (press) SoGuiFullViewerP::zoom(this->getCamera(), 0.1f);
++      break;
++    case SoMouseButtonEvent::BUTTON5:
++      if (press) SoGuiFullViewerP::zoom(this->getCamera(), -0.1f);
++      break;
++#endif // HAVE_SOMOUSEBUTTONEVENT_BUTTON5
++    default:
++      break;
++    }
++  }
++
++  // Keyboard handling
++  if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
++    const SoKeyboardEvent * const event = (const SoKeyboardEvent *) ev;
++    const SbBool press = event->getState() == SoButtonEvent::DOWN ? TRUE : FALSE;
++    switch (event->getKey()) {
++    case SoKeyboardEvent::LEFT_CONTROL:
++    case SoKeyboardEvent::RIGHT_CONTROL:
++      processed = TRUE;
++      PRIVATE(this)->ctrldown = press;
++      break;
++    case SoKeyboardEvent::LEFT_SHIFT:
++    case SoKeyboardEvent::RIGHT_SHIFT:
++      processed = TRUE;
++      PRIVATE(this)->shiftdown = press;
++      break;
++    default:
++      break;
++    }
++  }
++
++  // Mouse Movement handling
++  if (type.isDerivedFrom(SoLocation2Event::getClassTypeId())) {
++    const SoLocation2Event * const event = (const SoLocation2Event *) ev;
++
++    processed = TRUE;
++
++    if (PRIVATE(this)->currentmode == SoGuiExaminerViewerP::ZOOMING) {
++      PRIVATE(this)->zoomByCursor(posn, prevnormalized);
++    }
++    else if (PRIVATE(this)->currentmode == SoGuiExaminerViewerP::PANNING) {
++      SoGuiFullViewerP::pan(this->getCamera(), this->getGLAspectRatio(),
++                            PRIVATE(this)->panningplane, posn, prevnormalized);
++    }
++    else if (PRIVATE(this)->currentmode == SoGuiExaminerViewerP::DRAGGING) {
++      PRIVATE(this)->addToLog(event->getPosition(), event->getTime());
++      PRIVATE(this)->spin(posn);
++    }
++    else {
++      processed = FALSE;
++    }
++  }
++
++  // Spaceball & Joystick handling
++  if (type.isDerivedFrom(SoMotion3Event::getClassTypeId())) {
++    SoMotion3Event * const event = (SoMotion3Event *) ev;
++    SoCamera * const camera = this->getCamera();
++    if (camera) {
++      if (PRIVATE(this)->motion3OnCamera) {
++        SbVec3f dir = event->getTranslation();
++        camera->orientation.getValue().multVec(dir,dir);
++        camera->position = camera->position.getValue() + dir;
++        camera->orientation = 
++          event->getRotation() * camera->orientation.getValue();
++        processed = TRUE;
++      }
++      else {
++        // FIXME: move/rotate model
++#if SO at GUI@_DEBUG
++        SoDebugError::postInfo("So at Gui@ExaminerViewer::processSoEvent",
++                               "SoMotion3Event for model movement is not implemented yet");
++#endif // SO at GUI@_DEBUG
++        processed = TRUE;
++      }
++    }
++  }
++
++  enum {
++    BUTTON1DOWN = 1 << 0,
++    BUTTON3DOWN = 1 << 1,
++    CTRLDOWN =    1 << 2,
++    SHIFTDOWN =   1 << 3
++  };
++  unsigned int combo =
++    (PRIVATE(this)->button1down ? BUTTON1DOWN : 0) |
++    (PRIVATE(this)->button3down ? BUTTON3DOWN : 0) |
++    (PRIVATE(this)->ctrldown ? CTRLDOWN : 0) |
++    (PRIVATE(this)->shiftdown ? SHIFTDOWN : 0);
++
++  switch (combo) {
++  case 0:
++    if (currentmode == SoGuiExaminerViewerP::SPINNING) { break; }
++    newmode = SoGuiExaminerViewerP::IDLE;
++    if ((currentmode == SoGuiExaminerViewerP::DRAGGING) &&
++        this->isAnimationEnabled() && (PRIVATE(this)->log.historysize >= 3)) {
++      SbTime stoptime = (ev->getTime() - PRIVATE(this)->log.time[0]);
++      if (stoptime.getValue() < 0.100) {
++        const SbVec2s glsize(this->getGLSize());
++        SbVec3f from = PRIVATE(this)->spinprojector->project(SbVec2f(float(PRIVATE(this)->log.position[2][0]) / float(So at Gui@Max(glsize[0]-1, 1)),
++                                                                     float(PRIVATE(this)->log.position[2][1]) / float(So at Gui@Max(glsize[1]-1, 1))));
++        SbVec3f to = PRIVATE(this)->spinprojector->project(posn);
++        SbRotation rot = PRIVATE(this)->spinprojector->getRotation(from, to);
++
++        SbTime delta = (PRIVATE(this)->log.time[0] - PRIVATE(this)->log.time[2]);
++        double deltatime = delta.getValue();
++        rot.invert();
++        rot.scaleAngle(float(0.200 / deltatime));
++
++        SbVec3f axis;
++        float radians;
++        rot.getValue(axis, radians);
++        if ((radians > 0.01f) && (deltatime < 0.300)) {
++          newmode = SoGuiExaminerViewerP::SPINNING;
++          PRIVATE(this)->spinRotation = rot;
++        }
++      }
++    }
++    break;
++  case BUTTON1DOWN:
++    newmode = SoGuiExaminerViewerP::DRAGGING;
++    break;
++  case BUTTON3DOWN:
++  case CTRLDOWN|BUTTON1DOWN:
++  case SHIFTDOWN|BUTTON1DOWN:
++    newmode = SoGuiExaminerViewerP::PANNING;
++    break;
++  case BUTTON1DOWN|BUTTON3DOWN:
++  case CTRLDOWN|BUTTON3DOWN:
++  case CTRLDOWN|SHIFTDOWN|BUTTON1DOWN:
++    newmode = SoGuiExaminerViewerP::ZOOMING;
++    break;
++
++    // There are many cases we don't handle that just falls through to
++    // the default case, like SHIFTDOWN, CTRLDOWN, CTRLDOWN|SHIFTDOWN,
++    // SHIFTDOWN|BUTTON3DOWN, SHIFTDOWN|CTRLDOWN|BUTTON3DOWN, etc.
++    // This is a feature, not a bug. :-)
++    //
++    // mortene.
++
++  default:
++    // The default will make a spin stop and otherwise not do
++    // anything.
++    if ((currentmode != SoGuiExaminerViewerP::SEEK_WAIT_MODE) &&
++        (currentmode != SoGuiExaminerViewerP::SEEK_MODE)) {
++      newmode = SoGuiExaminerViewerP::IDLE;
++    }
++    break;
++  }
++
++  if (newmode != currentmode) {
++    PRIVATE(this)->setMode(newmode);
++  }
++
++  // If not handled in this class, pass on upwards in the inheritance
++  // hierarchy.
++  return processed || inherited::processSoEvent(ev);
++}
++
++// *************************************************************************
++
++// documented in superclass
++void
++So at Gui@ExaminerViewer::setSeekMode(SbBool on)
++{
++  // Overrides this method to make sure any animations are stopped
++  // before we go into seek mode.
++
++  // Note: this method is almost identical to the setSeekMode() in the
++  // So at Gui@FlyViewer and So at Gui@PlaneViewer, so migrate any changes.
++
++#if SO at GUI@_DEBUG
++  if (on == this->isSeekMode()) {
++    SoDebugError::postWarning("So at Gui@ExaminerViewer::setSeekMode",
++                              "seek mode already %sset", on ? "" : "un");
++    return;
++  }
++#endif // SO at GUI@_DEBUG
++
++  if (this->isAnimating()) { this->stopAnimating(); }
++  inherited::setSeekMode(on);
++  PRIVATE(this)->setMode(on ?
++                         SoGuiExaminerViewerP::SEEK_WAIT_MODE :
++                         (this->isViewing() ?
++                          SoGuiExaminerViewerP::IDLE : SoGuiExaminerViewerP::INTERACT));
++}
++
++// *************************************************************************
++
++/*!
++  Decide whether or not the mouse pointer cursor should be visible in
++  the rendering canvas.
++*/
++void
++So at Gui@ExaminerViewer::setCursorEnabled(SbBool enable)
++{
++  inherited::setCursorEnabled(enable);
++  PRIVATE(this)->setCursorRepresentation(PRIVATE(this)->currentmode);
++}
++
++// *************************************************************************
++
++// Documented in superclass.
++const char *
++So at Gui@ExaminerViewer::getDefaultWidgetName(void) const
++{
++  return "So at Gui@ExaminerViewer";
++}
++
++// *************************************************************************
++
++// Documented in superclass.
++const char *
++So at Gui@ExaminerViewer::getDefaultTitle(void) const
++{
++  return "Examiner Viewer";
++}
++
++// *************************************************************************
++
++// Documented in superclass.
++const char *
++So at Gui@ExaminerViewer::getDefaultIconTitle(void) const
++{
++  return "Examiner Viewer";
++}
++
++// *************************************************************************
++
++// Documented in superclass. Overrides this method to be able to draw
++// the axis cross, if selected, and to keep a continuous animation
++// upon spin.
++void
++So at Gui@ExaminerViewer::actualRedraw(void)
++{
++  SbTime now = SbTime::getTimeOfDay();
++  double secs = now.getValue() -  PRIVATE(this)->prevRedrawTime.getValue();
++
++  PRIVATE(this)->prevRedrawTime = now;
++
++  if (this->isAnimating()) {
++    SbRotation deltaRotation = PRIVATE(this)->spinRotation;
++    deltaRotation.scaleAngle(float(secs * 5.0));
++    PRIVATE(this)->reorientCamera(deltaRotation);
++  }
++
++  inherited::actualRedraw();
++
++  if (this->isFeedbackVisible()) { PRIVATE(this)->drawAxisCross(); }
++
++  // Immediately reschedule to get continous spin animation.
++  if (this->isAnimating()) { this->scheduleRedraw(); }
++}
++
++// *************************************************************************
++
++// doc in super
++void
++So at Gui@ExaminerViewer::afterRealizeHook(void)
++{
++  inherited::afterRealizeHook();
++  PRIVATE(this)->setCursorRepresentation(PRIVATE(this)->currentmode);
++}
++
++// *************************************************************************
++
++// Documented in superclass. Overridden to provide the examiner viewer
++// functionality on the left thumbwheel (x axis rotation).
++void
++So at Gui@ExaminerViewer::leftWheelMotion(float value)
++{
++  if (this->isAnimating()) this->stopAnimating();
++
++  float newval = PRIVATE(this)->rotXWheelMotion(value, this->getLeftWheelValue());
++  inherited::leftWheelMotion(newval);
++}
++
++// Documented in superclass. Overridden to provide the examiner viewer
++// functionality on the bottom thumbwheel (y axis rotation).
++void
++So at Gui@ExaminerViewer::bottomWheelMotion(float value)
++{
++  if (this->isAnimating()) this->stopAnimating();
++
++  float newval = PRIVATE(this)->rotYWheelMotion(value, this->getBottomWheelValue());
++  inherited::bottomWheelMotion(newval);
++}
++
++// Documented in superclass. Overridden to provide the examiner viewer
++// functionality on the left thumbwheel (dolly/zoom).
++void
++So at Gui@ExaminerViewer::rightWheelMotion(float value)
++{
++  SoGuiFullViewerP::zoom(this->getCamera(), this->getRightWheelValue() - value);
++  inherited::rightWheelMotion(value);
++}
++
++// *************************************************************************
++
++// Documented in superclass. This method overridden from parent class
++// to make sure the mouse pointer cursor is updated.
++void
++So at Gui@ExaminerViewer::setViewing(SbBool enable)
++{
++  if (!!this->isViewing() == !!enable) {
++#if SO at GUI@_DEBUG
++    SoDebugError::postWarning("So at Gui@ExaminerViewer::setViewing",
++                              "current state already %s", enable ? "TRUE" : "FALSE");
++#endif // SO at GUI@_DEBUG
++    return;
++  }
++
++  PRIVATE(this)->setMode(enable ?
++                         SoGuiExaminerViewerP::IDLE :
++                         SoGuiExaminerViewerP::INTERACT);
++  inherited::setViewing(enable);
++}
++
++// *************************************************************************
++
++#ifndef DOXYGEN_SKIP_THIS
++
++// Remaining code is for the SoGuiExaminerViewerP "private
++// implementation" class.
++
++SoGuiExaminerViewerP::SoGuiExaminerViewerP(So at Gui@ExaminerViewer * publ)
++{
++  PUBLIC(this) = publ;
++}
++
++SoGuiExaminerViewerP::~SoGuiExaminerViewerP()
++{
++}
++
++void
++SoGuiExaminerViewerP::genericConstructor(void)
++{
++  this->currentmode = SoGuiExaminerViewerP::IDLE;
++
++  this->prevRedrawTime = SbTime::getTimeOfDay();
++  this->spinanimatingallowed = TRUE;
++  this->spinsamplecounter = 0;
++  this->spinincrement = SbRotation::identity();
++
++  // FIXME: use a smaller sphere than the default one to have a larger
++  // area close to the borders that gives us "z-axis rotation"?
++  // 19990425 mortene.
++  this->spinprojector = new SbSphereSheetProjector(SbSphere(SbVec3f(0, 0, 0), 0.8f));
++  SbViewVolume volume;
++  volume.ortho(-1, 1, -1, 1, -1, 1);
++  this->spinprojector->setViewVolume(volume);
++
++  this->axiscrossEnabled = FALSE;
++  this->axiscrossSize = 25;
++
++  this->spinRotation.setValue(SbVec3f(0, 0, -1), 0);
++
++  this->log.size = MOUSEPOSLOGSIZE;
++  this->log.position = new SbVec2s [ MOUSEPOSLOGSIZE ];
++  this->log.time = new SbTime [ MOUSEPOSLOGSIZE ];
++  this->log.historysize = 0;
++  this->button1down = FALSE;
++  this->button3down = FALSE;
++  this->ctrldown = FALSE;
++  this->shiftdown = FALSE;
++  this->pointer.now = SbVec2s(0, 0);
++  this->pointer.then = SbVec2s(0, 0);
++  this->motion3OnCamera = TRUE;
++}
++
++void
++SoGuiExaminerViewerP::genericDestructor(void)
++{
++  delete this->spinprojector;
++  delete[] this->log.position;
++  delete[] this->log.time;
++}
++
++// ************************************************************************
++
++// rotate a camera around its focalpoint, in the direction around the
++// given axis, by the given delta value (in radians)
++void
++SoGuiExaminerViewerP::rotateCamera(SoCamera * cam,
++                                   const SbVec3f & aroundaxis,
++                                   const float delta)
++{
++  const SbVec3f DEFAULTDIRECTION(0, 0, -1);
++  const SbRotation currentorientation = cam->orientation.getValue();
++
++  SbVec3f currentdir;
++  currentorientation.multVec(DEFAULTDIRECTION, currentdir);
++
++  const SbVec3f focalpoint = cam->position.getValue() +
++    cam->focalDistance.getValue() * currentdir;
++
++  // set new orientation
++  cam->orientation = SbRotation(aroundaxis, delta) * currentorientation;
++
++  SbVec3f newdir;
++  cam->orientation.getValue().multVec(DEFAULTDIRECTION, newdir);
++  cam->position = focalpoint - cam->focalDistance.getValue() * newdir;
++}
++
++// The "rotX" wheel is the wheel on the left decoration on the
++// examiner viewer.  This function translates interaction with the
++// "rotX" wheel into camera movement.
++float
++SoGuiExaminerViewerP::rotXWheelMotion(float value, float oldvalue)
++{
++  SoCamera * cam = PUBLIC(this)->getCamera();
++  if (cam == NULL) return 0.0f; // can happen for empty scenegraph
++
++  SoGuiExaminerViewerP::rotateCamera(cam, SbVec3f(-1, 0, 0), value - oldvalue);
++  return value;
++}
++
++// The "rotY" wheel is the wheel on the bottom decoration on the
++// examiner viewer.  This function translates interaction with the
++// "rotX" wheel into camera movement.
++float
++SoGuiExaminerViewerP::rotYWheelMotion(float value, float oldvalue)
++{
++  SoCamera * cam = PUBLIC(this)->getCamera();
++  if (cam == NULL) return 0.0f; // can happen for empty scenegraph
++
++  SoGuiExaminerViewerP::rotateCamera(cam, SbVec3f(0, -1, 0), value - oldvalue);
++  return value;
++}
++
++// ************************************************************************
++
++// The viewer is a state machine, and all changes to the current state
++// are made through this call.
++void
++SoGuiExaminerViewerP::setMode(const ViewerMode newmode)
++{
++  const ViewerMode oldmode = this->currentmode;
++  if (newmode == oldmode) { return; }
++
++  switch (newmode) {
++  case DRAGGING:
++    // Set up initial projection point for the projector object when
++    // first starting a drag operation.
++    this->spinprojector->project(this->lastmouseposition);
++    PUBLIC(this)->interactiveCountInc();
++    this->clearLog();
++    break;
++
++  case SPINNING:
++    PUBLIC(this)->interactiveCountInc();
++    PUBLIC(this)->scheduleRedraw();
++    break;
++
++  case PANNING:
++    {
++      // The plane we're projecting the mouse coordinates to get 3D
++      // coordinates should stay the same during the whole pan
++      // operation, so we should calculate this value here.
++      SoCamera * cam = PUBLIC(this)->getCamera();
++      if (cam == NULL) { // can happen for empty scenegraph
++        this->panningplane = SbPlane(SbVec3f(0, 0, 1), 0);
++      }
++      else {
++        SbViewVolume vv = cam->getViewVolume(PUBLIC(this)->getGLAspectRatio());
++        this->panningplane = vv.getPlane(cam->focalDistance.getValue());
++      }
++    }
++    PUBLIC(this)->interactiveCountInc();
++    break;
++
++  case ZOOMING:
++    PUBLIC(this)->interactiveCountInc();
++    break;
++
++  default: // include default to avoid compiler warnings.
++    break;
++  }
++
++  switch (oldmode) {
++  case SPINNING:
++  case DRAGGING:
++  case PANNING:
++  case ZOOMING:
++    PUBLIC(this)->interactiveCountDec();
++    break;
++
++  default:
++    break;
++  }
++
++#if SO at GUI@_DEBUG && 0 // debug
++  if (oldmode == ZOOMING) {
++    SbVec3f v = PUBLIC(this)->getCamera()->position.getValue();
++    SoDebugError::postInfo("So at Gui@ExaminerViewerP::setMode",
++                           "new camera position after zoom: <%e, %e, %e>",
++                           v[0], v[1], v[2]);
++  }
++#endif // debug
++
++  this->setCursorRepresentation(newmode);
++  this->currentmode = newmode;
++}
++
++// ************************************************************************
++
++void
++SoGuiExaminerViewerP::drawAxisCross(void)
++{
++  // FIXME: convert this to a superimposition scenegraph instead of
++  // OpenGL calls. 20020603 mortene.
++
++  // Store GL state.
++  glPushAttrib(GL_ALL_ATTRIB_BITS);
++  GLfloat depthrange[2];
++  glGetFloatv(GL_DEPTH_RANGE, depthrange);
++  GLdouble projectionmatrix[16];
++  glGetDoublev(GL_PROJECTION_MATRIX, projectionmatrix);
++
++  glDepthFunc(GL_ALWAYS);
++  glDepthMask(GL_TRUE);
++  glDepthRange(0, 0);
++  glEnable(GL_DEPTH_TEST);
++  glDisable(GL_LIGHTING);
++  glEnable(GL_COLOR_MATERIAL);
++  glDisable(GL_BLEND); // Kills transparency.
++
++  // Set the viewport in the OpenGL canvas. Dimensions are calculated
++  // as a percentage of the total canvas size.
++  SbVec2s view = PUBLIC(this)->getGLSize();
++  const int pixelarea =
++    int(float(this->axiscrossSize)/100.0f * So at Gui@Min(view[0], view[1]));
++#if 0 // middle of canvas
++  SbVec2s origin(view[0]/2 - pixelarea/2, view[1]/2 - pixelarea/2);
++#endif // middle of canvas
++#if 1 // lower right of canvas
++  SbVec2s origin(view[0] - pixelarea, 0);
++#endif // lower right of canvas
++  glViewport(origin[0], origin[1], pixelarea, pixelarea);
++
++
++
++  // Set up the projection matrix.
++  glMatrixMode(GL_PROJECTION);
++  glLoadIdentity();
++
++  const float NEARVAL = 0.1f;
++  const float FARVAL = 10.0f;
++  const float dim = NEARVAL * float(tan(M_PI / 8.0)); // FOV is 45� (45/360 = 1/8)
++  glFrustum(-dim, dim, -dim, dim, NEARVAL, FARVAL);
++
++
++  // Set up the model matrix.
++  glMatrixMode(GL_MODELVIEW);
++  glPushMatrix();
++  SbMatrix mx;
++  SoCamera * cam = PUBLIC(this)->getCamera();
++
++  // If there is no camera (like for an empty scene, for instance),
++  // just use an identity rotation.
++  if (cam) { mx = cam->orientation.getValue(); }
++  else { mx = SbMatrix::identity(); }
++
++  mx = mx.inverse();
++  mx[3][2] = -3.5; // Translate away from the projection point (along z axis).
++  glLoadMatrixf((float *)mx);
++
++
++  // Find unit vector end points.
++  SbMatrix px;
++  glGetFloatv(GL_PROJECTION_MATRIX, (float *)px);
++  SbMatrix comb = mx.multRight(px);
++
++  SbVec3f xpos;
++  comb.multVecMatrix(SbVec3f(1,0,0), xpos);
++  xpos[0] = (1 + xpos[0]) * view[0]/2;
++  xpos[1] = (1 + xpos[1]) * view[1]/2;
++  SbVec3f ypos;
++  comb.multVecMatrix(SbVec3f(0,1,0), ypos);
++  ypos[0] = (1 + ypos[0]) * view[0]/2;
++  ypos[1] = (1 + ypos[1]) * view[1]/2;
++  SbVec3f zpos;
++  comb.multVecMatrix(SbVec3f(0,0,1), zpos);
++  zpos[0] = (1 + zpos[0]) * view[0]/2;
++  zpos[1] = (1 + zpos[1]) * view[1]/2;
++
++
++  // Render the cross.
++  {
++    glLineWidth(2.0);
++
++    enum { XAXIS, YAXIS, ZAXIS };
++    int idx[3] = { XAXIS, YAXIS, ZAXIS };
++    float val[3] = { xpos[2], ypos[2], zpos[2] };
++
++    // Bubble sort.. :-}
++    if (val[0] < val[1]) { So at Gui@Swap(val[0], val[1]); So at Gui@Swap(idx[0], idx[1]); }
++    if (val[1] < val[2]) { So at Gui@Swap(val[1], val[2]); So at Gui@Swap(idx[1], idx[2]); }
++    if (val[0] < val[1]) { So at Gui@Swap(val[0], val[1]); So at Gui@Swap(idx[0], idx[1]); }
++    assert((val[0] >= val[1]) && (val[1] >= val[2])); // Just checking..
++
++    for (int i=0; i < 3; i++) {
++      glPushMatrix();
++      if (idx[i] == XAXIS) {                       // X axis.
++        glColor3f(0.500f, 0.125f, 0.125f);
++      } else if (idx[i] == YAXIS) {                // Y axis.
++        glRotatef(90, 0, 0, 1);
++        glColor3f(0.125f, 0.500f, 0.125f);
++      } else {                                     // Z axis.
++        glRotatef(-90, 0, 1, 0);
++        glColor3f(0.125f, 0.125f, 0.500f);
++      }
++      this->drawArrow();
++      glPopMatrix();
++    }
++  }
++
++  // Render axis notation letters ("X", "Y", "Z").
++  glMatrixMode(GL_PROJECTION);
++  glLoadIdentity();
++  glOrtho(0, view[0], 0, view[1], -1, 1);
++
++  glMatrixMode(GL_MODELVIEW);
++  glLoadIdentity();
++
++  GLint unpack;
++  glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack);
++  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
++
++  glColor3fv(SbVec3f(0.8f, 0.8f, 0.0f).getValue());
++
++  glRasterPos2d(xpos[0], xpos[1]);
++  glBitmap(8, 7, 0, 0, 0, 0, xbmp);
++  glRasterPos2d(ypos[0], ypos[1]);
++  glBitmap(8, 7, 0, 0, 0, 0, ybmp);
++  glRasterPos2d(zpos[0], zpos[1]);
++  glBitmap(8, 7, 0, 0, 0, 0, zbmp);
++
++  glPixelStorei(GL_UNPACK_ALIGNMENT, unpack);
++  glPopMatrix();
++
++  // Reset original state.
++
++  // FIXME: are these 3 lines really necessary, as we push
++  // GL_ALL_ATTRIB_BITS at the start? 20000604 mortene.
++  glDepthRange(depthrange[0], depthrange[1]);
++  glMatrixMode(GL_PROJECTION);
++  glLoadMatrixd(projectionmatrix);
++
++  glPopAttrib();
++}
++
++// Draw an arrow for the axis representation directly through OpenGL.
++void
++SoGuiExaminerViewerP::drawArrow(void)
++{
++  glBegin(GL_LINES);
++  glVertex3f(0.0f, 0.0f, 0.0f);
++  glVertex3f(1.0f, 0.0f, 0.0f);
++  glEnd();
++  glDisable(GL_CULL_FACE);
++  glBegin(GL_TRIANGLES);
++  glVertex3f(1.0f, 0.0f, 0.0f);
++  glVertex3f(1.0f - 1.0f / 3.0f, +0.5f / 4.0f, 0.0f);
++  glVertex3f(1.0f - 1.0f / 3.0f, -0.5f / 4.0f, 0.0f);
++  glVertex3f(1.0f, 0.0f, 0.0f);
++  glVertex3f(1.0f - 1.0f / 3.0f, 0.0f, +0.5f / 4.0f);
++  glVertex3f(1.0f - 1.0f / 3.0f, 0.0f, -0.5f / 4.0f);
++  glEnd();
++  glBegin(GL_QUADS);
++  glVertex3f(1.0f - 1.0f / 3.0f, +0.5f / 4.0f, 0.0f);
++  glVertex3f(1.0f - 1.0f / 3.0f, 0.0f, +0.5f / 4.0f);
++  glVertex3f(1.0f - 1.0f / 3.0f, -0.5f / 4.0f, 0.0f);
++  glVertex3f(1.0f - 1.0f / 3.0f, 0.0f, -0.5f / 4.0f);
++  glEnd();
++}
++
++// ************************************************************************
++
++// Rotate the camera by the given amount, then reposition it so we're
++// still pointing at the same focal point.
++void
++SoGuiExaminerViewerP::reorientCamera(const SbRotation & rot)
++{
++  SoCamera * cam = PUBLIC(this)->getCamera();
++  if (cam == NULL) return;
++
++  // Find global coordinates of focal point.
++  SbVec3f direction;
++  cam->orientation.getValue().multVec(SbVec3f(0, 0, -1), direction);
++  SbVec3f focalpoint = cam->position.getValue() +
++    cam->focalDistance.getValue() * direction;
++
++  // Set new orientation value by accumulating the new rotation.
++  cam->orientation = rot * cam->orientation.getValue();
++
++  // Reposition camera so we are still pointing at the same old focal point.
++  cam->orientation.getValue().multVec(SbVec3f(0, 0, -1), direction);
++  cam->position = focalpoint - cam->focalDistance.getValue() * direction;
++}
++
++// ************************************************************************
++
++// Uses the sphere sheet projector to map the mouseposition unto
++// a 3D point and find a rotation from this and the last calculated point.
++void
++SoGuiExaminerViewerP::spin(const SbVec2f & pointerpos)
++{
++  if (this->log.historysize < 2) return;
++  assert(this->spinprojector != NULL);
++
++  SbVec2s glsize(PUBLIC(this)->getGLSize());
++  SbVec2f lastpos;
++  lastpos[0] = float(this->log.position[1][0]) / float(So at Gui@Max((int)(glsize[0]-1), 1));
++  lastpos[1] = float(this->log.position[1][1]) / float(So at Gui@Max((int)(glsize[1]-1), 1));
++
++  this->spinprojector->project(lastpos);
++  SbRotation r;
++  this->spinprojector->projectAndGetRotation(pointerpos, r);
++  r.invert();
++  this->reorientCamera(r);
++
++  // Calculate an average angle magnitude value to make the transition
++  // to a possible spin animation mode appear smooth.
++
++  SbVec3f dummy_axis, newaxis;
++  float acc_angle, newangle;
++  this->spinincrement.getValue(dummy_axis, acc_angle);
++  acc_angle *= this->spinsamplecounter; // weight
++  r.getValue(newaxis, newangle);
++  acc_angle += newangle;
++
++  this->spinsamplecounter++;
++  acc_angle /= this->spinsamplecounter;
++  // FIXME: accumulate and average axis vectors aswell? 19990501 mortene.
++  this->spinincrement.setValue(newaxis, acc_angle);
++
++  // Don't carry too much baggage, as that'll give unwanted results
++  // when the user quickly trigger (as in "click-drag-release") a spin
++  // animation.
++  if (this->spinsamplecounter > 3) this->spinsamplecounter = 3;
++}
++
++// ************************************************************************
++
++// Calculate a zoom/dolly factor from the difference of the current
++// cursor position and the last.
++void
++SoGuiExaminerViewerP::zoomByCursor(const SbVec2f & thispos,
++                                   const SbVec2f & prevpos)
++{
++  // There is no "geometrically correct" value, 20 just seems to give
++  // about the right "feel".
++  SoGuiFullViewerP::zoom(PUBLIC(this)->getCamera(),
++                         (thispos[1] - prevpos[1]) * 20.0f);
++}
++
++// *************************************************************************
++// Methods used for spin animation tracking.
++
++// This method "clears" the mouse location log, used for spin
++// animation calculations.
++void
++SoGuiExaminerViewerP::clearLog(void)
++{
++  this->log.historysize = 0;
++}
++
++// This method adds another point to the mouse location log, used for spin
++// animation calculations.
++void
++SoGuiExaminerViewerP::addToLog(const SbVec2s pos, const SbTime time)
++{
++  // In case someone changes the const size setting at the top of this
++  // file too small.
++  assert (this->log.size > 2 && "mouse log too small!");
++
++  if (this->log.historysize > 0 && pos == this->log.position[0]) {
++#if SO at GUI@_DEBUG && 0 // debug
++    // This can at least happen under SoQt.
++    SoDebugError::postInfo("SoGuiExaminerViewerP::addToLog", "got position already!");
++#endif // debug
++    return;
++  }
++
++  int lastidx = this->log.historysize;
++  // If we've filled up the log, we should throw away the last item:
++  if (lastidx == this->log.size) { lastidx--; }
++
++  assert(lastidx < this->log.size);
++  for (int i = lastidx; i > 0; i--) {
++    this->log.position[i] = this->log.position[i-1];
++    this->log.time[i] = this->log.time[i-1];
++  }
++
++  this->log.position[0] = pos;
++  this->log.time[0] = time;
++  if (this->log.historysize < this->log.size)
++    this->log.historysize += 1;
++}
++
++// *************************************************************************
++
++// This method sets whether Motion3 events should affect the camera or
++// the model.
++void
++SoGuiExaminerViewerP::setMotion3OnCamera(SbBool enable)
++{
++  this->motion3OnCamera = enable;
++}
++
++// This method returns whether Motion3 events affects the camera or
++// the model.
++SbBool
++SoGuiExaminerViewerP::getMotion3OnCamera(void) const
++{
++  return this->motion3OnCamera;
++}
++
++// ************************************************************************
++
++// Set cursor graphics according to mode.
++void
++SoGuiExaminerViewerP::setCursorRepresentation(int modearg)
++{
++  if (!PUBLIC(this)->isCursorEnabled()) {
++    PUBLIC(this)->setComponentCursor(So at Gui@Cursor::getBlankCursor());
++    return;
++  }
++
++  switch (modearg) {
++  case SoGuiExaminerViewerP::INTERACT:
++    PUBLIC(this)->setComponentCursor(So at Gui@Cursor(So at Gui@Cursor::DEFAULT));
++    break;
++
++  case SoGuiExaminerViewerP::IDLE:
++  case SoGuiExaminerViewerP::DRAGGING:
++  case SoGuiExaminerViewerP::SPINNING:
++    PUBLIC(this)->setComponentCursor(So at Gui@Cursor::getRotateCursor());
++    break;
++
++  case SoGuiExaminerViewerP::ZOOMING:
++    PUBLIC(this)->setComponentCursor(So at Gui@Cursor::getZoomCursor());
++    break;
++
++  case SoGuiExaminerViewerP::SEEK_MODE:
++  case SoGuiExaminerViewerP::SEEK_WAIT_MODE:
++    PUBLIC(this)->setComponentCursor(So at Gui@Cursor(So at Gui@Cursor::CROSSHAIR));
++    break;
++
++  case SoGuiExaminerViewerP::PANNING:
++    PUBLIC(this)->setComponentCursor(So at Gui@Cursor::getPanCursor());
++    break;
++
++  default: assert(0); break;
++  }
++}
++
++#endif // DOXYGEN_SKIP_THIS
++
++// *************************************************************************
++
++#undef PRIVATE
++#undef PUBLIC
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiExaminerViewer.h.in
+@@ -0,0 +1,108 @@
++#ifndef SO at GUI@_EXAMINERVIEWER_H
++#define SO at GUI@_EXAMINERVIEWER_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/SbLinear.h>
++#include <Inventor/@Gui@/viewers/So at Gui@FullViewer.h>
++
++class SoSeparator;
++class SoSwitch;
++class SoTranslation;
++class SoScale;
++
++class So at Gui@ThumbWheel;
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@ExaminerViewer : public So at Gui@FullViewer {
++  SO at GUI@_OBJECT_HEADER(So at Gui@ExaminerViewer, So at Gui@FullViewer);
++
++public:
++  So at Gui@ExaminerViewer(@WIDGET@ parent = NULL,
++                        const char * name = NULL,
++                        SbBool embed = TRUE,
++                        So at Gui@FullViewer::BuildFlag flag = BUILD_ALL,
++                        So at Gui@Viewer::Type type = BROWSER);
++  ~So at Gui@ExaminerViewer();
++
++  void setAnimationEnabled(const SbBool enable);
++  SbBool isAnimationEnabled(void) const;
++
++  void stopAnimating(void);
++  SbBool isAnimating(void) const;
++
++  void setFeedbackVisibility(const SbBool enable);
++  SbBool isFeedbackVisible(void) const;
++
++  void setFeedbackSize(const int size);
++  int getFeedbackSize(void) const;
++
++  virtual void setViewing(SbBool enable);
++  virtual void setCamera(SoCamera * camera);
++  virtual void setCursorEnabled(SbBool enable);
++
++protected:
++  So at Gui@ExaminerViewer(@WIDGET@ parent,
++                        const char * name,
++                        SbBool embed,
++                        So at Gui@FullViewer::BuildFlag flag,
++                        So at Gui@Viewer::Type type,
++                        SbBool build);
++
++  virtual void leftWheelMotion(float val);
++  virtual void bottomWheelMotion(float val);
++  virtual void rightWheelMotion(float val);
++
++  virtual void createViewerButtons(@WIDGET@ parent, SbPList * buttonlist);
++
++  virtual const char * getDefaultWidgetName(void) const;
++  virtual const char * getDefaultTitle(void) const;
++  virtual const char * getDefaultIconTitle(void) const;
++
++  virtual SbBool processSoEvent(const SoEvent * const event);
++  virtual void setSeekMode(SbBool enable);
++  virtual void actualRedraw(void);
++
++  virtual void afterRealizeHook(void);
++
++private:
++  class So at Gui@ExaminerViewerP * pimpl;
++
++  friend class SoGuiExaminerViewerP;
++  friend class So at Gui@ExaminerViewerP;
++};
++
++#endif // ! SO at GUI@_EXAMINERVIEWER_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiExaminerViewerP.h.in
+@@ -0,0 +1,140 @@
++#ifndef SOGUIEXAMINERVIEWERP_H
++#define SOGUIEXAMINERVIEWERP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/SbLinear.h>
++#include <Inventor/SbTime.h>
++
++class So at Gui@ExaminerViewer;
++class SoCamera;
++
++// ************************************************************************
++
++// This class contains private data and methods used within the
++// SoGuiExaminerViewer class.
++
++class SoGuiExaminerViewerP
++{
++public:
++  ~SoGuiExaminerViewerP();
++
++  void genericConstructor(void);
++  void genericDestructor(void);
++
++  void setMotion3OnCamera(SbBool enable);
++  SbBool getMotion3OnCamera(void) const;
++
++  static void rotateCamera(SoCamera * cam, const SbVec3f & aroundaxis, const float delta);
++  float rotXWheelMotion(float value, float old);
++  float rotYWheelMotion(float value, float old);
++
++  void reorientCamera(const SbRotation & rotation);
++  void spin(const SbVec2f & mousepos);
++  void pan(const SbVec2f & mousepos, const SbVec2f & prevpos);
++  void zoom(const float diffvalue);
++  void zoomByCursor(const SbVec2f & mousepos, const SbVec2f & prevpos);
++
++  SbVec2f lastmouseposition;
++  SbPlane panningplane;
++
++  SbBool spinanimatingallowed;
++  SbVec2f lastspinposition;
++  int spinsamplecounter;
++  SbRotation spinincrement;
++  class SbSphereSheetProjector * spinprojector;
++
++  SbRotation spinRotation;
++
++  SbBool axiscrossEnabled;
++  int axiscrossSize;
++
++  void drawAxisCross(void);
++  static void drawArrow(void);
++
++  struct { // tracking mouse movement in a log
++    short size;
++    short historysize;
++    SbVec2s * position;
++    SbTime * time;
++  } log;
++
++  // The Microsoft Visual C++ v6.0 compiler needs a name on this class
++  // to be able to generate a constructor (which it wants to have for
++  // running the the SbVec2s constructors). So don't try to be clever
++  // and make it anonymous.
++  struct Pointer {
++    SbVec2s now, then;
++  } pointer;
++
++  SbBool button1down;
++  SbBool button3down;
++  SbBool ctrldown, shiftdown;
++
++  void clearLog(void);
++  void addToLog(const SbVec2s pos, const SbTime time);
++
++  SbTime prevRedrawTime;
++
++  SbBool motion3OnCamera;
++
++  enum ViewerMode {
++    IDLE,
++    INTERACT,
++    ZOOMING,
++    PANNING,
++    DRAGGING,
++    SPINNING,
++    SEEK_WAIT_MODE,
++    SEEK_MODE
++  } mode;
++
++  ViewerMode currentmode;
++  void setMode(const ViewerMode mode);
++
++  void setCursorRepresentation(int mode);
++
++protected:
++  SoGuiExaminerViewerP(So at Gui@ExaminerViewer * publ);
++  So at Gui@ExaminerViewer * pub;
++};
++
++// ************************************************************************
++
++#endif // ! SOGUIEXAMINERVIEWERP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiFlyViewer.cpp.in
+@@ -0,0 +1,1289 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/*!
++  \class So at Gui@FlyViewer Inventor/@Gui@/viewers/So at Gui@FlyViewer.h
++  \brief The So at Gui@FlyViewer class implements controls for moving
++  the camera in a "flying" motion.
++  \ingroup viewers
++
++  Controls:
++  <ul>
++
++  <li>Left mouse button increases the speed.</li>
++
++  <li>Middle mouse button decreases the speed.</li>
++
++  <li>Left and middle mouse button together sets the speed to zero.</li>
++
++  <li>"s" puts the viewer in seek mode. Click some geometry with the
++      left mouse button to start the seek zoom animation. (Hitting "s"
++      again before clicking will cancel the seek operation.)</li>
++
++  <li>"u" puts the viewer in up-vector pick mode. Click some geometry
++      with the left mouse button to set the camera's up-vector to the
++      normal vector of the face you pick.
++      (Hitting "u" again before clicking will cancel the pick operation.)</li>
++
++  <li>The control key stops the flying and lets you tilt the camera by moving
++      the pointer.</li>
++
++  </ul>
++*/
++
++/*
++  FIXME:
++  - animate camera when setting up-vector so the scene doesn't just
++    suddenly change.
++*/
++
++#include <so at gui@defs.h>
++#include <Inventor/@Gui@/viewers/So at Gui@FlyViewer.h>
++#include <Inventor/events/SoKeyboardEvent.h>
++#include <Inventor/events/SoLocation2Event.h>
++#include <Inventor/events/SoMouseButtonEvent.h>
++#include <Inventor/nodes/SoCamera.h>
++#include <Inventor/nodes/SoCallback.h>
++#include <Inventor/nodes/SoCoordinate3.h>
++#include <Inventor/nodes/SoSwitch.h>
++#include <Inventor/nodes/SoScale.h>
++#include <Inventor/nodes/SoTranslation.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/actions/SoSearchAction.h>
++#include <Inventor/actions/SoHandleEventAction.h>
++#include <Inventor/actions/SoGetBoundingBoxAction.h>
++#include <string.h> // strlen() etc
++#include <stdlib.h> // abs() 
++#include <Inventor/@Gui@/So at Gui@Cursor.h>
++
++
++// ************************************************************************
++
++#ifndef DOXYGEN_SKIP_THIS
++
++// FIXME: We should probably move this class out of this
++// impl-file. There is code here that could be factored out and reused
++// in other modules, for example camera handling. Now there is a
++// duplication with some of the code in So at Gui@ConstrainedViewerP, for
++// example. 20021017 rolvs
++class So at Gui@FlyViewerP {
++public:
++  So at Gui@FlyViewerP(So at Gui@FlyViewer * owner);
++  ~So at Gui@FlyViewerP();
++
++  enum ViewerMode {
++    FLYING, TILTING, WAITING_FOR_SEEK, WAITING_FOR_UP_PICK
++  };
++
++  void constructor(SbBool build);
++
++  void dolly(const float delta) const;
++  void updateCursorRepresentation(void); // in SoNativeFlyViewer.cpp
++  void setMode(ViewerMode newmode);
++  int getMode(void) { return this->viewermode; }
++
++#define SO at GUI@_MIN_STEP     0.2f
++#define SO at GUI@_INC_FACTOR   1.2f
++#define SO at GUI@_MAX_SPEED   20.0f
++
++  SbTime * lastrender;
++
++  float currentspeed;
++  
++  // Maximum speed, target for currentspeed during
++  // acceleration/decceleration.
++  float maxspeed; 
++
++  // Scales speed. Calculated in updateSpeedScalingFactor.
++  float speed_scaling_factor; 
++  
++  // Used to calculate a new max_speed, on the basis on 'where' we are
++  // in the speed landscape, see {increment|decrement}MaxSpeed(). 
++  int max_speed_factor; 
++
++  // Speed
++  void incrementMaxSpeed();
++  void decrementMaxSpeed();
++  void updateMaxSpeed();
++  void updateSpeedScalingFactor();
++  void stopMoving();
++
++  void updateSpeedIndicator(void);
++  void updateCameraPosition( SoCamera * camera, float speed, float dt ); 
++  void updateCameraOrientation( SoCamera * camera, 
++                                float d_tilt, 
++                                float d_pan, 
++                                float dt );
++  double calculateChangeInTime();
++  void  updateCurrentSpeed(double dt);
++
++
++  // Current keyboard state.
++  SbBool button1down;
++  SbBool button3down;
++  int lctrldown;
++  int rctrldown;
++  SbBool lshiftdown;
++  SbBool rshiftdown;
++
++  // View, speed display, renderingstate.
++  SoSearchAction * searcher;
++
++  SoNode * superimposition;
++  SoCoordinate3 * sgeometry;
++
++  SoScale * sscale;
++  SoScale * crossscale;
++
++  SoTranslation * stranslation;
++  SoTranslation * crossposition;
++
++  SoSwitch * smaxspeedswitch; 
++  SoSwitch * scurrentspeedswitch;
++  SoSwitch * crossswitch;
++
++  SoNode * getSuperimpositionNode(const char * name);
++
++  void superimpositionevent(SoAction * action);
++  static void superimposition_cb(void * closure, SoAction * action);
++
++
++  // 
++  float tilt_increment; // Angle-adjustment between View-up and direction 
++  float pan_increment;  // Rotation-adjustment around View-up
++
++  SbVec2s mouseloc;
++  SbVec2s lastpos;
++  SbVec2s tiltpos;
++
++  // FIXME: Refactor event handlers and PUBLIC(this)->processSoEvent
++  // in a way similar to that in SoGuiExaminerViewer, where only
++  // internal state is red/set. 20021017 rolvs
++  SbBool processKeyboardEvent(const SoKeyboardEvent * const kevt);
++  SbBool processMouseButtonEvent(const SoMouseButtonEvent * const mevt);
++  SbBool processLocation2Event(const SoLocation2Event * const levt);
++private:
++  So at Gui@FlyViewer * publ;
++  ViewerMode viewermode;
++};
++
++So at Gui@FlyViewerP::So at Gui@FlyViewerP(So at Gui@FlyViewer * owner)
++{
++  this->searcher = NULL;
++  this->publ = owner;
++  this->viewermode = FLYING;
++  this->currentspeed = 0.0f;
++  this->maxspeed = 0.0f;
++  this->speed_scaling_factor = 0.4f;
++  this->max_speed_factor = 0;
++  this->stranslation = NULL;
++  this->sscale = NULL;
++  this->button1down = FALSE;
++  this->button3down = FALSE;
++  this->lctrldown = 0;
++  this->rctrldown = 0;
++  this->lshiftdown = FALSE;
++  this->rshiftdown = FALSE;
++  this->lastrender = new SbTime;
++  this->tilt_increment = 0.0f;
++  this->pan_increment = 0.0f;
++}
++
++So at Gui@FlyViewerP::~So at Gui@FlyViewerP(void)
++{
++  if ( this->searcher != NULL )
++    delete this->searcher;
++  delete this->lastrender;
++
++  // superimposition unrefed in other destructor
++}
++
++#define PRIVATE(o) (o->pimpl)
++#define PUBLIC(o) (o->publ)
++
++
++// Common constructor code.
++void
++So at Gui@FlyViewerP::constructor(SbBool build)
++{
++  PUBLIC(this)->setClassName(PUBLIC(this)->getDefaultWidgetName());
++
++  static const char * superimposed[] = {
++    "#Inventor V2.1 ascii",
++    "",
++    "Separator {",
++    "  MaterialBinding {",
++    "    value OVERALL",
++    "  }",
++    "  OrthographicCamera {",
++    "    height 1",
++    "    nearDistance 0",
++    "    farDistance 1",
++    "  }",
++    "  DEF so at gui@->callback Callback { }",
++    "  Separator {",
++    "    DEF so at gui@->translation Translation {",
++    "      translation 0 0 0",
++    "    }",
++    "    DEF so at gui@->scale Scale {",
++    "      scaleFactor 1 1 1",
++    "    }",
++    "    DEF so at gui@->geometry Coordinate3 {",
++    "      point [",
++    "       -0.8 -0.04 0,",
++    "       -0.8  0    0,",
++    "       -0.8  0.04 0,",
++    "        0   -0.04 0,",
++    "        0    0    0,",
++    "        0    0.04 0,",
++    "        0.8 -0.04 0,",
++    "        0.8  0    0,",
++    "        0.8  0.04 0,", 
++    "        0    0.02 0,", // idx 9
++    "        0.8  0.02 0,",
++    "        0.8 -0.02 0,",
++    "        0   -0.02 0,",
++    "        0    0.01 0,", // idx 13
++    "        0.4  0.01 0,",
++    "        0.4 -0.01 0,",
++    "        0   -0.01 0",
++    "      ]",
++    "    }",
++    "    DEF so at gui@->maxspeedswitch Switch {",
++    "      whichChild -3",
++    // max speed indicator
++    "      Material {",
++    "        emissiveColor 1 0 0",
++    "      }",
++    "      IndexedFaceSet {",
++    "        coordIndex [",
++    "          12, 11, 10, 9, -1",
++    "        ]",
++    "      }",
++    "    }",
++    // the coordinate system
++    "    BaseColor {",
++    "      rgb 1 1 1",
++    "    }",
++    "    IndexedLineSet {",
++    "      coordIndex [",
++    "        0, 2, -1,",
++    "        3, 5, -1,",
++    "        6, 8, -1,",
++    "        1, 7, -1",
++    "      ]",
++    "    }",
++    // current speed indicator
++    "    DEF so at gui@->currentspeedswitch Switch {",
++    "      whichChild -3",
++    "      Material {",
++    "        emissiveColor 0 0 1",
++    "      }",
++    "      IndexedFaceSet {",
++    "        coordIndex [",
++    "          16, 15, 14, 13, -1",
++    "        ]",
++    "      }",
++    "    }",
++    "  }",
++    // cross
++    "  DEF so at gui@->crossswitch Switch {",
++    "    whichChild -1",
++    "    DEF so at gui@->crossposition Translation {",
++    "      translation 0 0 0",
++    "    }",
++    "    DEF so at gui@->crossscale Scale {",
++    "      scaleFactor 1 1 1",
++    "    }",
++    "    BaseColor {",
++    "      rgb 1 0 0",
++    "    }",
++    "    Coordinate3 {",
++    "      point [",
++    "        0 -1  0,",
++    "        0  1  0,",
++    "       -1  0  0,",
++    "        1  0  0",
++    "      ]",
++    "    }",
++    "    IndexedLineSet {",
++    "      coordIndex [",
++    "        0, 1, -1,",
++    "        2, 3, -1",
++    "      ]",
++    "    }",
++    "  }",
++    "}",
++    NULL
++  };
++
++  int i, bufsize;
++  for (i = bufsize = 0; superimposed[i]; i++)
++    bufsize += strlen(superimposed[i]) + 1;
++  char * buf = new char [bufsize + 1];
++  for (i = bufsize = 0; superimposed[i]; i++) {
++    strcpy(buf + bufsize, superimposed[i]);
++    bufsize += strlen(superimposed[i]);
++    buf[bufsize] = '\n';
++    bufsize++;
++  }
++  SoInput * input = new SoInput;
++  input->setBuffer(buf, bufsize);
++  SbBool ok = SoDB::read(input, this->superimposition);
++  assert(ok);
++  delete input;
++  delete [] buf;
++  this->superimposition->ref();
++
++
++  this->sscale = (SoScale *)
++    this->getSuperimpositionNode("so at gui@->scale");
++  this->stranslation = (SoTranslation *)
++    this->getSuperimpositionNode("so at gui@->translation");
++  this->sgeometry = (SoCoordinate3 *)
++    this->getSuperimpositionNode("so at gui@->geometry");
++  this->smaxspeedswitch = (SoSwitch *)
++    this->getSuperimpositionNode("so at gui@->maxspeedswitch");
++  this->scurrentspeedswitch = (SoSwitch *)
++    this->getSuperimpositionNode("so at gui@->currentspeedswitch");
++  this->crossswitch = (SoSwitch *)
++    this->getSuperimpositionNode("so at gui@->crossswitch");
++  this->crossposition = (SoTranslation *)
++    this->getSuperimpositionNode("so at gui@->crossposition");
++  this->crossscale = (SoScale *)
++    this->getSuperimpositionNode("so at gui@->crossscale");
++
++  SoCallback * cb = (SoCallback *)
++    this->getSuperimpositionNode("so at gui@->callback");
++  cb->setCallback(So at Gui@FlyViewerP::superimposition_cb, this);
++
++  this->updateSpeedIndicator();
++
++  PUBLIC(this)->addSuperimposition(this->superimposition);
++  PUBLIC(this)->setSuperimpositionEnabled(this->superimposition,TRUE);
++
++  if (build) {
++    @WIDGET@ viewer = PUBLIC(this)->buildWidget(PUBLIC(this)->getParentWidget());
++    PUBLIC(this)->setBaseWidget(viewer);
++  }
++}
++
++// This method dollies the camera back and forth in the scene.
++void
++So at Gui@FlyViewerP::dolly(const float delta) const
++{
++  SoCamera * const camera = PUBLIC(this)->getCamera();
++  if (camera == NULL) { return; } // if there's no scenegraph, for instance
++
++  SbPlane walkplane(PUBLIC(this)->getUpDirection(), 
++		    camera->position.getValue());
++
++  SbVec3f campos = camera->position.getValue();
++  SbVec3f camvec;
++  camera->orientation.getValue().multVec(SbVec3f(0, 0, -1), camvec);
++  SbLine cross(campos + camvec,
++                campos + camvec + PUBLIC(this)->getUpDirection());
++  SbVec3f intersect;
++  walkplane.intersect(cross, intersect);
++  SbVec3f dir = intersect - campos;
++  dir.normalize();
++
++  camera->position = campos - dir * delta;
++}
++
++// The viewer is a state machine, and all changes to the current state
++// are made through this call.
++void
++So at Gui@FlyViewerP::setMode(ViewerMode newmode)
++{
++  this->viewermode = newmode;
++  this->updateCursorRepresentation();
++}
++
++// This method locates a named node in the superimposed scene.
++SoNode *
++So at Gui@FlyViewerP::getSuperimpositionNode(const char * name)
++{
++  if (! this->searcher)
++    this->searcher = new SoSearchAction;
++  searcher->reset();
++  searcher->setName(SbName(name));
++  searcher->setInterest(SoSearchAction::FIRST);
++  searcher->setSearchingAll(TRUE);
++  searcher->apply(this->superimposition);
++  assert(searcher->getPath());
++  return searcher->getPath()->getTail();
++}
++
++SbBool
++So at Gui@FlyViewerP::processKeyboardEvent(const SoKeyboardEvent * const ke)
++{
++  assert( ke != NULL );
++  switch (ke->getState()) {
++  case SoButtonEvent::UP:
++    switch (ke->getKey()) {
++    case SoKeyboardEvent::U:
++      do {
++	// either to switch to up-vector pick mode, or back to fly
++	// mode if pick-mode already activated (ie cancel the
++	// up-vector pick operation)
++	SbBool uppickmode =
++	  this->getMode() == So at Gui@FlyViewerP::WAITING_FOR_UP_PICK;
++	this->setMode(uppickmode ? So at Gui@FlyViewerP::FLYING :
++			       So at Gui@FlyViewerP::WAITING_FOR_UP_PICK);
++
++        this->stopMoving();
++
++	this->updateSpeedIndicator();
++	PUBLIC(this)->scheduleRedraw();
++	return TRUE;
++      } while (FALSE);
++      break;
++      
++    case SoKeyboardEvent::S:
++      this->stopMoving();
++      this->updateSpeedIndicator();
++      PUBLIC(this)->scheduleRedraw();
++      return FALSE;
++      
++    case SoKeyboardEvent::LEFT_SHIFT:
++      this->lshiftdown = FALSE;
++      if (this->lshiftdown < 0) {
++#if SO at GUI@_DEBUG
++	SoDebugError::post("So at Gui@FlyViewerP::processKeyboardEvent",
++			   "left shift key count < 0");
++#endif
++	this->lshiftdown = 0;
++      }
++      break;
++    case SoKeyboardEvent::RIGHT_SHIFT:
++      this->rshiftdown = FALSE;
++      if (this->rshiftdown < 0) {
++#if SO at GUI@_DEBUG
++	SoDebugError::post("So at Gui@FlyViewerP::processKeyboardEvent",
++			   "right shift key count < 0");
++#endif
++	this->rshiftdown = 0;
++      }
++      break;
++    case SoKeyboardEvent::LEFT_CONTROL:
++      this->lctrldown -= 1;
++      if (this->lctrldown < 0) {
++#if SO at GUI@_DEBUG
++	SoDebugError::post("So at Gui@FlyViewerP::processKyeboardEvent",
++			   "left control key count < 0");
++#endif
++	this->lctrldown = 0;
++      }
++      break;
++    case SoKeyboardEvent::RIGHT_CONTROL:
++      this->rctrldown -= 1;
++      if (this->rctrldown < 0) {
++#if SO at GUI@_DEBUG
++	SoDebugError::post("So at Gui@FlyViewerP::processKyeboardEvent",
++			   "right control key count < 0");
++#endif
++	this->rctrldown = 0;
++      }
++      break;
++    default:
++      break;
++    }
++    break;
++  case SoButtonEvent::DOWN:
++    switch (ke->getKey()) {
++    case SoKeyboardEvent::LEFT_SHIFT:
++      this->lshiftdown += 1;
++      if (this->lshiftdown > 2) {
++#if SO at GUI@_DEBUG
++	SoDebugError::post("So at Gui@FlyViewerP::processKeyboardEvent",
++			   "left shift key count > 2");
++#endif
++	this->lshiftdown = 2;
++      }
++      break;
++    case SoKeyboardEvent::RIGHT_SHIFT:
++      this->rshiftdown += 1;
++      if (this->rshiftdown > 2) {
++#if SO at GUI@_DEBUG
++	SoDebugError::post("So at Gui@FlyViewerP::processKeyboardEvent",
++			   "right shift key count > 2");
++#endif
++	this->rshiftdown = 2;
++      }
++      break;
++    case SoKeyboardEvent::LEFT_CONTROL:
++      this->lctrldown += 1;
++      if (this->lctrldown > 2) {
++#if SO at GUI@_DEBUG
++	SoDebugError::post("So at Gui@FlyViewerP::processKeyboardEvent",
++			   "left control key count > 2");
++#endif
++	this->lctrldown = 2;
++      }
++      break;
++    case SoKeyboardEvent::RIGHT_CONTROL:
++      this->rctrldown += 1;
++      if (this->rctrldown > 2) {
++#if SO at GUI@_DEBUG
++	SoDebugError::post("So at Gui@FlyViewer::processSoEvent",
++			   "right control key count > 2");
++#endif
++	this->rctrldown = 2;
++      }
++      break;
++    default:
++      break; 
++    }
++    break;
++  default:
++    break;
++  }
++
++  if ((this->getMode() == So at Gui@FlyViewerP::FLYING) &&
++      (this->lctrldown || this->rctrldown)) {
++    this->setMode(So at Gui@FlyViewerP::TILTING);
++    
++    this->tiltpos = this->mouseloc;
++    this->lastpos = this->mouseloc;
++
++    this->stopMoving();
++    this->updateSpeedIndicator();
++    this->crossswitch->whichChild.setValue(SO_SWITCH_ALL);
++    PUBLIC(this)->scheduleRedraw();
++    // NOTE; this could be optimized to only draw the superimposition in
++    // question if speed is zero.
++  } else if ((this->getMode() == So at Gui@FlyViewerP::TILTING) &&
++	     !this->lctrldown && !this->rctrldown) {
++    this->setMode(So at Gui@FlyViewerP::FLYING);
++    assert(this->crossswitch != NULL);
++    this->crossswitch->whichChild.setValue(SO_SWITCH_NONE);
++    PUBLIC(this)->scheduleRedraw();
++  }
++  return FALSE;
++}
++
++
++SbBool
++So at Gui@FlyViewerP::processMouseButtonEvent( const SoMouseButtonEvent * const me )
++{
++  assert( me != NULL );
++  
++  // FIXME: only for fly mode
++  switch (this->getMode()) {
++  case So at Gui@FlyViewerP::WAITING_FOR_UP_PICK:
++    if ((me->getButton() == SoMouseButtonEvent::BUTTON1) &&
++	(me->getState() == SoButtonEvent::DOWN)) {
++      PUBLIC(this)->findUpDirection(me->getPosition());
++      this->setMode(So at Gui@FlyViewerP::FLYING);
++      return TRUE;
++    }
++    break;
++  case So at Gui@FlyViewerP::FLYING:
++    switch (me->getButton()) {
++    case SoMouseButtonEvent::BUTTON1:
++
++      switch (me->getState()) {
++        
++      case SoButtonEvent::DOWN:
++        // Incrementing speed.
++	this->button1down = TRUE;
++	if (this->button3down) {
++          this->stopMoving();
++	} 
++        else {
++          this->incrementMaxSpeed();
++	}
++	this->updateSpeedIndicator();
++	PUBLIC(this)->scheduleRedraw();
++	return TRUE;
++      case SoButtonEvent::UP:
++	this->button1down = FALSE;
++	return TRUE;
++      default:
++	break;
++      }
++      break;
++
++    case SoMouseButtonEvent::BUTTON3:
++
++      switch (me->getState()) {
++      case SoButtonEvent::DOWN:
++	this->button3down = TRUE;
++	
++        if (this->button1down) {
++          this->stopMoving();
++	} 
++        else
++          this->decrementMaxSpeed();
++     
++	this->updateSpeedIndicator();
++	PUBLIC(this)->scheduleRedraw();
++	return TRUE;
++      case SoButtonEvent::UP:
++	this->button3down = FALSE;
++	return TRUE;
++      default:
++	break;
++      }
++      break;
++    default:
++      break;
++    }
++  default:
++    break;
++  }
++  return FALSE;
++}
++
++SbBool
++So at Gui@FlyViewerP::processLocation2Event(const SoLocation2Event * const lev)
++{  
++  this->mouseloc = lev->getPosition();
++
++  if (this->getMode() == So at Gui@FlyViewerP::TILTING) {
++
++    float pan = (this->lastpos[0] - this->mouseloc[0])/100.0f;
++    float tilt = (this->lastpos[1] - this->mouseloc[1])/100.0f;
++    
++    SoCamera * camera = PUBLIC(this)->getCamera();
++    if (camera == NULL) 
++      return TRUE; // probably sceneless
++    
++    this->updateCameraOrientation( camera, tilt, pan, 1.0f );
++    this->lastpos = this->mouseloc;
++  }
++
++  // FIXME: The size of the glcanvas only changes when the viewer is
++  // resized. The GLSize should be set from the FlyViewer, to remove
++  // the dependency on the PUBLIC(this) class. 20021021 rolvs
++  SbVec2s glsize( PUBLIC(this)->getGLSize() );
++
++  // NOTE: The values are normalized, so that the FlyViewer behaves
++  // the same way no matter the screen-size. The old way to do it made
++  // the possible range of pan and tilt increment depend on the canvas
++  // size. 20021022 rolvs.
++  this->pan_increment = 0.5f - float(this->mouseloc[0])/glsize[0]; 
++  this->tilt_increment = 0.5f - float(this->mouseloc[1])/glsize[1];
++
++  return TRUE;
++}
++
++void
++So at Gui@FlyViewerP::superimpositionevent(SoAction * action)
++{
++  if (!action->isOfType(SoGLRenderAction::getClassTypeId())) return;
++  SbViewportRegion vpRegion =
++    ((SoGLRenderAction *) action)->getViewportRegion();
++  SbVec2s viewport = vpRegion.getViewportSizePixels();
++  float aspect = float(viewport[0]) / float(viewport[1]);
++  float factorx = 1.0f/float(viewport[1]) * 220.0f;
++  float factory = factorx;
++  if (aspect > 1.0f) {
++    this->stranslation->translation.setValue(SbVec3f(0.0f, -0.4f, 0.0f));
++  } else {
++    this->stranslation->translation.setValue(SbVec3f(0.0f, -0.4f / aspect, 0.0f));
++    factorx /= aspect;
++    factory /= aspect;
++  }
++  if (viewport[0] > 500)
++    factorx *= 500.0f / 400.0f;
++  else
++    factorx *= float(viewport[0]) / 400.0f;
++  this->sscale->scaleFactor.setValue(SbVec3f(factorx, factory, 1.0f));
++
++  if (this->getMode() == TILTING) {
++    assert(this->crossposition != NULL);
++    assert(this->crossscale != NULL);
++    float tx = float(this->tiltpos[0]-float(viewport[0])/2.0f)/(float(viewport[0]));
++    float ty = float(this->tiltpos[1]-float(viewport[1])/2.0f)/(float(viewport[1]));
++    if (aspect > 1.0f) tx *= aspect;
++    else ty /= aspect;
++    this->crossposition->translation.setValue(SbVec3f(tx, ty, 0));
++
++    float sx = (1.0f/float(viewport[0])) * 15.0f;
++    float sy = (1.0f/float(viewport[1])) * 15.0f;
++    if (aspect > 1.0f) sx *= aspect;
++    else sy /= aspect;
++    this->crossscale->scaleFactor.setValue(SbVec3f(sx, sy, 0));
++  }
++}
++
++void
++So at Gui@FlyViewerP::superimposition_cb(void * closure, SoAction * action)
++{
++  assert(closure != NULL);
++  ((So at Gui@FlyViewerP *) closure)->superimpositionevent(action);
++}
++
++void
++So at Gui@FlyViewerP::updateSpeedIndicator(void)
++{
++  assert(this->sgeometry != NULL);
++
++  SbVec3f * points = this->sgeometry->point.startEditing();
++
++  if (points[10][0] == 0.0f)
++    this->smaxspeedswitch->whichChild.setValue(SO_SWITCH_ALL);
++  if (points[14][0] == 0.0f)
++    this->scurrentspeedswitch->whichChild.setValue(SO_SWITCH_ALL);
++  points[10][0] = this->maxspeed / (SO at GUI@_MAX_SPEED / 0.8f);
++  points[11][0] = this->maxspeed / (SO at GUI@_MAX_SPEED / 0.8f);
++  points[14][0] = this->currentspeed / (SO at GUI@_MAX_SPEED / 0.8f);
++  points[15][0] = this->currentspeed / (SO at GUI@_MAX_SPEED / 0.8f);
++  this->sgeometry->point.finishEditing();
++
++  if (this->maxspeed == 0.0f)
++    this->smaxspeedswitch->whichChild.setValue(SO_SWITCH_NONE);
++  if (this->currentspeed == 0.0f)
++    this->scurrentspeedswitch->whichChild.setValue(SO_SWITCH_NONE);
++}
++
++double So at Gui@FlyViewerP::calculateChangeInTime()
++{
++  SbTime thisrender; 
++  thisrender.setToTimeOfDay();
++
++  if (this->currentspeed == 0.0f)
++    this->lastrender->setValue(thisrender.getValue() - 0.01);
++
++  // We've had a report on Coin-support that floats may have too low
++  // precision for the subtraction of these two values (ie it becomes
++  // zero), so don't cast to float.
++  //
++  // FIXME: it doesn't sound likely that this was the real cause of
++  // the problem. First of all, it seems improbably that precision
++  // could be so bad for floats, as the time between render frames
++  // should almost be guaranteed to be milliseconds, at least.  It is
++  // suspicious that the error only shows up with the Intel C++
++  // compiler, and not when the reported built with MSVC++ instead.
++  //
++  // Second, the fix is not sufficient. What if the
++  // SbTime::getTimeOfDay() resolution is too low on the particular
++  // system, so we often get zero difference here? That case must be
++  // handled, and from the original bug report, it sounds like it
++  // isn't, which is a separate bug in itself.
++  //
++  // Third, what's up with that magic multiplication factor of 10?
++  // That doesn't seem to make sense.
++  //
++  // 20061212 mortene.
++
++  // This is only a problem on release builds which makes it sound
++  // like it's just some value that is not properly
++  // initialized. (20061212 frodo)
++
++  double t = (thisrender.getValue() - this->lastrender->getValue()) * 10.0;
++
++  if (t >= 1.0) 
++    t = 1.0;
++
++  return t;
++}
++
++void So at Gui@FlyViewerP::updateCurrentSpeed(double dt)
++{
++  float speedscale = 
++    1.0f - (this->pan_increment * this->pan_increment 
++            + this->tilt_increment * this->tilt_increment);
++  
++  // NOTE: I don't believe that this boundary condition could ever
++  // happen. 20021022 rolvs
++  if (speedscale < 0.0f)
++    speedscale = 0.0f;
++  
++  this->currentspeed +=
++    (((this->currentspeed +
++       this->maxspeed * speedscale) / 2.0f) - 
++     this->currentspeed) * dt;
++}
++
++void So at Gui@FlyViewerP::updateCameraPosition(SoCamera * camera, 
++                                             float current_speed,
++                                             float dt)
++{
++  assert(camera != NULL);
++  SbVec3f dir;
++  camera->orientation.getValue().multVec(SbVec3f(0, 0, -1), dir);
++  dir.normalize();
++  camera->position.setValue(camera->position.getValue() +
++                            dir * (current_speed * dt));
++}
++ 
++void So at Gui@FlyViewerP::updateCameraOrientation(SoCamera * camera, 
++                                                float d_tilt, 
++                                                float d_pan, 
++                                                float dt)
++{
++  assert(camera != NULL);
++  // FIXME: Make sure that the angle between direction and up-vector
++  // stays larger than zero, or else it gets 'locked' in an undefined
++  // state and starts to act weird. This should probably be done in
++  // parent class. 20021017 rolvs
++  PUBLIC(this)->tiltCamera(d_tilt * dt);
++  
++  camera->orientation = camera->orientation.getValue() *
++    SbRotation(PUBLIC(this)->getUpDirection(), d_pan * dt);
++}
++
++void
++So at Gui@FlyViewerP::incrementMaxSpeed(void)
++{
++  this->max_speed_factor++;
++  this->updateMaxSpeed();
++}
++
++
++void
++So at Gui@FlyViewerP::decrementMaxSpeed(void)
++{	
++  this->max_speed_factor--;
++  this->updateMaxSpeed();
++}
++
++
++void 
++So at Gui@FlyViewerP::updateSpeedScalingFactor(void)
++{
++  SoNode * n = PUBLIC(this)->getSceneGraph();
++  if(n == NULL)
++    return; // Scenegraph not set yet?
++
++  SoGetBoundingBoxAction bbact(PUBLIC(this)->getViewportRegion());
++  bbact.apply(n);
++  
++  SbBox3f bbox = bbact.getBoundingBox();
++  float bbox_diagonal = (bbox.getMax() - bbox.getMin()).length();
++
++  // FIXME: It should be possible to create a simple scaling function,
++  // based on some logaritmic evaluation. 20021017 rolvs.
++  if (bbox_diagonal > 100)
++    this->speed_scaling_factor = 1.0f; // log(bbox_diagonal);
++  else if (bbox_diagonal > 10 && bbox_diagonal < 100)
++    this->speed_scaling_factor = 0.4f; 
++  else if (bbox_diagonal > 1 && bbox_diagonal < 10)
++    this->speed_scaling_factor = 0.3f; 
++  else if (bbox_diagonal > 0.1 && bbox_diagonal < 1)
++    this->speed_scaling_factor = 0.1f; 
++  else
++    this->speed_scaling_factor = 0.1f * bbox_diagonal;
++}
++
++void So at Gui@FlyViewerP::stopMoving(void)
++{
++  this->maxspeed = 0.0f;
++  this->currentspeed = 0.0f; 
++  this->max_speed_factor = 0;
++}
++
++void So at Gui@FlyViewerP::updateMaxSpeed(void)
++{
++  if (this->max_speed_factor == 0) {
++    this->stopMoving();
++    return;
++  }
++
++  // FIXME: Move this methodcall so that it is called only
++  // once. (e.g. when scene graph is set) 20021021 rolvs
++  this->updateSpeedScalingFactor();
++
++  this->maxspeed = 
++    this->max_speed_factor 
++    * float(pow(SO at GUI@_INC_FACTOR, abs( this->max_speed_factor)))
++    * this->speed_scaling_factor;
++
++  if (this->maxspeed > SO at GUI@_MAX_SPEED)
++    this->maxspeed = SO at GUI@_MAX_SPEED;
++  else if (this->maxspeed < -1*SO at GUI@_MAX_SPEED)
++    this->maxspeed = -1 * SO at GUI@_MAX_SPEED;
++}
++
++
++
++// Set cursor graphics according to mode.
++void
++So at Gui@FlyViewerP::updateCursorRepresentation(void)
++{
++  if (!PUBLIC(this)->isCursorEnabled()) {
++    PUBLIC(this)->setComponentCursor(So at Gui@Cursor::getBlankCursor());
++    return;
++  }
++
++  switch (this->viewermode) {
++  case So at Gui@FlyViewerP::FLYING:
++    PUBLIC(this)->setComponentCursor(So at Gui@Cursor(So at Gui@Cursor::DEFAULT));
++    break;
++
++  case So at Gui@FlyViewerP::WAITING_FOR_SEEK:
++    PUBLIC(this)->setComponentCursor(So at Gui@Cursor(So at Gui@Cursor::CROSSHAIR));
++    break;
++
++  case So at Gui@FlyViewerP::WAITING_FOR_UP_PICK:
++    PUBLIC(this)->setComponentCursor(So at Gui@Cursor(So at Gui@Cursor::UPARROW));
++    break;
++
++  case So at Gui@FlyViewerP::TILTING:
++    PUBLIC(this)->setComponentCursor(So at Gui@Cursor::getPanCursor());
++    break;
++
++  default:
++    assert(0 && "unknown mode");
++    break;
++  }
++}
++
++#endif // DOXYGEN_SKIP_THIS
++
++// ************************************************************************
++
++SO at GUI@_OBJECT_SOURCE(So at Gui@FlyViewer);
++
++// ************************************************************************
++
++/*!
++  Public constructor.
++*/
++So at Gui@FlyViewer::So at Gui@FlyViewer(@WIDGET@ parent,
++                                   const char * name, 
++                                   SbBool embed, 
++                                   So at Gui@FullViewer::BuildFlag flag,
++                                   So at Gui@Viewer::Type type)
++  : inherited(parent, name, embed, flag, type, FALSE)
++{
++  PRIVATE(this) = new So at Gui@FlyViewerP(this);
++  PRIVATE(this)->constructor(TRUE);
++}
++
++// ************************************************************************
++
++/*!
++  Protected constructor, used by viewer components derived from the
++  So at Gui@FlyViewer.
++*/
++So at Gui@FlyViewer::So at Gui@FlyViewer(@WIDGET@ parent,
++                                   const char * const name,
++                                   SbBool embed, 
++                                   So at Gui@FullViewer::BuildFlag flag, 
++                                   So at Gui@Viewer::Type type, 
++                                   SbBool build)
++  : inherited(parent, name, embed, flag, type, FALSE)
++{
++  PRIVATE(this) = new So at Gui@FlyViewerP(this);
++  PRIVATE(this)->constructor(build);
++}
++
++// ************************************************************************
++
++/*!
++  Virtual constructor.
++*/
++So at Gui@FlyViewer::~So at Gui@FlyViewer()
++{
++  if (PRIVATE(this)->superimposition != NULL) {
++    this->removeSuperimposition(PRIVATE(this)->superimposition);
++    PRIVATE(this)->superimposition->unref();
++    PRIVATE(this)->superimposition = NULL;
++  }
++  delete PRIVATE(this);
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@FlyViewer::setViewing(SbBool enable)
++{
++  if (enable != this->isViewing())
++    PRIVATE(this)->stopMoving();
++
++  inherited::setViewing(enable);
++  this->setSuperimpositionEnabled(PRIVATE(this)->superimposition, enable);
++  this->scheduleRedraw();
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@FlyViewer::resetToHomePosition(void)
++{
++  PRIVATE(this)->stopMoving();
++  inherited::resetToHomePosition();
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@FlyViewer::viewAll(void)
++{
++  PRIVATE(this)->stopMoving();
++  inherited::viewAll();
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@FlyViewer::setCamera(SoCamera * camera)
++{
++  PRIVATE(this)->stopMoving();
++
++  inherited::setCamera(camera);
++  // FIXME: do something with up-direction? 
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@FlyViewer::setCursorEnabled(SbBool enable)
++{
++  inherited::setCursorEnabled(enable);
++  PRIVATE(this)->updateCursorRepresentation();
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@FlyViewer::setCameraType(SoType type)
++{
++  PRIVATE(this)->stopMoving();
++  inherited::setCameraType(type);
++  // FIXME: what else? 20010907 mortene.
++}
++
++// ************************************************************************
++
++// doc in super
++const char *
++So at Gui@FlyViewer::getDefaultWidgetName(void) const
++{
++  static const char defaultWidgetName[] = "So at Gui@FlyViewer";
++  return defaultWidgetName;
++}
++
++// ************************************************************************
++
++// doc in super
++const char *
++So at Gui@FlyViewer::getDefaultTitle(void) const
++{
++  static const char defaultTitle[] = "Fly Viewer";
++  return defaultTitle;
++}
++
++// ************************************************************************
++
++// doc in super
++const char *
++So at Gui@FlyViewer::getDefaultIconTitle(void) const
++{
++  static const char defaultIconTitle[] = "Fly Viewer";
++  return defaultIconTitle;
++}
++
++// ************************************************************************
++
++// Documented in superclass.
++SbBool
++So at Gui@FlyViewer::processSoEvent(const SoEvent * const event)
++{
++  // FIXME: Refactor the event-handling so that it uses the same
++  // strategy as in So at Gui@ExaminerViewer, where the event-handler
++  // only checks the state and the mode from that. 20021016 rolvs.
++
++  // We're in "interact" mode (ie *not* the camera modification mode),
++  // so don't handle the event here. It should either be forwarded to
++  // the scenegraph, or caught by So at Gui@Viewer::processSoEvent() if
++  // it's an ESC and ALT press (to switch modes).
++  if (!this->isViewing()) { return inherited::processSoEvent(event); }
++
++  // Events when in "ready-to-seek" mode are ignored, except those
++  // which influence the seek mode itself -- these are handled further
++  // up the inheritance hierarchy.
++  if (this->isSeekMode()) { return inherited::processSoEvent(event); }
++  
++  // FIXME: There is more parts of the code in
++  // So at Gui@*FlyViewer::processEvent that should go in to the
++  // processKeyboardEvent function; to be fixed later. 
++  // 20021015 rolvs
++
++  // Keyboard handling
++  if (event->isOfType(SoKeyboardEvent::getClassTypeId())) {
++    SbBool result =
++      PRIVATE(this)->processKeyboardEvent( (SoKeyboardEvent*)event );
++
++    if( result ){
++      return TRUE;
++    }
++    // Else: Do nothing, and proceed as usual
++  }
++
++  // Mousebutton handling
++  // See FIXME and comment for keyboardhandler.
++  else if (event->isOfType(SoMouseButtonEvent::getClassTypeId())) {
++    // FIXME: only for fly mode
++    const SoMouseButtonEvent * const me = 
++      (const SoMouseButtonEvent *const) event;
++    SbBool result = PRIVATE( this )->processMouseButtonEvent( me );
++    if( result ) 
++      return TRUE;
++  }
++
++  else if (event->isOfType(SoLocation2Event::getClassTypeId())) {
++    const SoLocation2Event * const le = 
++      (const SoLocation2Event * const) event;
++    SbBool result = PRIVATE( this )->processLocation2Event( le );
++    if( result ) 
++      return TRUE;
++  }
++
++  return inherited::processSoEvent(event);
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@FlyViewer::setSeekMode(SbBool enable)
++{
++  // Note: this method is almost identical to the setSeekMode() in the
++  // So at Gui@ExaminerViewer, so migrate any changes.
++
++#if SO at GUI@_DEBUG
++  if (enable == this->isSeekMode()) {
++    SoDebugError::postWarning("So at Gui@FlyViewer::setSeekMode",
++                              "seek mode already %sset", enable ? "" : "un");
++    return;
++  }
++#endif // SO at GUI@_DEBUG
++
++  // FIXME: what if we're in the middle of a seek already? 20010910 mortene.
++  // larsa - either stop the seek (on false) or reset timer to two new secs
++
++  inherited::setSeekMode(enable);
++  PRIVATE(this)->setMode(enable ? So at Gui@FlyViewerP::WAITING_FOR_SEEK :
++                            So at Gui@FlyViewerP::FLYING);
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@FlyViewer::actualRedraw(void)
++{
++  if (!this->isViewing()) {
++    inherited::actualRedraw();
++    return;
++  }
++
++  switch (PRIVATE(this)->getMode()) {
++  case So at Gui@FlyViewerP::FLYING:
++    {
++      PRIVATE(this)->updateCurrentSpeed(PRIVATE(this)->calculateChangeInTime());
++      PRIVATE(this)->updateSpeedIndicator();
++
++      SbTime thisrender; 
++      thisrender.setToTimeOfDay();
++
++      if (PRIVATE(this)->currentspeed != 0.0f) {
++        // We've had a report on Coin-support that floats may have too
++        // low precision for the subtraction of these two values (ie
++        // it becomes zero), so don't cast to float.
++        // 
++        // Note: there's some additional information about this, see
++        // the FIXME comment in the
++        // So at Gui@FlyViewerP::calculateChangeInTime() function.
++        double t = (thisrender.getValue() -
++                    PRIVATE(this)->lastrender->getValue()) * 2.0;
++        if (t > 0.0) {
++          SoCamera * camera = this->getCamera();
++
++          if (camera){ // could be a sceneless viewer
++            PRIVATE(this)->updateCameraPosition
++              ( camera,
++                PRIVATE(this)->currentspeed*
++                PRIVATE(this)->speed_scaling_factor,
++                t );
++            PRIVATE(this)->updateCameraOrientation
++              ( camera, 
++                PRIVATE(this)->tilt_increment, 
++                PRIVATE(this)->pan_increment, 
++                t );
++          }
++        }
++      }
++      
++      inherited::actualRedraw();
++      
++      PRIVATE(this)->lastrender->setValue(thisrender.getValue());
++      
++      if (PRIVATE(this)->currentspeed != 0.0f ||
++          PRIVATE(this)->maxspeed != 0.0f)
++        this->scheduleRedraw();
++    }
++    break;
++  default:
++    inherited::actualRedraw();
++    break;
++  }
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@FlyViewer::rightWheelMotion(float value)
++{
++  PRIVATE(this)->dolly(value - this->getRightWheelValue());
++  inherited::rightWheelMotion(value);
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@FlyViewer::afterRealizeHook(void)
++{
++  PRIVATE(this)->updateCursorRepresentation();
++  inherited::afterRealizeHook();
++}
++
++// ************************************************************************
++
++#undef PRIVATE
++#undef PUBLIC
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiFlyViewer.h.in
+@@ -0,0 +1,87 @@
++#ifndef SO at GUI@_FLYVIEWER_H
++#define SO at GUI@_FLYVIEWER_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.h>
++
++// ************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@FlyViewer : public So at Gui@ConstrainedViewer {
++  SO at GUI@_OBJECT_HEADER(So at Gui@FlyViewer, So at Gui@ConstrainedViewer);
++
++public:
++  So at Gui@FlyViewer(@WIDGET@ parent = NULL,
++                   const char * name = NULL, 
++                   SbBool embed = TRUE, 
++                   So at Gui@FullViewer::BuildFlag flag = BUILD_ALL,
++                   So at Gui@Viewer::Type type = BROWSER);
++  ~So at Gui@FlyViewer();
++
++  virtual void setViewing(SbBool enable);
++  virtual void viewAll(void);
++  virtual void resetToHomePosition(void);
++  virtual void setCamera(SoCamera * camera);
++  virtual void setCursorEnabled(SbBool enable);
++  virtual void setCameraType(SoType type);
++
++protected:
++  So at Gui@FlyViewer(@WIDGET@ parent,
++                   const char * const name, 
++                   SbBool embed, 
++                   So at Gui@FullViewer::BuildFlag flag, 
++                   So at Gui@Viewer::Type type, 
++                   SbBool build);
++
++  virtual const char * getDefaultWidgetName(void) const;
++  virtual const char * getDefaultTitle(void) const;
++  virtual const char * getDefaultIconTitle(void) const;
++
++  virtual SbBool processSoEvent(const SoEvent * const event);
++  virtual void setSeekMode(SbBool enable);
++  virtual void actualRedraw(void);
++
++  virtual void rightWheelMotion(float value);
++
++  virtual void afterRealizeHook(void);
++
++private:
++  class So at Gui@FlyViewerP * pimpl;
++  friend class So at Gui@FlyViewerP;
++};
++
++// ************************************************************************
++
++#endif // ! SO at GUI@_FLYVIEWER_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiFullViewer.cpp.in
+@@ -0,0 +1,1648 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// This file contains the generic, "templatize-able" parts of the
++// So*FullViewer sourcecode.
++
++/*!
++  \class So at Gui@FullViewer So at Gui@FullViewer.h Inventor/@Gui@/viewers/So at Gui@FullViewer.h
++  \brief The So at Gui@FullViewer class adds some user interface components to the viewer canvas.
++  \ingroup components viewers
++
++  The So at Gui@FullViewer is an abstract viewer class which extends it's
++  superclass (the basic So at Gui@Viewer class) with two major user
++  interface additions:
++
++  <ul>
++
++  <li>decorations around the render canvas, with buttons and
++  thumbwheels to control camera interaction and various other aspects
++  of model / scene viewing</li>
++
++  <li>a popup menu, invoked with the right mouse button, which
++  controls yet more aspects of the rendering and the viewer</li>
++
++  </ul>
++
++  The user interface features listed above are the common parts of the
++  user interfaces of the So at Gui@FullViewer's non-abstract subclasses.
++
++  For "real" application programs, the viewers / components from this
++  class onwards and further down in the inheritance hierarchy is
++  usually not all that interesting, as they enforces too much extra
++  user interface cruft not compatible with the look and feel of the
++  other parts of the application user interface. So most "real"
++  applications will use either the So at Gui@Viewer or the
++  So at Gui@RenderArea as their base-level component, and then inherit
++  one of these down into one's own "proper" viewer classes.
++
++  The non-abstract subclasses of the So at Gui@FullViewer class are
++  viewer components often used as a test-bed for prototyping / rapid
++  application development when doing quick testing of scenes,
++  stand-alone 3D-models, animation techniques, etc etc.
++
++
++  \sa So at Gui@ConstrainedViewer, So at Gui@ExaminerViewer, So at Gui@PlaneViewer
++*/
++
++
++// *************************************************************************
++
++#include <float.h>
++
++#include <Inventor/@Gui@/viewers/So at Gui@FullViewer.h>
++#include <Inventor/@Gui@/viewers/So at Gui@FullViewerP.h>
++#include <Inventor/@Gui@/widgets/So at Gui@PopupMenu.h>
++#include <so at gui@defs.h>
++
++#include <Inventor/events/SoMouseButtonEvent.h>
++#include <Inventor/events/SoKeyboardEvent.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/nodes/SoOrthographicCamera.h>
++#include <Inventor/nodes/SoPerspectiveCamera.h>
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++// ************************************************************************
++
++#define PRIVATE(o) (o->pimpl)
++#define PUBLIC(o) (o->pub)
++
++// ************************************************************************
++
++// Note: the following function documentation block will also be used
++// for all the miscellaneous viewer subclasses, so keep it general.
++/*!
++  \fn void So at Gui@FullViewer::createViewerButtons(@WIDGET@ parent, SbPList * buttonlist)
++
++  Set up the viewer buttons with pixmaps and event connections.
++
++
++  One important note if you want to override this method to add your
++  own buttons to the list (in the explanation below, it is assumed
++  that you know how virtual function table pointers are handled by
++  C++):
++
++  createViewerButtons() is called (indirectly) from the constructors
++  of the viewer classes. This means that you need to delay it's
++  invocation until your own subclass's constructor is run, because
++  otherwise your re-implementation won't have been added to the
++  internal virtual function table yet.
++
++  Delaying a superclass viewer from building it's decorations is done
++  by passing build==FALSE as the last argument of the protected
++  constructors. You will then have to explicitly trigger the building
++  in your own constructor.
++
++  Here's a minimal example that shows the steps needed to be able to
++  override createViewerButtons() from So at Gui@ExaminerViewer:
++
++  \code
++  class MyExaminerViewer : public So at Gui@ExaminerViewer {
++  
++  public:
++    MyExaminerViewer(@WIDGET@ parent);
++  
++  protected:
++    virtual void createViewerButtons(@WIDGET@ parent, SbPList * buttonlist);
++  };
++  
++  MyExaminerViewer::MyExaminerViewer(@WIDGET@ parent)
++    : So at Gui@ExaminerViewer(parent, NULL, TRUE,
++                            So at Gui@FullViewer::BUILD_ALL, So at Gui@FullViewer::BROWSER,
++                            // build == FALSE, to delay creation of decorations
++                            FALSE)
++  {
++    // Explicitly trigger the construction of viewer decorations.
++    @WIDGET@ widget = this->buildWidget(this->getParentWidget());
++    this->setBaseWidget(widget);
++  }
++  
++  void
++  MyExaminerViewer::createViewerButtons(@WIDGET@ parent, SbPList * buttonlist)
++  {
++    So at Gui@ExaminerViewer::createViewerButtons(parent, buttonlist);
++    // [now add your own button(s) to the buttonlist]
++  }
++  \endcode
++*/
++
++/*!
++  \enum So at Gui@FullViewer::BuildFlag
++
++  Valid values for the constructor argument that decides how much of
++  the user interface features to set up. The enum values are bitflags
++  that can be OR'ed together.
++*/
++/*!
++  \var So at Gui@FullViewer::BuildFlag So at Gui@FullViewer::BUILD_NONE
++
++  Do not add any of the user interface components.
++*/
++/*!
++  \var So at Gui@FullViewer::BuildFlag So at Gui@FullViewer::BUILD_DECORATION
++
++  Only build and set up the decorations around the OpenGL canvas.
++*/
++/*!
++  \var So at Gui@FullViewer::BuildFlag So at Gui@FullViewer::BUILD_POPUP
++
++  Only build the popup menu. (Activated with the right mousebutton.)
++*/
++/*!
++  \var So at Gui@FullViewer::BuildFlag So at Gui@FullViewer::BUILD_ALL
++
++  Build all user interface components of the So at Gui@FullViewer.
++*/
++
++/*!
++  \var @WIDGET@ So at Gui@FullViewer::leftDecoration
++  The root widget for the left-side decorations.
++*/
++
++/*!
++  \var @WIDGET@ So at Gui@FullViewer::leftWheel
++  The widget representing the thumbwheel left of the render canvas.
++*/
++
++/*!
++  \var @WIDGET@ So at Gui@FullViewer::leftWheelLabel
++  Label widget of left wheel.
++*/
++
++/*!
++  \var char * So at Gui@FullViewer::leftWheelStr
++  Text of left thumbwheel's label.
++*/
++
++/*!
++  \var float So at Gui@FullViewer::leftWheelVal
++  Current value of the left thumbwheel.
++*/
++
++/*!
++  \var @WIDGET@ So at Gui@FullViewer::bottomDecoration
++  The root widget for the bottom decorations.
++*/
++
++/*!
++  \var @WIDGET@ So at Gui@FullViewer::bottomWheel
++  The widget representing the thumbwheel below the render canvas.
++*/
++
++/*!
++  \var @WIDGET@ So at Gui@FullViewer::bottomWheelLabel
++  Label widget of bottom wheel.
++*/
++
++/*!
++  \var char * So at Gui@FullViewer::bottomWheelStr
++  Text of bottom thumbwheel's label.
++*/
++
++/*!
++  \var float So at Gui@FullViewer::bottomWheelVal
++  Current value of the bottom thumbwheel.
++*/
++
++/*!
++  \var @WIDGET@ So at Gui@FullViewer::rightDecoration
++  The root widget for the right-side decorations.
++*/
++
++/*!
++  \var @WIDGET@ So at Gui@FullViewer::rightWheel
++  The widget representing the thumbwheel on the right side of the render canvas.
++*/
++
++/*!
++  \var @WIDGET@ So at Gui@FullViewer::rightWheelLabel
++  Label widget of right wheel.
++*/
++
++/*!
++  \var char * So at Gui@FullViewer::rightWheelStr
++  Text of right thumbwheel's label.
++*/
++
++/*!
++  \var float So at Gui@FullViewer::rightWheelVal
++  Current value of the right-side thumbwheel.
++*/
++
++/*!
++  \var So at Gui@PopupMenu * So at Gui@FullViewer::prefmenu
++  Pointer to the popup menu instance.
++*/
++
++/*!
++  \fn So at Gui@FullViewer::So at Gui@FullViewer(@WIDGET@ parent, const char * name, SbBool embed, So at Gui@FullViewer::BuildFlag buildFlag, So at Gui@Viewer::Type type, SbBool build)
++
++  Constructor. See parent class for explanation of arguments.
++
++  Subclasses will probably usually call with the \a buildNow flag set
++  to \c FALSE to be able to do delayed building of the OpenGL canvas
++  after other setup tasks has been performed.
++*/
++
++/*!
++  \fn So at Gui@FullViewer::~So at Gui@FullViewer()
++
++  Destructor.
++*/
++
++/*!
++  \fn void So at Gui@FullViewer::setDecoration(const SbBool enable)
++
++  Turn the viewer decorations on or off.
++
++  \sa isDecoration()
++*/
++
++/*!
++  \fn SbBool So at Gui@FullViewer::isDecoration(void) const
++
++  Return \c TRUE if the viewer decorations are on, otherwise \c FALSE.
++
++  \sa setDecoration()
++*/
++
++/*!
++  \fn void So at Gui@FullViewer::setPopupMenuEnabled(const SbBool enable)
++
++  Decide whether or not if clicking with the right mouse button on
++  the OpenGL canvas should reveal a preferences popup menu when in
++  viewing mode.
++
++  \sa isPopupMenuEnabled()
++*/
++
++/*!
++  \fn SbBool So at Gui@FullViewer::isPopupMenuEnabled(void) const
++
++  Return \c TRUE if the popup preferences menu is enabled,
++  otherwise \c FALSE.
++
++  \sa setPopupMenuEnabled()
++*/
++
++/*!
++  \fn @WIDGET@ So at Gui@FullViewer::getAppPushButtonParent(void) const
++
++  Returns the widget which is used as the parent of application
++  specified buttons. The row of application buttons (if any) will be
++  placed in the upper left corner.
++
++  \sa addAppPushButton(), insertAppPushButton(), removeAppPushButton()
++*/
++
++/*!
++  \fn void So at Gui@FullViewer::addAppPushButton(@WIDGET@ newButton)
++
++  Add an application specific push button to the viewer decorations.
++  Application buttons will be laid out in a vertical row from the
++  upper left corner.
++
++  The button will be added bottom-most.
++
++  \sa insertAppPushButton(), removeAppPushButton(), getAppPushButtonParent()
++*/
++
++/*!
++  \fn void So at Gui@FullViewer::insertAppPushButton(@WIDGET@ newButton, int index)
++
++  Insert an application specific push button to the viewer decorations
++  at the given \c index.
++
++  \sa addAppPushButton(), removeAppPushButton(), getAppPushButtonParent()
++*/
++
++/*!
++  \fn void So at Gui@FullViewer::removeAppPushButton(@WIDGET@ oldButton)
++
++  Remove one of the application specific buttons.
++
++  \sa addAppPushButton(), insertAppPushButton()
++*/
++
++/*!
++  \fn int So at Gui@FullViewer::findAppPushButton(@WIDGET@ oldButton) const
++
++  Return the index of a particular button that has been specified by
++  the application, or -1 of the button has not been added.
++
++  \sa addAppPushButton()
++*/
++
++/*!
++  \fn int So at Gui@FullViewer::lengthAppPushButton(void) const
++
++  Return number of application specific buttons added.
++
++  \sa addAppPushButton(), insertAddAppPushButton()
++*/
++
++/*!
++  \fn @WIDGET@ So at Gui@FullViewer::getRenderAreaWidget(void) const
++
++  Returns the render area OpenGL canvas widget.
++*/
++
++/*!
++  \fn void So at Gui@FullViewer::buildDecoration(@WIDGET@ parent)
++
++  Build viewer decorations.
++*/
++
++/*!
++  \fn @WIDGET@ So at Gui@FullViewer::buildLeftTrim(@WIDGET@ parent)
++
++  Build decorations on the left of the render canvas.  Override this
++  method in subclasses if you want your own decorations on the viewer
++  window.
++
++  The decoration will be 30 pixels wide.
++*/
++
++/*!
++  \fn @WIDGET@ So at Gui@FullViewer::buildBottomTrim(@WIDGET@ parent)
++
++  Build decorations on the bottom of the render canvas. Override this
++  method in subclasses if you want your own decorations on the viewer window.
++*/
++
++/*!
++  \fn @WIDGET@ So at Gui@FullViewer::buildRightTrim(@WIDGET@ parent)
++
++  Build decorations on the right side of the render canvas. Override this
++  method in subclasses if you want your own decorations on the viewer window.
++*/
++
++/*!
++  \fn @WIDGET@ So at Gui@FullViewer::buildAppButtons(@WIDGET@ parent)
++
++  Build the application specified button row (if any buttons were
++  set up).
++*/
++
++/*!
++  \fn @WIDGET@ So at Gui@FullViewer::buildViewerButtons(@WIDGET@ parent)
++
++  Build and layout viewer specified button row.
++*/
++
++/*!
++  \fn void So at Gui@FullViewer::buildPopupMenu(void)
++
++  Make a popup menu with preferences settings.
++
++  One important note as for when you want to override this function in
++  a subclass: be aware that it will usually be invoked (indirectly)
++  from this class's constructor. That is \e before the table of
++  virtual function pointers has been set up for the subclass, and
++  because of this, the function will not be called in the subclass
++  even though it is virtual.
++
++  To make the overriding actually be in effect, you need to delay
++  building the widgets of this class. For information on how to do
++  that, see the documentation of
++  So at Gui@FullViewer::createViewerButtons().
++*/
++
++/*!
++  \fn void So at Gui@FullViewer::openPopupMenu(const SbVec2s position)
++
++  NOTE: This method is not part of the original InventorXt API.
++*/
++
++/*!
++  \fn void So at Gui@FullViewer::setLeftWheelString(const char * const string)
++
++  Set label of the left thumbwheel.
++*/
++
++/*!
++  \fn void So at Gui@FullViewer::setBottomWheelString(const char * const string)
++
++  Set label of the bottom thumbwheel.
++*/
++
++/*!
++  \fn void So at Gui@FullViewer::setRightWheelString(const char * const string)
++
++  Set label of the right thumbwheel.
++*/
++
++// ************************************************************************
++
++// Note: the following function documentation blocks for thumbwheel
++// handling will also be used for all the miscellaneous viewer
++// subclasses, so keep'em general.
++
++/*!
++  Called when the user start to drag the thumbwheel in the left
++  frame.  Override this method in subclassed viewers to provide your
++  own functionality on the thumbwheel.
++
++  \sa leftWheelMotion(), leftWheelFinish()
++  \sa bottomWheelStart(), rightWheelStart()
++*/
++void
++So at Gui@FullViewer::leftWheelStart(void)
++{
++  this->interactiveCountInc();
++}
++
++/*!
++  Called repeatedly as the user drags the thumbwheel in the left
++  frame.  Override this method in subclassed viewers to provide your
++  own functionality on the thumbwheel.
++
++  \sa leftWheelStart(), leftWheelFinish()
++  \sa bottomWheelStart(), rightWheelStart()
++*/
++void
++So at Gui@FullViewer::leftWheelMotion(float value)
++{
++  this->leftWheelVal = value;
++}
++
++/*!
++  Called as the user let go of the thumbwheel in the left frame
++  after a drag operation. Override this method in subclassed viewers
++  to provide your own functionality on the thumbwheel.
++
++  \sa leftWheelStart(), leftWheelMotion()
++  \sa bottomWheelStart(), rightWheelStart()
++*/
++void
++So at Gui@FullViewer::leftWheelFinish(void)
++{
++  this->interactiveCountDec();
++}
++
++/*!
++  Set a new value for the left thumbwheel.
++*/
++void
++So at Gui@FullViewer::setLeftWheelValue(const float value)
++{
++  this->leftWheelVal = value;
++  // Wheel may not be constructed yet, but we need to be robust, as
++  // set*WheelValue() is used from subclasses.
++  if (this->leftWheel) {
++    So at Gui@FullViewerP::setThumbWheelValue(this->leftWheel, value);
++  }
++}
++
++/*!
++  Get current value of the left thumbwheel.
++
++  \sa leftWheelMotion()
++*/
++float
++So at Gui@FullViewer::getLeftWheelValue(void) const
++{
++  return this->leftWheelVal;
++}
++
++/*!
++  Called when the user start to drag the thumbwheel in the bottom
++  frame.  Override this method in subclassed viewers to provide your
++  own functionality on the thumbwheel.
++
++  \sa bottomWheelMotion(), bottomWheelFinish()
++  \sa leftWheelStart(), rightWheelStart()
++*/
++void
++So at Gui@FullViewer::bottomWheelStart(void)
++{
++  this->interactiveCountInc();
++}
++
++/*!
++  Called repeatedly as the user drags the thumbwheel in the bottom
++  frame.  Override this method in subclassed viewers to provide your
++  own functionality on the thumbwheel.
++
++  \sa bottomWheelStart(), bottomWheelFinish()
++  \sa leftWheelStart(), rightWheelStart()
++*/
++void
++So at Gui@FullViewer::bottomWheelMotion(float value)
++{
++  this->bottomWheelVal = value;
++}
++
++/*!
++  Called as the user let go of the thumbwheel in the bottom frame
++  after a drag operation. Override this method in subclassed viewers
++  to provide your own functionality on the thumbwheel.
++
++  \sa bottomWheelStart(), bottomWheelMotion()
++  \sa leftWheelStart(), rightWheelStart()
++*/
++void
++So at Gui@FullViewer::bottomWheelFinish(void)
++{
++  this->interactiveCountDec();
++}
++
++/*!
++  Set a new value for the bottom thumbwheel.
++*/
++void
++So at Gui@FullViewer::setBottomWheelValue(const float value)
++{
++  this->bottomWheelVal = value;
++  // Wheel may not be constructed yet, but we need to be robust, as
++  // set*WheelValue() is used from subclasses.
++  if (this->bottomWheel) {
++    So at Gui@FullViewerP::setThumbWheelValue(this->bottomWheel, value);
++  }
++}
++
++/*!
++  Get current value of the bottom thumbwheel.
++
++  \sa bottomWheelMotion()
++*/
++float
++So at Gui@FullViewer::getBottomWheelValue(void) const
++{
++  return this->bottomWheelVal;
++}
++
++/*!
++  Called when the user start to drag the thumbwheel in the right
++  frame.  Override this method in subclassed viewers to provide your
++  own functionality on the thumbwheel.
++
++  \sa rightWheelMotion(), rightWheelFinish()
++  \sa leftWheelStart(), bottomWheelStart()
++*/
++void
++So at Gui@FullViewer::rightWheelStart(void)
++{
++  this->interactiveCountInc();
++}
++
++/*!
++  Called repeatedly as the user drags the thumbwheel in the right
++  frame.  Override this method in subclassed viewers to provide your
++  own functionality on the thumbwheel.
++
++  \sa rightWheelStart(), rightWheelFinish()
++  \sa leftWheelStart(), bottomWheelStart()
++*/
++void
++So at Gui@FullViewer::rightWheelMotion(float value)
++{
++  this->rightWheelVal = value;
++}
++
++/*!
++  Called as the user let go of the thumbwheel in the right frame
++  after a drag operation. Override this method in subclassed viewers
++  to provide your own functionality on the thumbwheel.
++
++  \sa rightWheelStart(), rightWheelMotion()
++  \sa leftWheelStart(), bottomWheelStart()
++*/
++void
++So at Gui@FullViewer::rightWheelFinish(void)
++{
++  this->interactiveCountDec();
++}
++
++/*!
++  Set a new value for the right thumbwheel.
++*/
++void
++So at Gui@FullViewer::setRightWheelValue(const float value)
++{
++  this->rightWheelVal = value;
++  // Wheel may not be constructed yet, but we need to be robust, as
++  // set*WheelValue() is used from subclasses.
++  if (this->rightWheel) {
++    So at Gui@FullViewerP::setThumbWheelValue(this->rightWheel, value);
++  }
++}
++
++/*!
++  Get current value of the right thumbwheel.
++
++  \sa rightWheelMotion()
++*/
++float
++So at Gui@FullViewer::getRightWheelValue(void) const
++{
++  return this->rightWheelVal;
++}
++
++// *************************************************************************
++
++/*!
++  This method returns the native widget for the label below the left
++  thumb wheel.
++*/
++
++ at WIDGET@
++So at Gui@FullViewer::getLeftWheelLabelWidget(void) const
++{
++  return this->leftWheelLabel;
++}
++
++/*!
++  This method returns the native widget for the label below the right thumb
++  wheel.
++*/
++ at WIDGET@
++So at Gui@FullViewer::getRightWheelLabelWidget(void) const
++{
++  return this->rightWheelLabel;
++}
++
++/*!
++  This method returns the native widget for the label beside the
++  bottom thumb wheel.
++*/
++ at WIDGET@
++So at Gui@FullViewer::getBottomWheelLabelWidget(void) const
++{
++  return this->bottomWheelLabel;
++}
++
++// ************************************************************************
++
++/*!
++  Set title of popup menu.
++*/
++void
++So at Gui@FullViewer::setPopupMenuString(const char * name)
++{
++  PRIVATE(this)->popupmenutitle = name;
++  if (this->prefmenu) { this->prefmenu->setMenuTitle(SoGuiFullViewerP::ROOT_MENU, name); }
++}
++
++
++// Documented in superclass.
++SbBool
++So at Gui@FullViewer::processSoEvent(const SoEvent * const ev)
++{
++  // We're in "interact" mode (ie *not* the camera modification mode),
++  // so don't handle the event here. It should either be forwarded to
++  // the scenegraph, or caught by So at Gui@Viewer::processSoEvent() if
++  // it's an ESC press (to switch modes).
++  if (!this->isViewing()) { return inherited::processSoEvent(ev); }
++
++  // Note: with the original SGI InventorXt, the popup menu is also
++  // activated by RMB clicks in non-viewing mode. We want to allow RMB
++  // clicks to pass through to the scenegraph in non-viewing mode, so
++  // we don't copy that behavior.
++
++  if (ev->getTypeId().isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) {
++    SoMouseButtonEvent * const e = (SoMouseButtonEvent *) ev;
++    if ((e->getButton() == SoMouseButtonEvent::BUTTON2)) {
++      if (this->isPopupMenuEnabled()) {
++        if (e->getState() == SoButtonEvent::DOWN) {
++          this->openPopupMenu(e->getPosition());
++        }
++        // Steal all RMB-events if the viewer uses the popup-menu.
++        return TRUE;
++      }
++    }
++  }
++
++  return inherited::processSoEvent(ev);
++}
++
++// *************************************************************************
++
++// FIXME: get rid of this hack and make this file truly
++// "generic". 20020109 mortene.
++#ifndef __COIN_SOWIN__
++
++// *************************************************************************
++
++// Doc in superclass.
++void
++So at Gui@FullViewer::setComponentCursor(const So at Gui@Cursor & cursor)
++{
++  // Overridden to apply the new cursor only for the rendering canvas
++  // widget. Otherwise, the default So at Gui@Component
++  // setComponentCursor() method will set the cursor for the top-most
++  // parent widget, which makes it affect all sub-widgets, like the
++  // decorations stuff.
++
++  So at Gui@Component::setWidgetCursor(this->getGLWidget(), cursor);
++}
++
++// *************************************************************************
++
++#endif // ! __COIN_SOWIN__
++
++// ************************************************************************
++
++#ifndef DOXYGEN_SKIP_THIS
++
++SoGuiFullViewerP::SoGuiFullViewerP(So at Gui@FullViewer * owner)
++{
++  this->pub = owner;
++}
++
++SoGuiFullViewerP::~SoGuiFullViewerP()
++{
++}
++
++So at Gui@PopupMenu *
++SoGuiFullViewerP::setupStandardPopupMenu(void)
++{
++  So at Gui@PopupMenu * menu = So at Gui@PopupMenu::createInstance();
++
++  menu->newMenu("rootmenu", ROOT_MENU);
++  // FIXME: none of the So*-toolkits so far uses the rootmenu title to
++  // set up a title string at the top of the root popupmenu. 20010810 mortene.
++  menu->setMenuTitle(ROOT_MENU, this->popupmenutitle.getString());
++
++#if 0 // OBSOLETED: this looks ugly and confusing for the user. 20010810 mortene.
++  // Simple hack for a common / generic way of setting up a title for
++  // the popupmenu.
++  menu->newMenuItem("rootmenutitle", ROOT_MENU_TITLE);
++  menu->setMenuItemTitle(ROOT_MENU_TITLE, this->popupmenutitle.getString());
++  menu->addMenuItem(ROOT_MENU, ROOT_MENU_TITLE);
++  menu->setMenuItemEnabled(ROOT_MENU_TITLE, FALSE);
++  menu->addSeparator(ROOT_MENU);
++#endif // OBSOLETED
++
++  menu->newMenu("functionsmenu", FUNCTIONS_MENU);
++  menu->setMenuTitle(FUNCTIONS_MENU, _("Functions"));
++  menu->newMenu("drawstylesmenu", DRAWSTYLES_MENU);
++  menu->setMenuTitle(DRAWSTYLES_MENU, _("Draw Styles"));
++  menu->newMenu("stereomenu", STEREO_MENU);
++  menu->setMenuTitle(STEREO_MENU, _("Stereo Viewing"));
++  menu->newMenuItem("examining", EXAMINING_ITEM);
++  menu->setMenuItemTitle(EXAMINING_ITEM, _("Viewing"));
++  menu->newMenuItem("decoration", DECORATION_ITEM);
++  menu->setMenuItemTitle(DECORATION_ITEM, _("Decorations"));
++  menu->newMenuItem("headlight", HEADLIGHT_ITEM);
++  menu->setMenuItemTitle(HEADLIGHT_ITEM, _("Headlight"));
++  menu->newMenuItem("fullscreen", FULLSCREEN_ITEM);
++  menu->setMenuItemTitle(FULLSCREEN_ITEM, _("Fullscreen"));
++
++  menu->addMenu(ROOT_MENU, FUNCTIONS_MENU);
++  menu->addMenu(ROOT_MENU, DRAWSTYLES_MENU);
++  menu->addMenu(ROOT_MENU, STEREO_MENU);
++  menu->addMenuItem(ROOT_MENU, EXAMINING_ITEM);
++  menu->addMenuItem(ROOT_MENU, DECORATION_ITEM);
++  menu->addMenuItem(ROOT_MENU, HEADLIGHT_ITEM);
++  menu->addMenuItem(ROOT_MENU, FULLSCREEN_ITEM);
++
++  menu->newMenuItem("home", HOME_ITEM);
++  menu->setMenuItemTitle(HOME_ITEM, _("Home"));
++  menu->newMenuItem("set_home", SET_HOME_ITEM);
++  menu->setMenuItemTitle(SET_HOME_ITEM, _("Set Home"));
++  menu->newMenuItem("view_all", VIEW_ALL_ITEM);
++  menu->setMenuItemTitle(VIEW_ALL_ITEM, _("View All"));
++  menu->newMenuItem("seek", SEEK_ITEM);
++  menu->setMenuItemTitle(SEEK_ITEM, _("Seek"));
++
++  menu->addMenuItem(FUNCTIONS_MENU, HOME_ITEM);
++  menu->addMenuItem(FUNCTIONS_MENU, SET_HOME_ITEM);
++  menu->addMenuItem(FUNCTIONS_MENU, VIEW_ALL_ITEM);
++  menu->addMenuItem(FUNCTIONS_MENU, SEEK_ITEM);
++
++  menu->newMenu("drawstylesstill", DRAWSTYLES_STILL_MENU);
++  menu->setMenuTitle(DRAWSTYLES_STILL_MENU, _("Still Drawstyle"));
++
++  menu->newMenuItem("as_is", AS_IS_ITEM);
++  menu->setMenuItemTitle(AS_IS_ITEM, _("as is"));
++  menu->newMenuItem("hidden_line", HIDDEN_LINE_ITEM);
++  menu->setMenuItemTitle(HIDDEN_LINE_ITEM, _("hidden line"));
++  menu->newMenuItem("wireframe_overlay", WIREFRAME_OVERLAY_ITEM);
++  menu->setMenuItemTitle(WIREFRAME_OVERLAY_ITEM, _("wireframe overlay"));
++  menu->newMenuItem("no_textures", NO_TEXTURE_ITEM);
++  menu->setMenuItemTitle(NO_TEXTURE_ITEM, _("no texture"));
++  menu->newMenuItem("low_resolution", LOW_RESOLUTION_ITEM);
++  menu->setMenuItemTitle(LOW_RESOLUTION_ITEM, _("low resolution"));
++  menu->newMenuItem("wireframe", WIREFRAME_ITEM);
++  menu->setMenuItemTitle(WIREFRAME_ITEM, _("wireframe"));
++  menu->newMenuItem("points", POINTS_ITEM);
++  menu->setMenuItemTitle(POINTS_ITEM, _("points"));
++  menu->newMenuItem("bounding_box", BOUNDING_BOX_ITEM);
++  menu->setMenuItemTitle(BOUNDING_BOX_ITEM, _("bounding box (no depth)"));
++
++  menu->newRadioGroup(STILL_GROUP);
++  menu->addRadioGroupItem(STILL_GROUP, AS_IS_ITEM);
++  menu->addRadioGroupItem(STILL_GROUP, HIDDEN_LINE_ITEM);
++  menu->addRadioGroupItem(STILL_GROUP, WIREFRAME_OVERLAY_ITEM);
++  menu->addRadioGroupItem(STILL_GROUP, NO_TEXTURE_ITEM);
++  menu->addRadioGroupItem(STILL_GROUP, LOW_RESOLUTION_ITEM);
++  menu->addRadioGroupItem(STILL_GROUP, WIREFRAME_ITEM);
++  menu->addRadioGroupItem(STILL_GROUP, POINTS_ITEM);
++  menu->addRadioGroupItem(STILL_GROUP, BOUNDING_BOX_ITEM);
++
++  menu->addMenuItem(DRAWSTYLES_STILL_MENU, AS_IS_ITEM);
++  menu->addMenuItem(DRAWSTYLES_STILL_MENU, HIDDEN_LINE_ITEM);
++  menu->addMenuItem(DRAWSTYLES_STILL_MENU, WIREFRAME_OVERLAY_ITEM);
++  menu->addMenuItem(DRAWSTYLES_STILL_MENU, NO_TEXTURE_ITEM);
++  menu->addMenuItem(DRAWSTYLES_STILL_MENU, LOW_RESOLUTION_ITEM);
++  menu->addMenuItem(DRAWSTYLES_STILL_MENU, WIREFRAME_ITEM);
++  menu->addMenuItem(DRAWSTYLES_STILL_MENU, POINTS_ITEM);
++  menu->addMenuItem(DRAWSTYLES_STILL_MENU, BOUNDING_BOX_ITEM);
++
++  menu->newMenu("drawstylesanimation", DRAWSTYLES_ANIMATING_MENU);
++  menu->setMenuTitle(DRAWSTYLES_ANIMATING_MENU, _("Animating Drawstyle"));
++
++  menu->newMenuItem("move_same_as_still", MOVE_SAME_AS_STILL_ITEM);
++  menu->setMenuItemTitle(MOVE_SAME_AS_STILL_ITEM, _("same as still"));
++  menu->newMenuItem("move_no_texture", MOVE_NO_TEXTURE_ITEM);
++  menu->setMenuItemTitle(MOVE_NO_TEXTURE_ITEM, _("no texture"));
++  menu->newMenuItem("move_low_res", MOVE_LOW_RES_ITEM);
++  menu->setMenuItemTitle(MOVE_LOW_RES_ITEM, _("low resolution"));
++  menu->newMenuItem("move_wireframe", MOVE_WIREFRAME_ITEM);
++  menu->setMenuItemTitle(MOVE_WIREFRAME_ITEM, _("wireframe"));
++  menu->newMenuItem("move_low_res_wireframe", MOVE_LOW_RES_WIREFRAME_ITEM);
++  menu->setMenuItemTitle(MOVE_LOW_RES_WIREFRAME_ITEM,
++    _("low res wireframe (no depth)"));
++  menu->newMenuItem("move_points", MOVE_POINTS_ITEM);
++  menu->setMenuItemTitle(MOVE_POINTS_ITEM, _("points"));
++  menu->newMenuItem("move_low_res_points", MOVE_LOW_RES_POINTS_ITEM);
++  menu->setMenuItemTitle(MOVE_LOW_RES_POINTS_ITEM,
++    _("low res points (no depth)"));
++  menu->newMenuItem("move_bounding_box", MOVE_BOUNDING_BOX_ITEM);
++  menu->setMenuItemTitle(MOVE_BOUNDING_BOX_ITEM, _("bounding box (no depth)"));
++
++  menu->newRadioGroup(MOVE_GROUP);
++  menu->addRadioGroupItem(MOVE_GROUP, MOVE_SAME_AS_STILL_ITEM);
++  menu->addRadioGroupItem(MOVE_GROUP, MOVE_NO_TEXTURE_ITEM);
++  menu->addRadioGroupItem(MOVE_GROUP, MOVE_LOW_RES_ITEM);
++  menu->addRadioGroupItem(MOVE_GROUP, MOVE_WIREFRAME_ITEM);
++  menu->addRadioGroupItem(MOVE_GROUP, MOVE_LOW_RES_WIREFRAME_ITEM);
++  menu->addRadioGroupItem(MOVE_GROUP, MOVE_POINTS_ITEM);
++  menu->addRadioGroupItem(MOVE_GROUP, MOVE_LOW_RES_POINTS_ITEM);
++  menu->addRadioGroupItem(MOVE_GROUP, MOVE_BOUNDING_BOX_ITEM);
++
++  menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_SAME_AS_STILL_ITEM);
++  menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_NO_TEXTURE_ITEM);
++  menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_LOW_RES_ITEM);
++  menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_WIREFRAME_ITEM);
++  menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_LOW_RES_WIREFRAME_ITEM);
++  menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_POINTS_ITEM);
++  menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_LOW_RES_POINTS_ITEM);
++  menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_BOUNDING_BOX_ITEM);
++
++  menu->newMenu("transparencytype", TRANSPARENCY_TYPE_MENU);
++  menu->setMenuTitle(TRANSPARENCY_TYPE_MENU, _("Transparency Type"));
++  menu->newRadioGroup(TRANSPARENCY_GROUP);
++
++  { // Fill in menu items in radiomenu with transparency selections.
++
++    struct menutransparencyitem {
++      const char * name, * title;
++      int id;
++    };
++
++    struct menutransparencyitem items[] = {
++#ifdef __COIN__
++      { "none", _("none"), NONE_TRANSPARENCY_ITEM },
++#endif // __COIN__
++      { "screen_door", _("screen door"), SCREEN_DOOR_TRANSPARENCY_ITEM },
++      { "add", _("add"), ADD_TRANSPARENCY_ITEM },
++      { "delayed_add", _("delayed add"), DELAYED_ADD_TRANSPARENCY_ITEM },
++      { "sorted_object_add", _("sorted object add"), SORTED_OBJECT_ADD_TRANSPARENCY_ITEM },
++      { "blend", _("blend"), BLEND_TRANSPARENCY_ITEM },
++      { "delayed_blend", _("delayed blend"), DELAYED_BLEND_TRANSPARENCY_ITEM },
++      { "sorted_object_blend", _("sorted object blend"), SORTED_OBJECT_BLEND_TRANSPARENCY_ITEM }
++#ifdef __COIN__ // Coin extensions
++      ,
++      { "sorted_object_sorted_triangle_add", _("sorted object sorted triangle add"), SORTED_OBJECT_SORTED_TRIANGLE_ADD_TRANSPARENCY_ITEM },
++      { "sorted_object_sorted_triangle_blend", _("sorted object sorted triangle blend"), SORTED_OBJECT_SORTED_TRIANGLE_BLEND_TRANSPARENCY_ITEM }
++#endif // __COIN__
++#ifdef HAVE_SORTED_LAYERS_BLEND
++      , { "sorted_layers_blend", _("sorted layers blend"), SORTED_LAYERS_BLEND_ITEM }
++#endif // HAVE_SORTED_LAYERS_BLEND
++    };
++
++    int nritems = sizeof(items) / sizeof(struct menutransparencyitem);
++    for (int i = 0; i < nritems; i++) {
++      menu->newMenuItem(items[i].name, items[i].id);
++      menu->setMenuItemTitle(items[i].id, items[i].title);
++      menu->addRadioGroupItem(TRANSPARENCY_GROUP, items[i].id);
++      menu->addMenuItem(TRANSPARENCY_TYPE_MENU, items[i].id);
++    }
++  }
++
++  menu->newMenuItem("stereooff", STEREO_OFF_ITEM);
++  menu->newMenuItem("stereoredcyan", STEREO_ANAGLYPH_ITEM);
++  menu->newMenuItem("stereoquadbuffer", STEREO_QUADBUFFER_ITEM);
++  menu->setMenuItemTitle(STEREO_OFF_ITEM, _("Off"));
++  menu->setMenuItemTitle(STEREO_ANAGLYPH_ITEM, _("Red/Cyan Anaglyph"));
++  menu->setMenuItemTitle(STEREO_QUADBUFFER_ITEM, _("Quad buffer"));
++
++  menu->newMenuItem("stereointerleavedrows", STEREO_INTERLEAVED_ROWS_ITEM);
++  menu->setMenuItemTitle(STEREO_INTERLEAVED_ROWS_ITEM, _("Interleaved Rows"));
++  menu->newMenuItem("stereointerleavedcolumns", STEREO_INTERLEAVED_COLUMNS_ITEM);
++  menu->setMenuItemTitle(STEREO_INTERLEAVED_COLUMNS_ITEM, _("Interleaved Columns"));
++
++  menu->newRadioGroup(STEREO_GROUP);
++  menu->addRadioGroupItem(STEREO_GROUP, STEREO_OFF_ITEM);
++  menu->addRadioGroupItem(STEREO_GROUP, STEREO_ANAGLYPH_ITEM);
++  menu->addRadioGroupItem(STEREO_GROUP, STEREO_QUADBUFFER_ITEM);
++  menu->addRadioGroupItem(STEREO_GROUP, STEREO_INTERLEAVED_ROWS_ITEM);
++  menu->addRadioGroupItem(STEREO_GROUP, STEREO_INTERLEAVED_COLUMNS_ITEM);
++
++  menu->addMenuItem(STEREO_MENU, STEREO_OFF_ITEM);
++  menu->addMenuItem(STEREO_MENU, STEREO_ANAGLYPH_ITEM);
++  menu->addMenuItem(STEREO_MENU, STEREO_QUADBUFFER_ITEM);
++  menu->addMenuItem(STEREO_MENU, STEREO_INTERLEAVED_ROWS_ITEM);
++  menu->addMenuItem(STEREO_MENU, STEREO_INTERLEAVED_COLUMNS_ITEM);
++
++  menu->newMenu("renderbuffertype", RENDER_BUFFER_TYPE_MENU);
++  menu->setMenuTitle(RENDER_BUFFER_TYPE_MENU, _("Render Buffer Type"));
++
++  menu->newMenuItem("single_buffer", SINGLE_BUFFER_ITEM);
++  menu->setMenuItemTitle(SINGLE_BUFFER_ITEM, _("single"));
++  menu->newMenuItem("double_buffer", DOUBLE_BUFFER_ITEM);
++  menu->setMenuItemTitle(DOUBLE_BUFFER_ITEM, _("double"));
++  menu->newMenuItem("interactive_buffer", INTERACTIVE_BUFFER_ITEM);
++  menu->setMenuItemTitle(INTERACTIVE_BUFFER_ITEM, _("interactive"));
++
++  menu->newRadioGroup(BUFFER_GROUP);
++  menu->addRadioGroupItem(BUFFER_GROUP, SINGLE_BUFFER_ITEM);
++  menu->addRadioGroupItem(BUFFER_GROUP, DOUBLE_BUFFER_ITEM);
++  menu->addRadioGroupItem(BUFFER_GROUP, INTERACTIVE_BUFFER_ITEM);
++
++  menu->addMenuItem(RENDER_BUFFER_TYPE_MENU, SINGLE_BUFFER_ITEM);
++  menu->addMenuItem(RENDER_BUFFER_TYPE_MENU, DOUBLE_BUFFER_ITEM);
++  menu->addMenuItem(RENDER_BUFFER_TYPE_MENU, INTERACTIVE_BUFFER_ITEM);
++
++  menu->addMenu(DRAWSTYLES_MENU, DRAWSTYLES_STILL_MENU);
++  menu->addMenu(DRAWSTYLES_MENU, DRAWSTYLES_ANIMATING_MENU);
++  menu->addMenu(DRAWSTYLES_MENU, TRANSPARENCY_TYPE_MENU);
++  menu->addMenu(DRAWSTYLES_MENU, RENDER_BUFFER_TYPE_MENU);
++
++  int toggle;
++  toggle = menu->newRadioGroup();
++  menu->addRadioGroupItem(toggle, EXAMINING_ITEM);
++  toggle = menu->newRadioGroup();
++  menu->addRadioGroupItem(toggle, DECORATION_ITEM);
++  toggle = menu->newRadioGroup();
++  menu->addRadioGroupItem(toggle, HEADLIGHT_ITEM);
++  toggle = menu->newRadioGroup();
++  menu->addRadioGroupItem(toggle, FULLSCREEN_ITEM);
++
++  menu->addMenuSelectionCallback(SoGuiFullViewerP::menuSelectionCallback,
++                                 (void *) this);
++
++  // this instance is freed in the native viewer component
++  PUBLIC(this)->prefmenu = menu;
++  return menu;
++}
++
++// ************************************************************************
++
++void
++SoGuiFullViewerP::prepareMenu(So at Gui@PopupMenu * menu)
++{
++  //// Misc. //////////////////////////////////////////////////////////
++  menu->setMenuItemMarked(DECORATION_ITEM, PUBLIC(this)->isDecoration());
++  menu->setMenuItemMarked(EXAMINING_ITEM, PUBLIC(this)->isViewing());
++  menu->setMenuItemMarked(HEADLIGHT_ITEM, PUBLIC(this)->isHeadlight());
++  menu->setMenuItemMarked(FULLSCREEN_ITEM, PUBLIC(this)->isFullScreen());
++
++  //// Basic drawstyles. //////////////////////////////////////////////
++  this->setDrawStyleMenuActivation(So at Gui@FullViewer::STILL,
++                                   PUBLIC(this)->getDrawStyle(So at Gui@FullViewer::STILL));
++  this->setDrawStyleMenuActivation(So at Gui@FullViewer::INTERACTIVE,
++                                   PUBLIC(this)->getDrawStyle(So at Gui@FullViewer::INTERACTIVE));
++
++  //// Transparency setting. //////////////////////////////////////////
++  switch (PUBLIC(this)->getTransparencyType()) {
++  case SoGLRenderAction::SCREEN_DOOR:
++    menu->setMenuItemMarked(SCREEN_DOOR_TRANSPARENCY_ITEM, TRUE);
++    break;
++  case SoGLRenderAction::ADD:
++    menu->setMenuItemMarked(ADD_TRANSPARENCY_ITEM, TRUE);
++    break;
++  case SoGLRenderAction::DELAYED_ADD:
++    menu->setMenuItemMarked(DELAYED_ADD_TRANSPARENCY_ITEM, TRUE);
++    break;
++  case SoGLRenderAction::SORTED_OBJECT_ADD:
++    menu->setMenuItemMarked(SORTED_OBJECT_ADD_TRANSPARENCY_ITEM, TRUE);
++    break;
++  case SoGLRenderAction::BLEND:
++    menu->setMenuItemMarked(BLEND_TRANSPARENCY_ITEM, TRUE);
++    break;
++  case SoGLRenderAction::DELAYED_BLEND:
++    menu->setMenuItemMarked(DELAYED_BLEND_TRANSPARENCY_ITEM, TRUE);
++    break;
++  case SoGLRenderAction::SORTED_OBJECT_BLEND:
++    menu->setMenuItemMarked(SORTED_OBJECT_BLEND_TRANSPARENCY_ITEM, TRUE);
++    break;
++#ifdef __COIN__  // Coin extensions
++  case SoGLRenderAction::NONE:
++    menu->setMenuItemMarked(NONE_TRANSPARENCY_ITEM, TRUE);
++    break;
++  case SoGLRenderAction::SORTED_OBJECT_SORTED_TRIANGLE_ADD:
++    menu->setMenuItemMarked(SORTED_OBJECT_SORTED_TRIANGLE_ADD_TRANSPARENCY_ITEM, TRUE);
++    break;
++  case SoGLRenderAction::SORTED_OBJECT_SORTED_TRIANGLE_BLEND:
++    menu->setMenuItemMarked(SORTED_OBJECT_SORTED_TRIANGLE_BLEND_TRANSPARENCY_ITEM, TRUE);
++    break;
++#endif // __COIN__
++#ifdef HAVE_SORTED_LAYERS_BLEND
++  case SoGLRenderAction::SORTED_LAYERS_BLEND:
++    menu->setMenuItemMarked(SORTED_LAYERS_BLEND_ITEM, TRUE);
++    break;
++#endif // HAVE_SORTED_LAYERS_BLEND
++  default:
++#if SO at GUI@_DEBUG
++    SoDebugError::postInfo("SoGuiFullViewerP::prepareMenu",
++                           "Unknown transparency type");
++#endif // SO at GUI@_DEBUG
++    break;
++  }
++
++  //// Stereo viewing. ////////////////////////////////////////////////
++
++  const So at Gui@Viewer::StereoType type = PUBLIC(this)->getStereoType();
++  switch (type) {
++  case So at Gui@Viewer::STEREO_NONE:
++    menu->setMenuItemMarked(STEREO_OFF_ITEM, TRUE);
++    break;
++  case So at Gui@Viewer::STEREO_ANAGLYPH:
++    menu->setMenuItemMarked(STEREO_ANAGLYPH_ITEM, TRUE);
++    break;
++  case So at Gui@Viewer::STEREO_QUADBUFFER:
++    menu->setMenuItemMarked(STEREO_QUADBUFFER_ITEM, TRUE);
++    break;
++  case So at Gui@Viewer::STEREO_INTERLEAVED_ROWS:
++    menu->setMenuItemMarked(STEREO_INTERLEAVED_ROWS_ITEM, TRUE);
++    break;
++  case So at Gui@Viewer::STEREO_INTERLEAVED_COLUMNS:
++    menu->setMenuItemMarked(STEREO_INTERLEAVED_COLUMNS_ITEM, TRUE);
++    break;
++  default:
++    assert(FALSE); break;
++  }
++
++  //// GL canvas settings. ////////////////////////////////////////////
++  switch (PUBLIC(this)->getBufferingType()) {
++  case So at Gui@Viewer::BUFFER_SINGLE:
++    menu->setMenuItemMarked(SINGLE_BUFFER_ITEM, TRUE);
++    break;
++  case So at Gui@Viewer::BUFFER_DOUBLE:
++    menu->setMenuItemMarked(DOUBLE_BUFFER_ITEM, TRUE);
++    break;
++  case So at Gui@Viewer::BUFFER_INTERACTIVE:
++    menu->setMenuItemMarked(INTERACTIVE_BUFFER_ITEM, TRUE);
++    break;
++  default:
++#if SO at GUI@_DEBUG
++    SoDebugError::postInfo("SoGuiFullViewerP::prepareMenu",
++                           "Unknown buffer type");
++#endif // SO at GUI@_DEBUG
++    break;
++  }
++}
++
++// ************************************************************************
++
++void
++SoGuiFullViewerP::menuSelection(int menuitemid)
++{
++  SbBool ok;
++
++  switch (menuitemid) {
++  case -1:
++    // means no item was selected
++#if SO at GUI@_DEBUG
++    SoDebugError::postInfo("SoGuiFullViewerP::menuSelection",
++                           "-1 not appropriate on callback usage");
++#endif // SO at GUI@_DEBUG
++    break;
++
++  case EXAMINING_ITEM:
++    PUBLIC(this)->setViewing(PUBLIC(this)->isViewing() ? FALSE : TRUE);
++    break;
++  case DECORATION_ITEM:
++    PUBLIC(this)->setDecoration(PUBLIC(this)->isDecoration() ? FALSE : TRUE);
++    break;
++  case HEADLIGHT_ITEM:
++    PUBLIC(this)->setHeadlight(PUBLIC(this)->isHeadlight() ? FALSE : TRUE);
++    break;
++  case FULLSCREEN_ITEM:
++    (void)PUBLIC(this)->setFullScreen(PUBLIC(this)->isFullScreen() ? FALSE : TRUE);
++    break;
++
++  case HOME_ITEM:
++    PUBLIC(this)->resetToHomePosition();
++    break;
++  case SET_HOME_ITEM:
++    PUBLIC(this)->saveHomePosition();
++    break;
++  case VIEW_ALL_ITEM:
++    PUBLIC(this)->viewAll();
++    break;
++  case SEEK_ITEM:
++    ((So at Gui@FullViewerP *)this)->seekbuttonClicked();
++    break;
++
++  case AS_IS_ITEM:
++  case HIDDEN_LINE_ITEM:
++  case WIREFRAME_OVERLAY_ITEM:
++  case NO_TEXTURE_ITEM:
++  case LOW_RESOLUTION_ITEM:
++  case WIREFRAME_ITEM:
++  case POINTS_ITEM:
++  case BOUNDING_BOX_ITEM:
++    this->drawstyleActivated(menuitemid);
++    break;
++
++  case MOVE_SAME_AS_STILL_ITEM:
++  case MOVE_NO_TEXTURE_ITEM:
++  case MOVE_LOW_RES_ITEM:
++  case MOVE_WIREFRAME_ITEM:
++  case MOVE_LOW_RES_WIREFRAME_ITEM:
++  case MOVE_POINTS_ITEM:
++  case MOVE_LOW_RES_POINTS_ITEM:
++  case MOVE_BOUNDING_BOX_ITEM:
++    this->drawstyleActivated(menuitemid);
++    break;
++
++  case SCREEN_DOOR_TRANSPARENCY_ITEM:
++  case ADD_TRANSPARENCY_ITEM:
++  case DELAYED_ADD_TRANSPARENCY_ITEM:
++  case SORTED_OBJECT_ADD_TRANSPARENCY_ITEM:
++  case BLEND_TRANSPARENCY_ITEM:
++  case DELAYED_BLEND_TRANSPARENCY_ITEM:
++  case SORTED_OBJECT_BLEND_TRANSPARENCY_ITEM:
++  case SORTED_OBJECT_SORTED_TRIANGLE_ADD_TRANSPARENCY_ITEM:
++  case SORTED_OBJECT_SORTED_TRIANGLE_BLEND_TRANSPARENCY_ITEM:
++  case NONE_TRANSPARENCY_ITEM:
++  case SORTED_LAYERS_BLEND_ITEM: // define test is not needed. This enum is always defined
++    this->drawstyleActivated(menuitemid);
++    PUBLIC(this)->scheduleRedraw();
++    break;
++
++  case SINGLE_BUFFER_ITEM:
++  case DOUBLE_BUFFER_ITEM:
++  case INTERACTIVE_BUFFER_ITEM:
++    this->drawstyleActivated(menuitemid);
++    break;
++
++  case STEREO_OFF_ITEM:
++    ok = PUBLIC(this)->setStereoType(So at Gui@Viewer::STEREO_NONE);
++    assert(ok);
++    break;
++  case STEREO_ANAGLYPH_ITEM:
++    ok = PUBLIC(this)->setStereoType(So at Gui@Viewer::STEREO_ANAGLYPH);
++    assert(ok && "anaglyph stereo should always be possible");
++    break;
++  case STEREO_QUADBUFFER_ITEM:
++    ok = PUBLIC(this)->setStereoType(So at Gui@Viewer::STEREO_QUADBUFFER);
++    if (!ok) { PUBLIC(this)->setStereoType(So at Gui@Viewer::STEREO_NONE); }
++    break;
++  case STEREO_INTERLEAVED_ROWS_ITEM:
++    ok = PUBLIC(this)->setStereoType(So at Gui@Viewer::STEREO_INTERLEAVED_ROWS);
++    if (!ok) { PUBLIC(this)->setStereoType(So at Gui@Viewer::STEREO_NONE); }
++    break;
++  case STEREO_INTERLEAVED_COLUMNS_ITEM:
++    ok = PUBLIC(this)->setStereoType(So at Gui@Viewer::STEREO_INTERLEAVED_COLUMNS);
++    if (!ok) { PUBLIC(this)->setStereoType(So at Gui@Viewer::STEREO_NONE); }
++    break;
++
++  default:
++    SoDebugError::postInfo("SoGuiFullViewerP::menuSelection",
++                           "popup menu handling for item %d is not implemented", 
++                           menuitemid);
++    break;
++  }
++}
++
++
++// ************************************************************************
++
++void
++SoGuiFullViewerP::menuSelectionCallback(int menuitemid,
++                                        void * userdata)
++{
++  SoGuiFullViewerP * viewer = (SoGuiFullViewerP *) userdata;
++  viewer->menuSelection(menuitemid);
++}
++
++// ************************************************************************
++
++void
++SoGuiFullViewerP::setDrawStyleMenuActivation(So at Gui@Viewer::DrawType type,
++                                             So at Gui@Viewer::DrawStyle value)
++{
++  assert(PUBLIC(this)->prefmenu != NULL);
++
++  switch (type) {
++  case So at Gui@Viewer::STILL:
++    switch (value) {
++    case So at Gui@Viewer::VIEW_AS_IS:
++      PUBLIC(this)->prefmenu->setMenuItemMarked(AS_IS_ITEM, TRUE);
++      break;
++    case So at Gui@Viewer::VIEW_HIDDEN_LINE:
++      PUBLIC(this)->prefmenu->setMenuItemMarked(HIDDEN_LINE_ITEM, TRUE);
++      break;
++    case So at Gui@Viewer::VIEW_WIREFRAME_OVERLAY:
++      PUBLIC(this)->prefmenu->setMenuItemMarked(WIREFRAME_OVERLAY_ITEM, TRUE);
++      break;
++    case So at Gui@Viewer::VIEW_NO_TEXTURE:
++      PUBLIC(this)->prefmenu->setMenuItemMarked(NO_TEXTURE_ITEM, TRUE);
++      break;
++    case So at Gui@Viewer::VIEW_LOW_COMPLEXITY:
++      PUBLIC(this)->prefmenu->setMenuItemMarked(LOW_RESOLUTION_ITEM, TRUE);
++      break;
++    case So at Gui@Viewer::VIEW_LOW_RES_LINE:
++#if SO at GUI@_DEBUG
++      SoDebugError::postWarning("So at Gui@FullViewer::setDrawStyleMenuActivation",
++                                "Use VIEW_LINE, not VIEW_LOW_RES_LINE for the STILL drawstyle.");
++#endif // debug
++    case So at Gui@Viewer::VIEW_LINE:
++      PUBLIC(this)->prefmenu->setMenuItemMarked(WIREFRAME_ITEM, TRUE);
++      break;
++    case So at Gui@Viewer::VIEW_LOW_RES_POINT:
++#if SO at GUI@_DEBUG
++      SoDebugError::postWarning("So at Gui@FullViewer::setDrawStyleMenuActivation",
++                                "Use VIEW_POINT, not VIEW_LOW_RES_POINT for the STILL drawstyle.");
++#endif // debug
++    case So at Gui@Viewer::VIEW_POINT:
++      PUBLIC(this)->prefmenu->setMenuItemMarked(POINTS_ITEM, TRUE);
++      break;
++    case So at Gui@Viewer::VIEW_BBOX:
++      PUBLIC(this)->prefmenu->setMenuItemMarked(BOUNDING_BOX_ITEM, TRUE);
++      break;
++    default:
++#if SO at GUI@_DEBUG
++      SoDebugError::postWarning("So at Gui@FullViewer::setDrawStyleMenuActivation",
++                                "Unsupporter still-drawstyle");
++#endif // debug
++      break;
++    }
++    break;
++
++  case So at Gui@Viewer::INTERACTIVE:
++    switch (value) {
++    case So at Gui@Viewer::VIEW_SAME_AS_STILL:
++      PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_SAME_AS_STILL_ITEM, TRUE);
++      break;
++    case So at Gui@Viewer::VIEW_NO_TEXTURE:
++      PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_NO_TEXTURE_ITEM, TRUE);
++      break;
++    case So at Gui@Viewer::VIEW_LOW_COMPLEXITY:
++      PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_LOW_RES_ITEM, TRUE);
++      break;
++    case So at Gui@Viewer::VIEW_LINE:
++      PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_WIREFRAME_ITEM, TRUE);
++      break;
++    case So at Gui@Viewer::VIEW_LOW_RES_LINE:
++      PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_LOW_RES_WIREFRAME_ITEM, TRUE);
++      break;
++    case So at Gui@Viewer::VIEW_POINT:
++      PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_POINTS_ITEM, TRUE);
++      break;
++    case So at Gui@Viewer::VIEW_LOW_RES_POINT:
++      PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_LOW_RES_POINTS_ITEM, TRUE);
++      break;
++    case So at Gui@Viewer::VIEW_BBOX:
++      PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_BOUNDING_BOX_ITEM, TRUE);
++      break;
++    default:
++#if SO at GUI@_DEBUG
++      SoDebugError::postWarning("So at Gui@FullViewer::setDrawStyleMenuActivation",
++                                "Unsupporter interactive drawstyle");
++#endif // debug
++      break;
++    }
++    break;
++
++  default:
++#if SO at GUI@_DEBUG
++    SoDebugError::postWarning("So at Gui@FullViewer::setDrawStyleMenuActivation",
++                              "Unsupporter drawstyle type");
++#endif // debug
++    break;
++  }
++}
++
++// ************************************************************************
++
++void
++SoGuiFullViewerP::drawstyleActivated(int menuitemid)
++{
++  switch (menuitemid) {
++  case SINGLE_BUFFER_ITEM:
++    PUBLIC(this)->setBufferingType(So at Gui@Viewer::BUFFER_SINGLE);
++    return;
++  case DOUBLE_BUFFER_ITEM:
++    PUBLIC(this)->setBufferingType(So at Gui@Viewer::BUFFER_DOUBLE);
++    return;
++  case INTERACTIVE_BUFFER_ITEM:
++    PUBLIC(this)->setBufferingType(So at Gui@Viewer::BUFFER_INTERACTIVE);
++    return;
++  default:
++    break;
++  }
++
++  // FIXME: should perhaps override transparency type to be screendoor
++  // if we detect that the OpenGL canvas has 0 alpha bits available?
++  // 20030626 mortene.
++  switch (menuitemid) {
++  case SCREEN_DOOR_TRANSPARENCY_ITEM:
++    PUBLIC(this)->setTransparencyType(SoGLRenderAction::SCREEN_DOOR);
++    return;
++  case ADD_TRANSPARENCY_ITEM:
++    PUBLIC(this)->setTransparencyType(SoGLRenderAction::ADD);
++    return;
++  case DELAYED_ADD_TRANSPARENCY_ITEM:
++    PUBLIC(this)->setTransparencyType(SoGLRenderAction::DELAYED_ADD);
++    return;
++  case SORTED_OBJECT_ADD_TRANSPARENCY_ITEM:
++    PUBLIC(this)->setTransparencyType(SoGLRenderAction::SORTED_OBJECT_ADD);
++    return;
++  case BLEND_TRANSPARENCY_ITEM:
++    PUBLIC(this)->setTransparencyType(SoGLRenderAction::BLEND);
++    return;
++  case DELAYED_BLEND_TRANSPARENCY_ITEM:
++    PUBLIC(this)->setTransparencyType(SoGLRenderAction::DELAYED_BLEND);
++    return;
++  case SORTED_OBJECT_BLEND_TRANSPARENCY_ITEM:
++    PUBLIC(this)->setTransparencyType(SoGLRenderAction::SORTED_OBJECT_BLEND);
++    return;
++#ifdef __COIN__ // Coin extensions
++  case NONE_TRANSPARENCY_ITEM:
++    PUBLIC(this)->setTransparencyType(SoGLRenderAction::NONE);
++    return;
++  case SORTED_OBJECT_SORTED_TRIANGLE_ADD_TRANSPARENCY_ITEM:
++    PUBLIC(this)->setTransparencyType(SoGLRenderAction::SORTED_OBJECT_SORTED_TRIANGLE_ADD);
++    return;
++  case SORTED_OBJECT_SORTED_TRIANGLE_BLEND_TRANSPARENCY_ITEM:
++    PUBLIC(this)->setTransparencyType(SoGLRenderAction::SORTED_OBJECT_SORTED_TRIANGLE_BLEND);
++    return;
++#endif // __COIN__
++#ifdef HAVE_SORTED_LAYERS_BLEND
++  case SORTED_LAYERS_BLEND_ITEM:
++    PUBLIC(this)->setTransparencyType(SoGLRenderAction::SORTED_LAYERS_BLEND);
++    return;
++#endif // HAVE_SORTED_LAYERS_BLEND
++  default:
++    // some other menu item, just continue
++    break;
++  }
++
++  So at Gui@Viewer::DrawStyle val = So at Gui@Viewer::VIEW_AS_IS;
++  switch (menuitemid) {
++  case AS_IS_ITEM:
++    val = So at Gui@Viewer::VIEW_AS_IS;
++    break;
++  case HIDDEN_LINE_ITEM:
++    val = So at Gui@Viewer::VIEW_HIDDEN_LINE;
++    break;
++  case WIREFRAME_OVERLAY_ITEM:
++    val = So at Gui@Viewer::VIEW_WIREFRAME_OVERLAY;
++    break;
++  case NO_TEXTURE_ITEM:
++    val = So at Gui@Viewer::VIEW_NO_TEXTURE;
++    break;
++  case LOW_RESOLUTION_ITEM:
++    val = So at Gui@Viewer::VIEW_LOW_COMPLEXITY;
++    break;
++  case WIREFRAME_ITEM:
++    val = So at Gui@Viewer::VIEW_LINE;
++    break;
++  case POINTS_ITEM:
++    val = So at Gui@Viewer::VIEW_POINT;
++    break;
++  case BOUNDING_BOX_ITEM:
++    val = So at Gui@Viewer::VIEW_BBOX;
++    break;
++
++  case MOVE_SAME_AS_STILL_ITEM:
++    val = So at Gui@Viewer::VIEW_SAME_AS_STILL;
++    break;
++  case MOVE_NO_TEXTURE_ITEM:
++    val = So at Gui@Viewer::VIEW_NO_TEXTURE;
++    break;
++  case MOVE_LOW_RES_ITEM:
++    val = So at Gui@Viewer::VIEW_LOW_COMPLEXITY;
++    break;
++  case MOVE_WIREFRAME_ITEM:
++    val = So at Gui@Viewer::VIEW_LINE;
++    break;
++  case MOVE_LOW_RES_WIREFRAME_ITEM:
++    val = So at Gui@Viewer::VIEW_LOW_RES_LINE;
++    break;
++  case MOVE_POINTS_ITEM:
++    val = So at Gui@Viewer::VIEW_POINT;
++    break;
++  case MOVE_LOW_RES_POINTS_ITEM:
++    val = So at Gui@Viewer::VIEW_LOW_RES_POINT;
++    break;
++  case MOVE_BOUNDING_BOX_ITEM:
++    val = So at Gui@Viewer::VIEW_BBOX;
++    break;
++
++  default:
++    assert(0);
++    break;
++  }
++
++  So at Gui@Viewer::DrawType type = So at Gui@Viewer::STILL;
++
++  switch (menuitemid) {
++  case AS_IS_ITEM:
++  case HIDDEN_LINE_ITEM:
++  case WIREFRAME_OVERLAY_ITEM:
++  case NO_TEXTURE_ITEM:
++  case LOW_RESOLUTION_ITEM:
++  case WIREFRAME_ITEM:
++  case POINTS_ITEM:
++  case BOUNDING_BOX_ITEM:
++    type = So at Gui@Viewer::STILL;
++    break;
++
++  case MOVE_SAME_AS_STILL_ITEM:
++  case MOVE_NO_TEXTURE_ITEM:
++  case MOVE_LOW_RES_ITEM:
++  case MOVE_WIREFRAME_ITEM:
++  case MOVE_LOW_RES_WIREFRAME_ITEM:
++  case MOVE_POINTS_ITEM:
++  case MOVE_LOW_RES_POINTS_ITEM:
++  case MOVE_BOUNDING_BOX_ITEM:
++    type = So at Gui@Viewer::INTERACTIVE;
++    break;
++
++  default:
++    assert(0);
++    break;
++  }
++
++  PUBLIC(this)->setDrawStyle(type, val);
++}
++
++// ************************************************************************
++
++// Move camera parallel with the plane orthogonal to the camera
++// direction vector.
++//
++// Used from both SoGuiPlaneViewer and SoGuiExaminerViewer.
++// Implemented in the SoGuiFullViewer private class to collect common
++// code.
++void
++SoGuiFullViewerP::pan(SoCamera * cam,
++                      float aspectratio, const SbPlane & panningplane,
++                      const SbVec2f & currpos, const SbVec2f & prevpos)
++{
++  if (cam == NULL) return; // can happen for empty scenegraph
++  if (currpos == prevpos) return; // useless invocation
++
++#if SO at GUI@_DEBUG && 0
++  SoDebugError::postInfo("SoGuiFullViewerP::pan",
++                         "was(%.3g, %.3g) -> now(%.3g, %.3g)",
++                         prevpos[0], prevpos[1], currpos[0], currpos[1]);
++#endif // SO at GUI@_DEBUG
++
++  // Find projection points for the last and current mouse coordinates.
++  SbViewVolume vv = cam->getViewVolume(aspectratio);
++  SbLine line;
++  vv.projectPointToLine(currpos, line);
++  SbVec3f current_planept;
++  panningplane.intersect(line, current_planept);
++  vv.projectPointToLine(prevpos, line);
++  SbVec3f old_planept;
++  panningplane.intersect(line, old_planept);
++
++  // Reposition camera according to the vector difference between the
++  // projected points.
++  cam->position = cam->position.getValue() - (current_planept - old_planept);
++}
++
++// *************************************************************************
++
++// Dependent on the camera type this will either shrink or expand the
++// height of the viewport (orthogonal camera) or move the camera
++// closer or further away from the focal point in the scene.
++//
++// Used from both SoGuiPlaneViewer and SoGuiExaminerViewer.
++// Implemented in the SoGuiFullViewer private class to collect common
++// code.
++void
++SoGuiFullViewerP::zoom(SoCamera * cam, const float diffvalue)
++{
++  if (cam == NULL) return; // can happen for empty scenegraph
++  SoType t = cam->getTypeId();
++  SbName tname = t.getName();
++
++  // This will be in the range of <0, ->>.
++  float multiplicator = float(exp(diffvalue));
++
++  if (t.isDerivedFrom(SoOrthographicCamera::getClassTypeId())) {
++
++    // Since there's no perspective, "zooming" in the original sense
++    // of the word won't have any visible effect. So we just increase
++    // or decrease the field-of-view values of the camera instead, to
++    // "shrink" the projection size of the model / scene.
++    SoOrthographicCamera * oc = (SoOrthographicCamera *)cam;
++    oc->height = oc->height.getValue() * multiplicator;
++
++  }
++  else {
++    // FrustumCamera can be found in the SmallChange CVS module (it's
++    // a camera that lets you specify (for instance) an off-center
++    // frustum (similar to glFrustum())
++    if (!t.isDerivedFrom(SoPerspectiveCamera::getClassTypeId()) &&
++        tname != "FrustumCamera") {
++      static SbBool first = TRUE;
++      if (first) {
++        SoDebugError::postWarning("SoGuiFullViewerP::zoom",
++                                  "Unknown camera type, "
++                                  "will zoom by moving position, but this might not be correct.");
++        first = FALSE;
++      }
++    }
++    
++    const float oldfocaldist = cam->focalDistance.getValue();
++    const float newfocaldist = oldfocaldist * multiplicator;
++
++    SbVec3f direction;
++    cam->orientation.getValue().multVec(SbVec3f(0, 0, -1), direction);
++
++    const SbVec3f oldpos = cam->position.getValue();
++    const SbVec3f newpos = oldpos + (newfocaldist - oldfocaldist) * -direction;
++
++    // This catches a rather common user interface "buglet": if the
++    // user zooms the camera out to a distance from origo larger than
++    // what we still can safely do floating point calculations on
++    // (i.e. without getting NaN or Inf values), the faulty floating
++    // point values will propagate until we start to get debug error
++    // messages and eventually an assert failure from core Coin code.
++    //
++    // With the below bounds check, this problem is avoided.
++    //
++    // (But note that we depend on the input argument ''diffvalue'' to
++    // be small enough that zooming happens gradually. Ideally, we
++    // should also check distorigo with isinf() and isnan() (or
++    // inversely; isinfite()), but those only became standardized with
++    // C99.)
++    const float distorigo = newpos.length();
++    // sqrt(FLT_MAX) == ~ 1e+19, which should be both safe for further
++    // calculations and ok for the end-user and app-programmer.
++    if (distorigo > float(sqrt(FLT_MAX))) {
++#if SO at GUI@_DEBUG && 0 // debug
++      SoDebugError::postWarning("SoGuiFullViewerP::zoom",
++                                "zoomed too far (distance to origo==%f (%e))",
++                                distorigo, distorigo);
++#endif // debug
++    }
++    else {
++      cam->position = newpos;
++      cam->focalDistance = newfocaldist;
++    }
++  }
++}
++
++// ************************************************************************
++
++#endif // DOXYGEN_SKIP_THIS
++
++#undef PRIVATE
++#undef PUBLIC
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiFullViewer.h.in
+@@ -0,0 +1,177 @@
++#ifndef SO at GUI@_FULLVIEWER_H
++#define SO at GUI@_FULLVIEWER_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/viewers/So at Gui@Viewer.h>
++
++class So at Gui@PopupMenu;
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@FullViewer : public So at Gui@Viewer {
++  SO at GUI@_OBJECT_ABSTRACT_HEADER(So at Gui@FullViewer, So at Gui@Viewer);
++
++public:
++  enum BuildFlag {
++    BUILD_NONE       = 0x00,
++    BUILD_DECORATION = 0x01,
++    BUILD_POPUP      = 0x02,
++    BUILD_ALL        = (BUILD_DECORATION | BUILD_POPUP)
++  };
++
++  void setDecoration(const SbBool on);
++  SbBool isDecoration(void) const;
++
++  void setPopupMenuEnabled(const SbBool on);
++  SbBool isPopupMenuEnabled(void) const;
++
++  @WIDGET@ getAppPushButtonParent(void) const;
++  void addAppPushButton(@WIDGET@ newButton);
++  void insertAppPushButton(@WIDGET@ newButton, int index);
++  void removeAppPushButton(@WIDGET@ oldButton);
++  int findAppPushButton(@WIDGET@ oldButton) const;
++  int lengthAppPushButton(void) const;
++
++  @WIDGET@ getRenderAreaWidget(void) const;
++
++  virtual void setViewing(SbBool on);
++
++  virtual void setComponentCursor(const So at Gui@Cursor & cursor);
++
++protected:
++  So at Gui@FullViewer(@WIDGET@ parent,
++                    const char * name,
++                    SbBool embed,
++                    BuildFlag flag,
++                    Type type,
++                    SbBool build);
++  ~So at Gui@FullViewer();
++
++  virtual void sizeChanged(const SbVec2s & size);
++
++  @WIDGET@ buildWidget(@WIDGET@ parent);
++
++  virtual void buildDecoration(@WIDGET@ parent);
++  virtual @WIDGET@ buildLeftTrim(@WIDGET@ parent);
++  virtual @WIDGET@ buildBottomTrim(@WIDGET@ parent);
++  virtual @WIDGET@ buildRightTrim(@WIDGET@ parent);
++  @WIDGET@ buildAppButtons(@WIDGET@ parent);
++  @WIDGET@ buildViewerButtons(@WIDGET@ parent);
++  virtual void createViewerButtons(@WIDGET@ parent, SbPList * buttonlist);
++
++  virtual void buildPopupMenu(void);
++  virtual void setPopupMenuString(const char * title);
++  virtual void openPopupMenu(const SbVec2s position);
++
++  virtual void leftWheelStart(void);
++  virtual void leftWheelMotion(float);
++  virtual void leftWheelFinish(void);
++  float getLeftWheelValue(void) const;
++  void setLeftWheelValue(const float value);
++
++  virtual void bottomWheelStart(void);
++  virtual void bottomWheelMotion(float);
++  virtual void bottomWheelFinish(void);
++  float getBottomWheelValue(void) const;
++  void setBottomWheelValue(const float value);
++
++  virtual void rightWheelStart(void);
++  virtual void rightWheelMotion(float);
++  virtual void rightWheelFinish(void);
++  float getRightWheelValue(void) const;
++  void setRightWheelValue(const float value);
++
++  void setLeftWheelString(const char * const name);
++  @WIDGET@ getLeftWheelLabelWidget(void) const;
++  void setBottomWheelString(const char * const name);
++  @WIDGET@ getBottomWheelLabelWidget(void) const;
++  void setRightWheelString(const char * const name);
++  const char * getRightWheelString() const;
++  @WIDGET@ getRightWheelLabelWidget(void) const;
++
++  virtual SbBool processSoEvent(const SoEvent * const event);
++
++protected:
++  @WIDGET@ leftWheel;
++  @WIDGET@ rightWheel;
++  @WIDGET@ bottomWheel;
++
++  @WIDGET@ leftDecoration;
++  @WIDGET@ rightDecoration;
++  @WIDGET@ bottomDecoration;
++
++  @WIDGET@ leftWheelLabel;
++  char * leftWheelStr;
++  float leftWheelVal;
++
++  @WIDGET@ rightWheelLabel;
++  char * rightWheelStr;
++  float rightWheelVal;
++
++  @WIDGET@ bottomWheelLabel;
++  char * bottomWheelStr;
++  float bottomWheelVal;
++
++  So at Gui@PopupMenu * prefmenu;
++
++private:
++  // Private class for implementation hiding. The idiom we're using is
++  // a variant of what is known as the "Cheshire Cat", and is also
++  // described as the "Bridge" pattern in �Design Patterns� by Gamma
++  // et al (aka The Gang Of Four).
++  class So at Gui@FullViewerP * pimpl;
++
++  friend class SoGuiFullViewerP;
++  friend class So at Gui@FullViewerP;
++
++
++
++// FIXME: get rid of non-templatized code. 20020108 mortene.
++
++#ifdef __COIN_SOXT__ // FIXME: get rid of non-templatized code. 20020108 mortene.
++protected:
++  Widget buildFunctionsSubmenu(Widget popup);
++  Widget buildDrawStyleSubmenu(Widget popup);
++
++  char * popupTitle;
++  SbBool popupEnabled;
++  SbPList * viewerButtonWidgets;
++#endif // __COIN_SOXT__
++};
++
++// *************************************************************************
++
++#endif // ! SO at GUI@_FULLVIEWER_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiFullViewerP.h.in
+@@ -0,0 +1,154 @@
++#ifndef SOGUIFULLVIEWERP_H
++#define SOGUIFULLVIEWERP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/SbString.h>
++#include <Inventor/@Gui@/viewers/So at Gui@Viewer.h>
++
++class So at Gui@FullViewer;
++
++// ************************************************************************
++
++// This class contains private data and methods used within the
++// SoGuiFullViewer class.
++
++class SoGuiFullViewerP
++{
++public:
++  ~SoGuiFullViewerP();
++
++  enum So at Gui@FullViewerPopupMenuItem {
++    // FIXME: there's code in (some of) the popupmenu widgets which
++    // assumes the root id is equal to 0.  Yup, lousy design. :-/
++    // Anyway, don't change it until those cases are fixed.
++    // 20010810 mortene.
++    ROOT_MENU = 0,
++      ROOT_MENU_TITLE,
++
++      FUNCTIONS_MENU,
++      HOME_ITEM,
++      SET_HOME_ITEM,
++      VIEW_ALL_ITEM,
++      SEEK_ITEM,
++
++      DRAWSTYLES_MENU,
++      DRAWSTYLES_STILL_MENU,
++      AS_IS_ITEM,
++      HIDDEN_LINE_ITEM,
++      WIREFRAME_OVERLAY_ITEM,
++      NO_TEXTURE_ITEM,
++      LOW_RESOLUTION_ITEM,
++      WIREFRAME_ITEM,
++      POINTS_ITEM,
++      BOUNDING_BOX_ITEM,
++
++      DRAWSTYLES_ANIMATING_MENU,
++      MOVE_SAME_AS_STILL_ITEM,
++      MOVE_NO_TEXTURE_ITEM,
++      MOVE_LOW_RES_ITEM,
++      MOVE_WIREFRAME_ITEM,
++      MOVE_LOW_RES_WIREFRAME_ITEM,
++      MOVE_POINTS_ITEM,
++      MOVE_LOW_RES_POINTS_ITEM,
++      MOVE_BOUNDING_BOX_ITEM,
++
++      TRANSPARENCY_TYPE_MENU,
++      SCREEN_DOOR_TRANSPARENCY_ITEM,
++      ADD_TRANSPARENCY_ITEM,
++      DELAYED_ADD_TRANSPARENCY_ITEM,
++      SORTED_OBJECT_ADD_TRANSPARENCY_ITEM,
++      BLEND_TRANSPARENCY_ITEM,
++      DELAYED_BLEND_TRANSPARENCY_ITEM,
++      SORTED_OBJECT_BLEND_TRANSPARENCY_ITEM,
++      // These are Coin extensions.
++      SORTED_OBJECT_SORTED_TRIANGLE_ADD_TRANSPARENCY_ITEM,
++      SORTED_OBJECT_SORTED_TRIANGLE_BLEND_TRANSPARENCY_ITEM,
++      SORTED_LAYERS_BLEND_ITEM,
++      NONE_TRANSPARENCY_ITEM,
++
++      RENDER_BUFFER_TYPE_MENU,
++      SINGLE_BUFFER_ITEM,
++      DOUBLE_BUFFER_ITEM,
++      INTERACTIVE_BUFFER_ITEM,
++
++      EXAMINING_ITEM,
++      DECORATION_ITEM,
++      HEADLIGHT_ITEM,
++      FULLSCREEN_ITEM,
++
++      STEREO_MENU,
++        STEREO_OFF_ITEM,
++        STEREO_ANAGLYPH_ITEM,
++        STEREO_QUADBUFFER_ITEM,
++        STEREO_INTERLEAVED_ROWS_ITEM,
++        STEREO_INTERLEAVED_COLUMNS_ITEM
++      };
++
++  enum So at Gui@ViewerPopupMenuRadioGroup {
++    STILL_GROUP = 1,
++      MOVE_GROUP,
++      TRANSPARENCY_GROUP,
++      BUFFER_GROUP,
++      STEREO_GROUP
++      };
++
++  class So at Gui@PopupMenu * setupStandardPopupMenu(void);
++  void prepareMenu(class So at Gui@PopupMenu * menu);
++  void menuSelection(int menuitemid);
++  static void menuSelectionCallback(int menuitemid, void * userdata);
++  SbString popupmenutitle;
++
++  void setDrawStyleMenuActivation(So at Gui@Viewer::DrawType type,
++                                  So at Gui@Viewer::DrawStyle value);
++  void drawstyleActivated(int menuitemid);
++
++  static void pan(SoCamera * cam,
++                  float aspectratio, const SbPlane & panplane,
++                  const SbVec2f & currpos, const SbVec2f & prevpos);
++  static void zoom(SoCamera * cam, const float diffvalue);
++
++protected:
++  SoGuiFullViewerP(So at Gui@FullViewer * publ);
++  So at Gui@FullViewer * pub;
++};
++
++// ************************************************************************
++
++#endif // ! SOGUIFULLVIEWERP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiPlaneViewer.cpp.in
+@@ -0,0 +1,990 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// This file contains the generic, "templatize-able" parts of the
++// So*PlaneViewer sourcecode.
++
++/*!
++  \class So at Gui@PlaneViewer Inventor/@Gui@/viewers/So at Gui@PlaneViewer.h
++  \brief The So at Gui@PlaneViewer class is for examining 3D models by moving the camera in orthogonal planes.
++  \ingroup components viewers
++
++  The So at Gui@PlaneViewer is a viewer that is useful for "CAD-style"
++  applications, where you want the end-user to examine your model with
++  the viewpoint set from one of the three principal axes.
++
++  <center>
++  <img src="http://doc.coin3d.org/images/SoLibs/viewers/planeviewer.png">
++  </center>
++
++
++  Controls:
++  <ul>
++
++  <li>hold down left mousebutton and move mouse pointer to dolly (or
++  hold both left and middle mousebuttons)</li>
++
++  <li>hold middle mousebutton to pan (or a CTRL-key plus left
++  mousebutton, or a SHIFT-key plus left mousebutton)</li>
++
++  <li>hold down CTRL + middle mousebutton to rotate (or CTRL + SHIFT +
++  the left mousebutton)</li>
++
++  <li>click 's', then pick with the left mousebutton to seek</li>
++
++  <li>right mousebutton open the popup menu</li>
++
++  <li>click 'ESC' key to switch to and from 'view' mode and
++  'scenegraph interaction' mode (see setViewing() documentation)</li>
++
++  <!-- 
++    FIXME: This functionality has been disabled. See FIXME comment
++    20050202 larsa below.
++
++  <li>hold down the 'ALT' key to temporary toggle from  
++      camera-interaction mode to scenegraph-interaction mode</li>  
++
++  //-->
++
++  </ul>
++
++  Hitting any of the X, Y or Z buttons in the panel on the right side
++  of the render canvas will "flip" the current camera direction around
++  it's focal point to point along the selected axis (towards negative
++  infinity).
++
++  The So at Gui@PlaneViewer also provides a user decoration's button for
++  toggling between orthographic or perspective camera view volumes and
++  projection methods. This is the bottom-most click button on the
++  right decoration border.
++
++  It also inherits the decoration buttons from the So at Gui@FullViewer:
++  the arrow for switching to "scenegraph interaction" mode, the hand
++  for setting back to "camera interaction" mode, the house for "reset
++  camera to home position", the blueprint house for "set new camera
++  home position", the eye for "zoom camera out to view full scene" and
++  the flashlight for setting "click to seek" mode.
++
++  Note that a common faulty assumption about all the viewer-classes is
++  that user interaction (in the "examine"-mode, not the
++  scenegraph-interaction mode) influences the model or 3D-scene in the
++  view. This is not correct, as it is always the viewer's \e camera
++  that is translated and rotated.
++
++  The initial position of the camera is placed such that all of the
++  scenegraph's geometry fits within it's view.
++*/
++
++// *************************************************************************
++
++#include <Inventor/@Gui@/viewers/So at Gui@PlaneViewer.h>
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <assert.h>
++#include <math.h>
++
++#include <Inventor/@Gui@/common/gl.h>
++#include <Inventor/@Gui@/So at Gui@Cursor.h>
++
++#include <Inventor/SbLinear.h>
++#include <Inventor/actions/SoSearchAction.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/nodes/SoCoordinate3.h>
++#include <Inventor/nodes/SoDrawStyle.h>
++#include <Inventor/nodes/SoOrthographicCamera.h>
++#include <Inventor/nodes/SoPerspectiveCamera.h>
++#include <Inventor/events/SoMouseButtonEvent.h>
++#include <Inventor/events/SoLocation2Event.h>
++#include <Inventor/events/SoKeyboardEvent.h>
++
++#include <so at gui@defs.h>
++
++#include <Inventor/@Gui@/viewers/SoGuiFullViewerP.h> // for pan() and zoom()
++#include <Inventor/@Gui@/viewers/SoGuiViewerP.h> // for adjusting final camera orientation before seek
++#include <Inventor/@Gui@/viewers/So at Gui@PlaneViewerP.h>
++
++// *************************************************************************
++
++// To access SoGuiPlaneViewerP "private implementation" class.
++
++#define PRIVATE(ptr) (ptr->pimpl)
++
++// *************************************************************************
++
++SO at GUI@_OBJECT_SOURCE(So at Gui@PlaneViewer);
++
++// ************************************************************************
++
++/*!
++  \fn So at Gui@PlaneViewer::So at Gui@PlaneViewer(@WIDGET@ parent, const char * const name, SbBool embed, So at Gui@FullViewer::BuildFlag flag, So at Gui@Viewer::Type type)
++
++  The public constructor, to be used by application programmers who
++  want to instantiate the plain, standard So at Gui@PlaneViewer.
++*/
++So at Gui@PlaneViewer::So at Gui@PlaneViewer(@WIDGET@ parent,
++                                       const char * const name,
++                                       SbBool embed,
++                                       So at Gui@FullViewer::BuildFlag flag,
++                                       So at Gui@Viewer::Type type)
++  : inherited(parent, name, embed, flag, type, FALSE)
++{
++  PRIVATE(this) = new So at Gui@PlaneViewerP(this);
++  PRIVATE(this)->constructor(TRUE);
++}
++
++/*!
++  \fn So at Gui@PlaneViewer::So at Gui@PlaneViewer(@WIDGET@ parent, const char * const name, SbBool embed, So at Gui@FullViewer::BuildFlag flag, So at Gui@Viewer::Type type, SbBool build)
++
++  A protected constructor, to be used by application programmers who
++  want to extend the So at Gui@PlaneViewer.
++*/
++So at Gui@PlaneViewer::So at Gui@PlaneViewer(@WIDGET@ parent,
++                                       const char * const name,
++                                       SbBool embed,
++                                       So at Gui@FullViewer::BuildFlag flag,
++                                       So at Gui@Viewer::Type type,
++                                       SbBool build)
++  : inherited(parent, name, embed, flag, type, FALSE)
++{
++  PRIVATE(this) = new So at Gui@PlaneViewerP(this);
++  PRIVATE(this)->constructor(build);
++}
++
++/*!
++  \fn So at Gui@PlaneViewer::~So at Gui@PlaneViewer()
++
++  The destructor. Cleans up all internal resources used by the
++  So at Gui@PlaneViewer instance.
++*/
++So at Gui@PlaneViewer::~So at Gui@PlaneViewer()
++{
++  delete PRIVATE(this);
++}
++
++// ************************************************************************
++
++// Documented in superclass.
++SbBool
++So at Gui@PlaneViewer::processSoEvent(const SoEvent * const ev)
++{
++#if SO at GUI@_DEBUG && 0 // debug
++  SoDebugError::postInfo("So at Gui@PlaneViewer::processSoEvent",
++                          "[invoked], event '%s' "
++                         "(isViewing()==%d, isSeekMode()==%d, mode==%d)",
++                         ev->getTypeId().getName().getString(),
++                         this->isViewing(), this->isSeekMode(),
++                         PRIVATE(this)->mode);
++#endif // debug
++
++  // We're in "interact" mode (ie *not* the camera modification mode),
++  // so don't handle the event here. It should either be forwarded to
++  // the scenegraph, or caught by So at Gui@Viewer::processSoEvent() if
++  // it's an ESC and ALT press (to switch modes).
++  if (!this->isViewing()) { return inherited::processSoEvent(ev); }
++    
++  // Events when in "ready-to-seek" mode are ignored, except those
++  // which influence the seek mode itself -- these are handled further
++  // up the inheritance hierarchy.
++  if (this->isSeekMode()) { return inherited::processSoEvent(ev); }
++
++
++  SbBool processed = FALSE;
++  const SoGuiPlaneViewerP::PlaneViewerMode currentmode = PRIVATE(this)->mode;
++  SoGuiPlaneViewerP::PlaneViewerMode newmode = currentmode;
++
++  const SoType type(ev->getTypeId());
++
++  const SbVec2s size(this->getGLSize());
++  const SbVec2s pos(ev->getPosition());
++  const SbVec2f posn((float)pos[0] / (float) So at Gui@Max(size[0], (short int)1),
++                     (float)pos[1] / (float) So at Gui@Max(size[1], (short int)1));
++
++  PRIVATE(this)->ctrldown = ev->wasCtrlDown();
++  PRIVATE(this)->shiftdown = ev->wasShiftDown();
++
++  if (type.isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) {
++    processed = TRUE;
++    const SoMouseButtonEvent * event = (const SoMouseButtonEvent *) ev;
++    const SbBool press = (event->getState() == SoButtonEvent::DOWN) ? TRUE : FALSE;
++
++    if (press) {
++      // Called twice to initialize both "now" (current) and "then"
++      // (previous) pointer location.
++      PRIVATE(this)->setPointerLocation(pos);
++      PRIVATE(this)->setPointerLocation(pos);
++    }
++
++    switch (event->getButton()) {
++      case SoMouseButtonEvent::BUTTON1:
++        PRIVATE(this)->button1down = press;
++
++        if (press && (currentmode == SoGuiPlaneViewerP::SEEK_WAIT_MODE)) {
++          newmode = SoGuiPlaneViewerP::SEEK_MODE;
++          this->seekToPoint(pos); // implicitly calls interactiveCountInc()
++        }
++        break;
++
++      case SoMouseButtonEvent::BUTTON2:
++        processed = FALSE; // pass on to superclass, so popup menu is shown
++        break;
++
++      case SoMouseButtonEvent::BUTTON3:
++        PRIVATE(this)->button3down = press;
++        break;
++
++#ifdef HAVE_SOMOUSEBUTTONEVENT_BUTTON5
++      case SoMouseButtonEvent::BUTTON4:
++        if (press) SoGuiFullViewerP::zoom(this->getCamera(), 0.1f);
++        break;
++
++      case SoMouseButtonEvent::BUTTON5:
++        if (press) SoGuiFullViewerP::zoom(this->getCamera(), -0.1f);
++        break;
++#endif // HAVE_SOMOUSEBUTTONEVENT_BUTTON5
++
++      default:
++        break;
++    } // switch (event->getButton())
++  } // SoMouseButtonEvent::getClassTypeId()
++
++  if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
++    const SoKeyboardEvent * event = (const SoKeyboardEvent *) ev;
++    const SbBool press = (event->getState() == SoButtonEvent::DOWN) ? TRUE : FALSE;
++
++#if SO at GUI@_DEBUG && 0 // debug
++    SoDebugError::postInfo("So at Gui@PlaneViewer::processSoEvent",
++                           "keyboard %s: \"%c\"",
++                           press ? "press" : "release",
++                           event->getPrintableCharacter());
++#endif // debug
++
++    switch (event->getKey()) {
++    case SoKeyboardEvent::LEFT_CONTROL:
++    case SoKeyboardEvent::RIGHT_CONTROL:
++      processed = TRUE;
++      PRIVATE(this)->ctrldown = press;
++      break;
++    case SoKeyboardEvent::LEFT_SHIFT:
++    case SoKeyboardEvent::RIGHT_SHIFT:
++      processed = TRUE;
++      PRIVATE(this)->shiftdown = press;
++      break;
++
++    default:
++      break;
++    }
++
++  } // SoKeyboardEvent::getClassTypeId()
++
++
++  if (type.isDerivedFrom(SoLocation2Event::getClassTypeId())) {
++    processed = TRUE;
++    const SoLocation2Event * event = (const SoLocation2Event *) ev;
++    PRIVATE(this)->setPointerLocation(pos);
++    const SbVec2f prevn((float) PRIVATE(this)->pointer.then[0] / (float) So at Gui@Max(size[0], (short int)1),
++                        (float) PRIVATE(this)->pointer.then[1] / (float) So at Gui@Max(size[1], (short int)1));
++
++    do {
++      if (currentmode == SoGuiPlaneViewerP::ROTZ_MODE) {
++        PRIVATE(this)->rotateZ(PRIVATE(this)->getPointerOrigoMotionAngle());
++        break;
++      }
++
++      if (currentmode == SoGuiPlaneViewerP::TRANSLATE_MODE) {
++        if (posn != prevn) {
++          SoGuiFullViewerP::pan(this->getCamera(), this->getGLAspectRatio(),
++                                PRIVATE(this)->panningplane, posn, prevn);
++        }
++        break;
++      }
++
++      if (currentmode == SoGuiPlaneViewerP::DOLLY_MODE) {
++        if (posn[1] != prevn[1]) {
++          float value = this->getRightWheelValue() + (prevn[1] - posn[1]) * 10.0f;
++          this->rightWheelMotion(value);
++          this->setRightWheelValue(value);
++        }
++        break;
++      }
++
++    } while (FALSE);
++  } // SoLocation2Event::getClassTypeId()
++
++  enum {
++    BUTTON1DOWN = 1 << 0,
++    BUTTON3DOWN = 1 << 1,
++    CTRLDOWN =    1 << 2,
++    SHIFTDOWN =   1 << 3
++  };
++  unsigned int combo =
++    (PRIVATE(this)->button1down ? BUTTON1DOWN : 0) |
++    (PRIVATE(this)->button3down ? BUTTON3DOWN : 0) |
++    (PRIVATE(this)->ctrldown ? CTRLDOWN : 0) |
++    (PRIVATE(this)->shiftdown ? SHIFTDOWN : 0);
++
++#if SO at GUI@_DEBUG && 0 // debug
++  SoDebugError::postInfo("So at Gui@PlaneViewer::processSoEvent",
++                         "button1==%d, button3==%d, "
++                         "ctrl==%d, shift==%d",
++                         PRIVATE(this)->button1down, PRIVATE(this)->button3down,
++                         PRIVATE(this)->ctrldown,
++                         PRIVATE(this)->shiftdown);
++#endif // debug
++  
++
++  switch (combo) {
++  case BUTTON1DOWN:
++  case BUTTON1DOWN|BUTTON3DOWN:
++    newmode = SoGuiPlaneViewerP::DOLLY_MODE;
++    break;
++  case BUTTON3DOWN:
++  case CTRLDOWN|BUTTON1DOWN:
++  case SHIFTDOWN|BUTTON1DOWN:
++    newmode = SoGuiPlaneViewerP::TRANSLATE_MODE;
++    break;
++  case CTRLDOWN|BUTTON3DOWN:
++  case CTRLDOWN|SHIFTDOWN|BUTTON1DOWN:
++    newmode = SoGuiPlaneViewerP::ROTZ_MODE;
++    break;
++  case CTRLDOWN:
++  case CTRLDOWN|SHIFTDOWN:
++    newmode = SoGuiPlaneViewerP::ROTZ_WAIT_MODE;
++    break;
++  default:
++    if ((currentmode != SoGuiPlaneViewerP::SEEK_WAIT_MODE) &&
++        (currentmode != SoGuiPlaneViewerP::SEEK_MODE)) {
++      newmode = SoGuiPlaneViewerP::IDLE_MODE;
++    }
++    break;
++  }
++
++  if (newmode != currentmode) {
++    if (newmode == SoGuiPlaneViewerP::ROTZ_MODE) {
++      PRIVATE(this)->setCanvasSize(size);
++      PRIVATE(this)->setPointerLocation(pos);
++      PRIVATE(this)->setPointerLocation(pos);
++    }
++
++    PRIVATE(this)->changeMode(newmode);
++  }
++
++  // If not handled in this class, pass on upwards in the inheritance
++  // hierarchy.
++  return processed || inherited::processSoEvent(ev);
++}
++
++// ************************************************************************
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::actualRedraw(void)
++{
++  if (PRIVATE(this)->mode == SoGuiPlaneViewerP::ROTZ_MODE) {
++    PRIVATE(this)->updateAnchorScenegraph();
++  }
++
++  inherited::actualRedraw();
++}
++
++// ************************************************************************
++
++// documented in superclass
++void
++So at Gui@PlaneViewer::setSeekMode(SbBool on)
++{
++#if SO at GUI@_DEBUG
++  if (!!on == !!this->isSeekMode()) {
++    SoDebugError::postWarning("So at Gui@PlaneViewer::setSeekMode",
++                              "seek mode already %sset", on ? "" : "un");
++    return;
++  }
++#endif // SO at GUI@_DEBUG
++
++  inherited::setSeekMode(on);
++
++  PRIVATE(this)->changeMode(on ?
++                            SoGuiPlaneViewerP::SEEK_WAIT_MODE :
++                            (this->isViewing() ?
++                             SoGuiPlaneViewerP::IDLE_MODE :
++                             SoGuiPlaneViewerP::SCENEGRAPH_INTERACT_MODE));
++}
++
++// ************************************************************************
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::setCursorEnabled(SbBool enable)
++{
++  inherited::setCursorEnabled(enable);
++  PRIVATE(this)->setCursorRepresentation(PRIVATE(this)->mode);
++}
++
++// ************************************************************************
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::setViewing(SbBool enable)
++{
++  if (!!enable == !!this->isViewing()) {
++#if SO at GUI@_DEBUG
++    SoDebugError::postWarning("SoQtPlaneViewer::setViewing",
++                              "unnecessary invocation");
++#endif // SO at GUI@_DEBUG
++    return;
++  }
++
++  inherited::setViewing(enable);
++
++  PRIVATE(this)->changeMode(this->isViewing() ? 
++                            SoGuiPlaneViewerP::IDLE_MODE :
++                            SoGuiPlaneViewerP::SCENEGRAPH_INTERACT_MODE);
++}
++
++// ************************************************************************
++
++// Documented in superclass.
++const char *
++So at Gui@PlaneViewer::getDefaultWidgetName(void) const
++{
++  return "So at Gui@PlaneViewer";
++}
++
++// Documented in superclass.
++const char *
++So at Gui@PlaneViewer::getDefaultTitle(void) const
++{
++  return "Plane Viewer";
++}
++
++// Documented in superclass.
++const char *
++So at Gui@PlaneViewer::getDefaultIconTitle(void) const
++{
++  return "Plane Viewer";
++}
++
++// ************************************************************************
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::bottomWheelStart(void)
++{
++  PRIVATE(this)->changeMode(SoGuiPlaneViewerP::TRANSLATE_MODE);
++}
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::bottomWheelMotion(float value)
++{
++  // This method set up the bottom wheel to control camera translation
++  // in the horizontal direction.
++
++  if (value != this->getBottomWheelValue()) {
++    SoGuiFullViewerP::pan(this->getCamera(), this->getGLAspectRatio(),
++                          PRIVATE(this)->panningplane,
++                          SbVec2f(value, 0),
++                          SbVec2f(this->getBottomWheelValue(), 0));
++  }
++  inherited::bottomWheelMotion(value);
++}
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::bottomWheelFinish(void)
++{
++  PRIVATE(this)->changeMode(SoGuiPlaneViewerP::IDLE_MODE);
++}
++
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::leftWheelStart(void)
++{
++  PRIVATE(this)->changeMode(SoGuiPlaneViewerP::TRANSLATE_MODE);
++}
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::leftWheelMotion(float value)
++{
++  // This method set up the left wheel to control camera translation
++  // in the vertical direction.
++
++  if (value != this->getLeftWheelValue()) {
++    SoGuiFullViewerP::pan(this->getCamera(), this->getGLAspectRatio(),
++                          PRIVATE(this)->panningplane,
++                          SbVec2f(0, this->getLeftWheelValue()),
++                          SbVec2f(0, value));
++  }
++
++  inherited::leftWheelMotion(value);
++}
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::leftWheelFinish(void)
++{
++  PRIVATE(this)->changeMode(SoGuiPlaneViewerP::IDLE_MODE);
++}
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::rightWheelStart(void)
++{
++  PRIVATE(this)->changeMode(SoGuiPlaneViewerP::DOLLY_MODE);
++}
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::rightWheelMotion(float value)
++{
++  // This method set up the right wheel to control camera movement in
++  // the inwards direction.
++
++  SoGuiFullViewerP::zoom(this->getCamera(), this->getRightWheelValue() - value);
++  inherited::rightWheelMotion(value);
++}
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::rightWheelFinish(void)
++{
++  PRIVATE(this)->changeMode(SoGuiPlaneViewerP::IDLE_MODE);
++}
++
++// ************************************************************************
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::afterRealizeHook(void)
++{
++  PRIVATE(this)->setCursorRepresentation(PRIVATE(this)->mode);
++  inherited::afterRealizeHook();
++}
++
++// ************************************************************************
++
++#ifndef DOXYGEN_SKIP_THIS
++
++// This method locates a named node in the superimposed scene.
++static SoNode *
++get_scenegraph_node(SoSearchAction * search, SoNode * root, const char * name)
++{
++  search->reset();
++  search->setName(SbName(name));
++  search->setInterest(SoSearchAction::FIRST);
++  search->setSearchingAll(TRUE);
++  search->apply(root);
++  assert(search->getPath());
++  return search->getPath()->getTail();
++}
++
++// *************************************************************************
++
++// Remaining code is for the SoGuiPlaneViewerP "private
++// implementation" class.
++
++#define PUBLIC(ptr) (ptr->pub)
++
++SoGuiPlaneViewerP::SoGuiPlaneViewerP(So at Gui@PlaneViewer * publ)
++{
++  PUBLIC(this) = publ;
++}
++
++SoGuiPlaneViewerP::~SoGuiPlaneViewerP()
++{
++  if (this->superimposition != NULL) {
++    PUBLIC(this)->removeSuperimposition(this->superimposition);
++    this->superimposition->unref();
++  }
++}
++
++void
++SoGuiPlaneViewerP::commonConstructor(void)
++{
++  this->mode = SoGuiPlaneViewerP::IDLE_MODE;
++
++  this->canvas = SbVec2s(0, 0);
++  this->pointer.now = SbVec2s(0, 0);
++  this->pointer.then = SbVec2s(0, 0);
++  this->ctrldown = FALSE;
++  this->shiftdown = FALSE;
++  this->button1down = FALSE;
++  this->button3down = FALSE;
++
++
++  static const char * superimposed = {
++    "#Inventor V2.1 ascii\n\n"
++    ""
++    "Separator {"
++    "  DEF so at gui@->orthocam OrthographicCamera {"
++    "    height 1"
++    "    nearDistance 0"
++    "    farDistance 1"
++    "  }"
++    "  LightModel {"
++    "    model BASE_COLOR"
++    "  }"
++    ""
++    "  Separator {"
++    "    DEF so at gui@->geometry Coordinate3 {"
++    "      point ["  // coordinates set from code
++    "       0 0 0,"
++    "       0 0 0," 
++    "       0 0 0,"
++    "       0 0 0"
++    "      ]"
++    "    }"
++    "    BaseColor { rgb 1 1 1 }"
++    "    DEF so at gui@->style0 DrawStyle { }" // lineWidth set in code
++    "    DEF so at gui@->mainline IndexedLineSet {" // fat line (exterior)
++    "      coordIndex ["
++    "        0, 1, -1, 1, 2, -1, 1, 3, -1"
++    "      ]"
++    "    }"
++    "    BaseColor { rgb 0.5 0.5 0.5 }"
++    "    DEF so at gui@->style1 DrawStyle { }" // lineWidth set in code
++    "    USE so at gui@->mainline" // thin line (interior)
++    "  }"
++    "}"
++  };
++
++  SoInput * input = new SoInput;
++  input->setBuffer((void *)superimposed, strlen(superimposed));
++  SbBool ok = SoDB::read(input, this->superimposition);
++  assert(ok && "error in superimposed scenegraph");
++  delete input;
++  this->superimposition->ref();
++
++  SoSearchAction s;
++  this->super.coords = (SoCoordinate3 *)
++    get_scenegraph_node(&s, this->superimposition, "so at gui@->geometry");
++  this->super.camera = (SoOrthographicCamera *)
++    get_scenegraph_node(&s, this->superimposition, "so at gui@->orthocam");
++
++  // drawstyle settings for the superimposed lines will be updated on
++  // demand, according to the capabilities of the GL driver & context.
++  this->lineds[0] = (SoDrawStyle *)
++    get_scenegraph_node(&s, this->superimposition, "so at gui@->style0");
++  this->lineds[1] = (SoDrawStyle *)
++    get_scenegraph_node(&s, this->superimposition, "so at gui@->style1");
++
++  PUBLIC(this)->addSuperimposition(this->superimposition);
++  PUBLIC(this)->setSuperimpositionEnabled(this->superimposition, FALSE);
++}
++
++void
++SoGuiPlaneViewerP::rotateZ(const float angle) const
++{
++  SoCamera * const camera = PUBLIC(this)->getCamera();
++  if (! camera) return; // probably a scene-less viewer
++
++  SbVec3f dir;
++  camera->orientation.getValue().multVec(SbVec3f(0, 0, -1), dir);
++  camera->orientation =
++    camera->orientation.getValue() * SbRotation(dir, angle);
++}
++
++void
++SoGuiPlaneViewerP::viewPlaneX(void) const
++{
++  SoCamera * const camera = PUBLIC(this)->getCamera();
++  if (! camera) return; // probably a scene-less viewer
++
++  SbVec3f dir;
++  camera->orientation.getValue().multVec(SbVec3f(0, 0, -1), dir);
++  SbVec3f focalpoint = camera->position.getValue() +
++    camera->focalDistance.getValue() * dir;
++  camera->position = focalpoint +
++    camera->focalDistance.getValue() * SbVec3f(1, 0, 0);
++  camera->orientation = SbRotation(SbVec3f(0, 1, 0), float(M_PI) / 2.0f);
++}
++
++void
++SoGuiPlaneViewerP::viewPlaneY(void) const
++{
++  SoCamera * const camera = PUBLIC(this)->getCamera();
++  if (! camera) return; // probably a scene-less viewer
++
++  SbVec3f dir;
++  camera->orientation.getValue().multVec(SbVec3f(0, 0, -1), dir);
++  SbVec3f focalpoint = camera->position.getValue() +
++    camera->focalDistance.getValue() * dir;
++  camera->position = focalpoint +
++    camera->focalDistance.getValue() * SbVec3f(0, 1, 0);
++  camera->orientation = SbRotation(SbVec3f(1, 0, 0), -float(M_PI) / 2.0f);
++}
++
++void
++SoGuiPlaneViewerP::viewPlaneZ(void) const
++{
++  SoCamera * const camera = PUBLIC(this)->getCamera();
++  if (! camera) return; // probably a scene-less viewer
++
++  SbVec3f dir;
++  camera->orientation.getValue().multVec(SbVec3f(0, 0, -1), dir);
++  SbVec3f focalpoint = camera->position.getValue() +
++    camera->focalDistance.getValue() * dir;
++  camera->position = focalpoint +
++    camera->focalDistance.getValue() * SbVec3f(0, 0, 1);
++  camera->orientation = SbRotation(SbVec3f(0, 1, 0), 0);
++}
++
++void
++SoGuiPlaneViewerP::setCanvasSize(const SbVec2s size)
++{
++  this->canvas = size;
++}
++
++void
++SoGuiPlaneViewerP::setPointerLocation(const SbVec2s position)
++{
++  this->pointer.then = this->pointer.now;
++  this->pointer.now = position;
++}
++
++int
++SoGuiPlaneViewerP::getPointerXMotion(void) const
++{
++  return this->pointer.now[0] - this->pointer.then[0];
++}
++
++int
++SoGuiPlaneViewerP::getPointerYMotion(void) const
++{
++  return this->pointer.now[1] - this->pointer.then[1];
++}
++
++float
++SoGuiPlaneViewerP::getPointerOrigoAngle(void) const
++{
++  SbVec2s now = this->pointer.now;
++  now[0] -= this->canvas[0] / 2;
++  now[1] -= this->canvas[1] / 2;
++
++  double nowradval = (now[0] != 0) ? atan(fabs((double) (now[1] / now[0]))) : 0.0;
++
++  if (now[0] < 0) nowradval = M_PI - nowradval;
++  if (now[1] < 0) nowradval = 2 * M_PI - nowradval;
++
++  return (float)nowradval;
++}
++
++float
++SoGuiPlaneViewerP::getPointerOrigoMotionAngle(void) const
++{
++  if (this->pointer.then == this->pointer.now)
++    return 0.0f;
++
++  SbVec2s now = this->pointer.now;
++  now[0] -= this->canvas[0] / 2;
++  now[1] -= this->canvas[1] / 2;
++
++  SbVec2s then = this->pointer.then;
++  then[0] -= this->canvas[0] / 2;
++  then[1] -= this->canvas[1] / 2;
++
++  double nowradval = (now[0] != 0) ? atan(fabs((double) (now[1] / now[0]))) : 0.0;
++  if (now[0] < 0) nowradval = M_PI - nowradval;
++  if (now[1] < 0) nowradval = 2 * M_PI - nowradval;
++
++  double thenradval = (then[0] != 0) ? atan(fabs((double) (then[1] / then[0]))) : 0.0;
++  if (then[0] < 0) thenradval = M_PI - thenradval;
++  if (then[1] < 0) thenradval = 2 * M_PI - thenradval;
++
++  return (float)(nowradval - thenradval);
++}
++
++// This method updates the contents of the scenegraph which renders
++// the rotate-"anchor".
++void
++SoGuiPlaneViewerP::updateAnchorScenegraph(void) const
++{
++  // must re-check this, since the GL context may be different between
++  // invocations:
++  SbVec2f range;
++  float granularity;
++  PUBLIC(this)->getLineWidthLimits(range, granularity);
++  // Draw a thinner line on top of a fat line, to make an outline.
++  const float lw0 = So at Gui@Clamp(5.0f, range[0], range[1]);
++  const float lw1 = So at Gui@Clamp(3.0f, range[0], range[1]);
++  if (this->lineds[0]->lineWidth.getValue() != lw0) { this->lineds[0]->lineWidth = lw0; }
++  if (this->lineds[1]->lineWidth.getValue() != lw1) { this->lineds[1]->lineWidth = lw1; }
++
++
++  float x = float(this->pointer.now[0]) / float(this->canvas[0]);
++  float y = float(this->pointer.now[1]) / float(this->canvas[1]);
++
++  float aspectratio = PUBLIC(this)->getViewportRegion().getViewportAspectRatio();
++  SbViewVolume vv = this->super.camera->getViewVolume(aspectratio);
++  // know we have ADJUST_CAMERA mapping
++  if (aspectratio < 1.0f) vv.scale(1.0f / aspectratio);
++
++  SbVec3f p = vv.getPlanePoint(1.0, SbVec2f(x, y));
++
++  this->super.coords->point.set1Value(0, SbVec3f(0, 0, 0));
++  this->super.coords->point.set1Value(1, SbVec3f(p[0], p[1], 0));
++
++  float angle = this->getPointerOrigoAngle();
++  SbRotation r(SbVec3f(0, 0, 1), angle);
++
++  SbVec3f xarrow(-0.02f, -0.1f, 0.0f);
++  r.multVec(xarrow, xarrow);
++  SbVec3f pa = SbVec3f(p[0] + xarrow[0], p[1] + xarrow[1], 0);
++  this->super.coords->point.set1Value(2, SbVec3f(pa[0], pa[1], 0));
++
++  SbVec3f yarrow(-0.02f, 0.1f, 0.0f);
++  r.multVec(yarrow, yarrow);
++  pa = SbVec3f(p[0] + yarrow[0], p[1] + yarrow[1], 0);
++  this->super.coords->point.set1Value(3, SbVec3f(pa[0], pa[1], 0));
++}
++
++// Set cursor graphics according to mode.
++void
++SoGuiPlaneViewerP::setCursorRepresentation(PlaneViewerMode modearg)
++{
++#if SO at GUI@_DEBUG && 0 // debug
++  SoDebugError::postInfo("So at Gui@PlaneViewer::setCursorRepresentation",
++                         "mode==%d", mode);
++#endif // debug
++
++  assert(PUBLIC(this)->getGLWidget());
++
++  if (!PUBLIC(this)->isCursorEnabled()) {
++    PUBLIC(this)->setComponentCursor(So at Gui@Cursor::getBlankCursor());
++    return;
++  }
++
++  switch (modearg) {
++  case SoGuiPlaneViewerP::SCENEGRAPH_INTERACT_MODE:
++    PUBLIC(this)->setComponentCursor(So at Gui@Cursor(So at Gui@Cursor::DEFAULT));
++    break;
++
++  case SoGuiPlaneViewerP::IDLE_MODE:
++  case SoGuiPlaneViewerP::DOLLY_MODE:
++    PUBLIC(this)->setComponentCursor(So at Gui@Cursor(So at Gui@Cursor::UPARROW));
++    break;
++  case SoGuiPlaneViewerP::ROTZ_WAIT_MODE:
++  case SoGuiPlaneViewerP::ROTZ_MODE:
++    PUBLIC(this)->setComponentCursor(So at Gui@Cursor::getRotateCursor());
++    break;
++  case SoGuiPlaneViewerP::SEEK_WAIT_MODE:
++  case SoGuiPlaneViewerP::SEEK_MODE:
++    PUBLIC(this)->setComponentCursor(So at Gui@Cursor(So at Gui@Cursor::CROSSHAIR));
++    break;
++  case SoGuiPlaneViewerP::TRANSLATE_MODE:
++    PUBLIC(this)->setComponentCursor(So at Gui@Cursor::getPanCursor());
++    break;
++  default:
++    assert(0 && "unknown PlaneViewer mode");
++    break;
++  }
++}
++
++
++/*!  
++  Overridden to make sure camera orientation is not affected by a
++  seek
++ */
++void
++So at Gui@PlaneViewer::computeSeekFinalOrientation(void)
++{
++  So at Gui@ViewerP * thisp = ((So at Gui@Viewer *)this)->pimpl;
++  thisp->cameraendorient = thisp->camera->orientation.getValue();
++}
++
++
++void
++SoGuiPlaneViewerP::changeMode(PlaneViewerMode newmode)
++{
++  if (newmode == this->mode) { return; }
++
++  switch (newmode) {
++  case SoGuiPlaneViewerP::TRANSLATE_MODE:
++  case SoGuiPlaneViewerP::DOLLY_MODE:
++    PUBLIC(this)->interactiveCountInc();
++    break;
++
++  case SoGuiPlaneViewerP::ROTZ_MODE:
++    PUBLIC(this)->interactiveCountInc();
++    PUBLIC(this)->setSuperimpositionEnabled(this->superimposition, TRUE);
++    PUBLIC(this)->scheduleRedraw();
++    break;
++
++  default:
++    break;
++  }
++
++  switch (this->mode) {
++  case SoGuiPlaneViewerP::ROTZ_MODE:
++    PUBLIC(this)->setSuperimpositionEnabled(this->superimposition, FALSE);
++    PUBLIC(this)->scheduleRedraw();
++    // fall through
++
++  case SoGuiPlaneViewerP::TRANSLATE_MODE:
++  case SoGuiPlaneViewerP::DOLLY_MODE:
++    PUBLIC(this)->interactiveCountDec();
++    break;
++  default:
++    break;
++  }
++
++  if (newmode == SoGuiPlaneViewerP::TRANSLATE_MODE) {
++    // The plane we're projecting the mouse coordinates to get 3D
++    // coordinates should stay the same during the whole pan
++    // operation, so we should calculate this value here.
++    SoCamera * cam = PUBLIC(this)->getCamera();
++    if (cam == NULL) { // can happen for empty scenegraph
++      this->panningplane = SbPlane(SbVec3f(0, 0, 1), 0);
++    }
++    else {
++      SbViewVolume vv = cam->getViewVolume(PUBLIC(this)->getGLAspectRatio());
++      this->panningplane = vv.getPlane(cam->focalDistance.getValue());
++    }
++  }
++
++  this->setCursorRepresentation(newmode);
++  this->mode = newmode;
++}
++
++#endif // DOXYGEN_SKIP_THIS
++
++// *************************************************************************
++
++#undef PRIVATE
++#undef PUBLIC
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiPlaneViewer.h.in
+@@ -0,0 +1,99 @@
++#ifndef SO at GUI@PLANEVIEWER_H
++#define SO at GUI@PLANEVIEWER_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/viewers/So at Gui@FullViewer.h>
++
++// ************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@PlaneViewer : public So at Gui@FullViewer {
++  SO at GUI@_OBJECT_HEADER(So at Gui@PlaneViewer, So at Gui@FullViewer);
++
++public:
++  So at Gui@PlaneViewer(@WIDGET@ parent = NULL,
++                     const char * const name = NULL, 
++                     SbBool embed = TRUE, 
++                     So at Gui@FullViewer::BuildFlag flag = BUILD_ALL, 
++                     So at Gui@Viewer::Type type = BROWSER);
++  ~So at Gui@PlaneViewer();
++
++  virtual void setViewing(SbBool enable);
++  virtual void setCamera(SoCamera * camera);
++  virtual void setCursorEnabled(SbBool enable);
++
++protected:
++  So at Gui@PlaneViewer(@WIDGET@ parent,
++                     const char * const name, 
++                     SbBool embed, 
++                     So at Gui@FullViewer::BuildFlag flag, 
++                     So at Gui@Viewer::Type type, 
++                     SbBool build);
++
++  @WIDGET@ buildWidget(@WIDGET@ parent);
++
++  virtual const char * getDefaultWidgetName(void) const;
++  virtual const char * getDefaultTitle(void) const;
++  virtual const char * getDefaultIconTitle(void) const;
++
++  virtual SbBool processSoEvent(const SoEvent * const event);
++  virtual void setSeekMode(SbBool enable);
++  virtual void actualRedraw(void);
++
++  virtual void bottomWheelStart(void);
++  virtual void bottomWheelMotion(float value);
++  virtual void bottomWheelFinish(void);
++
++  virtual void leftWheelStart(void);
++  virtual void leftWheelMotion(float value);
++  virtual void leftWheelFinish(void);
++
++  virtual void rightWheelStart(void);
++  virtual void rightWheelMotion(float value);
++  virtual void rightWheelFinish(void);
++
++  virtual void createViewerButtons(@WIDGET@ parent, SbPList * buttons);
++
++  virtual void afterRealizeHook(void);
++  virtual void computeSeekFinalOrientation(void);
++
++private:
++  class So at Gui@PlaneViewerP * pimpl;
++
++  friend class SoGuiPlaneViewerP;
++  friend class So at Gui@PlaneViewerP;
++};
++
++#endif // !SO at GUI@PLANEVIEWER_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiPlaneViewerP.h.in
+@@ -0,0 +1,120 @@
++#ifndef SOGUIPLANEVIEWERP_H
++#define SOGUIPLANEVIEWERP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/SbLinear.h>
++
++class So at Gui@PlaneViewer;
++
++// ************************************************************************
++
++// This class contains private data and methods used within the
++// SoGuiPlaneViewer class.
++
++class SoGuiPlaneViewerP
++{
++public:
++  ~SoGuiPlaneViewerP();
++
++  void commonConstructor(void);
++
++  void pan(const SbVec2f & thispos, const SbVec2f & prevpos);
++  void rotateZ(const float angle) const;
++
++  void viewPlaneX(void) const;
++  void viewPlaneY(void) const;
++  void viewPlaneZ(void) const;
++
++  void setCanvasSize(const SbVec2s size);
++  void setPointerLocation(const SbVec2s location);
++  int getPointerXMotion(void) const;
++  int getPointerYMotion(void) const;
++  float getPointerOrigoAngle(void) const;
++  float getPointerOrigoMotionAngle(void) const;
++
++  void updateAnchorScenegraph(void) const;
++
++  enum PlaneViewerMode {
++    SCENEGRAPH_INTERACT_MODE,
++
++    IDLE_MODE,
++
++    DOLLY_MODE,
++    TRANSLATE_MODE,
++
++    ROTZ_WAIT_MODE,
++    ROTZ_MODE,
++
++    SEEK_WAIT_MODE,
++    SEEK_MODE
++  } mode;
++
++  void changeMode(PlaneViewerMode newmode);
++  void setCursorRepresentation(PlaneViewerMode mode);
++
++  struct pointerdata {
++    SbVec2s now;
++    SbVec2s then;
++  } pointer;
++  SbVec2s canvas;
++
++  SbBool ctrldown;
++  SbBool shiftdown;
++  SbBool button1down;
++  SbBool button3down;
++
++  SbPlane panningplane;
++
++  class SoDrawStyle * lineds[2];
++
++  class SoNode * superimposition;
++  struct superdata {
++    class SoCoordinate3 * coords;
++    class SoOrthographicCamera * camera;
++  } super;
++
++protected:
++  SoGuiPlaneViewerP(So at Gui@PlaneViewer * publ);
++  So at Gui@PlaneViewer * pub;
++};
++
++// ************************************************************************
++
++#endif // ! SOGUIPLANEVIEWERP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiViewer.cpp.in
+@@ -0,0 +1,3862 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// NOTE: The So at Gui@Viewer.cpp sourcecode file is completely
++// autogenerated from "templatized" source code.
++
++// *************************************************************************
++
++/*!
++  \class So at Gui@Viewer Inventor/@Gui@/viewers/So at Gui@Viewer.h
++  \brief The So at Gui@Viewer class is the top level base viewer class.
++  \ingroup components viewers
++
++  This is an abstract class, which adds the following features to it's
++  So at Gui@RenderArea superclass: convenient methods for camera
++  handling, an automatic headlight configuration.
++
++  As for the camera handling: when setting a new scenegraph for the
++  viewer, the scenegraph will automatically be scanned for a node
++  derived from SoCamera. If not found, the viewer will itself set up a
++  camera for the scene. The camera can then be conveniently controlled
++  by the application programmers in many aspects:
++
++  <ul>
++
++  <li>camera type: toggle between using an orthographic camera and a
++  perspective camera with So at Gui@Viewer::toggleCameraType()</li>
++
++  <li>zoom out to exactly encompass all scene geometry within the view
++  by using So at Gui@Viewer::viewAll()</li>
++
++  <li>tag a specific position and orientation for the camera as the
++  "home" position with So at Gui@Viewer::saveHomePosition(), which one
++  can then return to by using
++  So at Gui@Viewer::resetToHomePosition()</li>
++
++  <li>automatically fit the near and far clipping planes of the camera
++  around the scene's geometry by using
++  So at Gui@Viewer::setAutoClipping()</li>
++
++  <li>control stereo viewing parameters</li>
++
++  </ul>
++
++  Note that there is no dragger or manipulator attached to the scene
++  camera.  The camera transform manipulation is calculated in a more
++  direct manner in the non-abstract viewer classes inheriting
++  So at Gui@Viewer by reading mouse and keyboard events and interpreting
++  how these should influence the camera. The calculations results in
++  new values for SoCamera::position, SoCamera::orientation, and the
++  other SoCamera field values for the camera designated to be the
++  viewer viewpoint camera. These values are then inserted directly
++  into the viewer's SoCamera node.
++
++  See e.g. the source code for So at Gui@ExaminerViewer::processSoEvent()
++  for the details.
++
++
++
++  The So at Gui@Viewer class automatically adds a headlight to the scene,
++  which will always point in the approximate same direction as the
++  current viewer camera, thereby securing that the scene geometry is
++  always lighted and visible. (If you don't want the constant
++  headlight, but rather want to light the scene on your own, this
++  behavior can be turned off with So at Gui@Viewer::setHeadlight()).
++
++
++  So at Gui@Viewer-derived viewers all inherit the following keyboard
++  controls from this class (but only when the viewer is in "examine
++  mode", ie So at Gui@Viewer::isViewing() returns \c TRUE):
++
++  <ul>
++
++  <li>"s": put the viewer in "seek mode", where the end user may click
++  anywhere on scene geometry to trigger an animation which moves the
++  camera towards the point clicked</li>
++
++  <li>"Home": hit this key to move camera back to last saved "home
++  position"</li>
++
++  <li>arrow keys: moves camera slightly left, right, up or down</li>
++
++  <li>"q": exit application</li>
++
++  </ul>
++*/
++
++// *************************************************************************
++
++/*!
++  \enum So at Gui@Viewer::AutoClippingStrategy
++
++  Enum for auto clipping strategy.
++  
++  \sa setAutoClippingStrategy()
++*/
++
++/*!
++  \var So at Gui@Viewer::AutoClippingStrategy So at Gui@Viewer::CONSTANT_NEAR_PLANE
++
++  Constant near plane auto clipping strategy. Explained in detail in
++  the documentation for the So at Gui@Viewer::setAutoClippingStrategy()
++  method.
++*/
++
++/*!
++  \var So at Gui@Viewer::AutoClippingStrategy So at Gui@Viewer::VARIABLE_NEAR_PLANE
++
++  Variable near plane auto clipping strategy. Explained in detail in
++  the documentation for the So at Gui@Viewer::setAutoClippingStrategy()
++  method.
++*/
++
++// *************************************************************************
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <stdlib.h>
++#include <string.h>
++#include <math.h>
++#include <float.h> // FLT_MAX
++
++#include <Inventor/SbLinear.h>
++#include <Inventor/SoDB.h>
++#include <Inventor/SoLists.h>
++#include <Inventor/SoPickedPoint.h>
++#include <Inventor/SoSceneManager.h>
++#include <Inventor/actions/SoGetBoundingBoxAction.h>
++#include <Inventor/actions/SoGetMatrixAction.h>
++#include <Inventor/actions/SoRayPickAction.h>
++#include <Inventor/actions/SoSearchAction.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/events/SoKeyboardEvent.h>
++#include <Inventor/events/SoMouseButtonEvent.h>
++#include <Inventor/misc/SoCallbackList.h>
++#include <Inventor/nodekits/SoBaseKit.h>
++#include <Inventor/nodes/SoBaseColor.h>
++#include <Inventor/nodes/SoComplexity.h>
++#include <Inventor/nodes/SoDirectionalLight.h>
++#include <Inventor/nodes/SoDrawStyle.h>
++#include <Inventor/nodes/SoLightModel.h>
++#include <Inventor/nodes/SoLocateHighlight.h>
++#include <Inventor/nodes/SoMaterialBinding.h>
++#include <Inventor/nodes/SoOrthographicCamera.h>
++#include <Inventor/nodes/SoPerspectiveCamera.h>
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoSwitch.h>
++#include <Inventor/SbColor4f.h>
++#include <Inventor/sensors/SoTimerSensor.h>
++
++#ifdef HAVE_SOPOLYGONOFFSET
++#include <Inventor/nodes/SoPolygonOffset.h>
++#endif // HAVE_SOPOLYGONOFFSET
++
++#include <Inventor/@Gui@/So at Gui@.h>
++#include <Inventor/@Gui@/SoAny.h>
++#include <Inventor/@Gui@/common/SbGuiList.h>
++#include <Inventor/@Gui@/common/gl.h>
++#include <Inventor/@Gui@/nodes/SoGuiViewpointWrapper.h>
++#include <Inventor/@Gui@/viewers/So at Gui@Viewer.h>
++#include <Inventor/@Gui@/viewers/SoGuiViewerP.h>
++#include <so at gui@defs.h>
++
++// *************************************************************************
++
++// (note: this *must* be a #define, not a static variable -- to avoid
++// initialization race conditions with the static variables being set
++// to the value of this)
++#define UNINITIALIZED_ENVVAR -1 // value of envvars before tested
++
++// Environment variable for debugging purpose: display a running
++// frames-per-second counter. See code comments above
++// So at Gui@ViewerP::recordFPS() function below for more information.
++static int COIN_SHOW_FPS_COUNTER = UNINITIALIZED_ENVVAR;
++
++// *************************************************************************
++
++#define PRIVATE(ptr) (ptr->pimpl)
++#define PUBLIC(ptr) (ptr->pub)
++
++// *************************************************************************
++
++So at Gui@ViewerP::So at Gui@ViewerP(So at Gui@Viewer * publ)
++{
++  PUBLIC(this) = publ;
++  this->searchaction = new SoSearchAction;
++  this->matrixaction = new SoGetMatrixAction(SbViewportRegion(100,100));
++  this->superimpositions = NULL;
++
++  this->storedcamera = NULL;
++
++  // initialize auto clipping parameters
++  this->autoclipstrategy = So at Gui@Viewer::VARIABLE_NEAR_PLANE;
++  this->autoclipvalue = 0.6f;
++  this->autoclipcb = NULL;
++
++  this->stereotype = So at Gui@Viewer::STEREO_NONE;
++  this->stereotypesetexplicit = FALSE;
++  this->stereostencilmaskvp = SbViewportRegion(0, 0);
++  this->stereostencilmask = NULL;
++  this->stereostenciltype = So at Gui@Viewer::STEREO_NONE;
++  this->stereoanaglyphmask[0][0] = TRUE;
++  this->stereoanaglyphmask[0][1] = this->stereoanaglyphmask[0][2] = FALSE;
++  this->stereoanaglyphmask[1][0] = FALSE;
++  this->stereoanaglyphmask[1][1] = this->stereoanaglyphmask[1][2] = TRUE;
++}
++
++So at Gui@ViewerP::~So at Gui@ViewerP()
++{
++  // This impossible to miss reminder was inserted so we don't
++  // accidentally let an So* v2 slip out the door without fixing this
++  // API design flaw. 20030625 mortene.
++#if (SO at GUI@_MAJOR_VERSION == 2)
++#error This is a reminder: when jumping to version 2 of an So* toolkit, the viewer destructors (at least, possibly also further up in the inheritance hierarchy) should be made virtual.
++#endif // version = 2
++
++  delete[] this->stereostencilmask;
++
++  if ( this->superimpositions != NULL ) delete this->superimpositions;
++  delete this->searchaction;
++  delete this->matrixaction;
++
++  if (this->storedcamera) { this->storedcamera->unref(); }
++}
++
++SoSeparator *
++So at Gui@ViewerP::createSuperScene(void)
++{
++  static const char * superSceneGraph[] =
++  {
++    "#Inventor V2.1 ascii",
++    "",
++    "Separator {",
++    "  renderCaching OFF",
++    "  renderCulling OFF",
++    "  pickCulling OFF",
++    "  boundingBoxCaching OFF",
++    
++    // Headlight. By inserting this before any scenegraph camera, the
++    // light will always be pointing in the correct direction.
++    "  DEF so at gui@->headlight DirectionalLight {",
++    "    direction 1 -1 -10",
++    "  }",
++
++    "  DEF so at gui@->drawstyleroot Switch {",
++    "    whichChild -1",
++    "    DEF so at gui@->lightmodel LightModel {",
++    "      model BASE_COLOR",
++    "    }",
++    "    DEF so at gui@->drawstyle DrawStyle {",
++    "      pointSize ~",
++    "      lineWidth ~",
++    "      linePattern ~",
++    "    }",
++    "    DEF so at gui@->complexity Complexity {",
++    "      textureQuality 0.0",
++    "      value 0.1",
++    "    }",
++    "  }",
++    "  DEF so at gui@->hiddenlineroot Switch {",
++    "    whichChild -1",
++    "    DEF so at gui@->basecolor BaseColor { }",
++    "    DEF so at gui@->materialbinding MaterialBinding {",
++    "      value OVERALL",
++    "    }",
++    "    DEF so at gui@->polygonoffsetparent Switch {",
++    "      whichChild -1",
++#ifdef HAVE_SOPOLYGONOFFSET
++    "      DEF so at gui@->polygonoffset PolygonOffset { }",
++#endif // HAVE_SOPOLYGONOFFSET
++    "    }",
++    "  }",
++    "  DEF so at gui@->userscenegraphroot Separator {",
++    // turn off caching to make it possible for users to disable
++    // caching in their scene graphs.
++    "    renderCaching OFF\n", 
++    "  }",
++    "}",
++    NULL
++  };
++
++  int i, bufsize;
++  for (i = bufsize = 0; superSceneGraph[i]; i++)
++    bufsize += strlen(superSceneGraph[i]) + 1;
++  char * buf = new char [bufsize + 1];
++  for (i = bufsize = 0; superSceneGraph[i]; i++) {
++    strcpy(buf + bufsize, superSceneGraph[i]);
++    bufsize += strlen(superSceneGraph[i]);
++    buf[bufsize] = '\n';
++    bufsize++;
++  }
++  SoInput * input = new SoInput;
++  input->setBuffer(buf, bufsize);
++  SoNode * root = NULL;
++  SbBool ok = SoDB::read(input, root);
++  delete input;
++  delete [] buf;
++  if (!ok) {
++    // FIXME: this looks unnecessary robust, and I believe it should
++    // be replaced by an assert()..? 20030430 mortene.
++    SoDebugError::post("So at Gui@ViewerP::createSuperScene",
++		       "couldn't create viewer superscene");
++    return NULL;
++  }
++  assert(root->isOfType(SoSeparator::getClassTypeId()));
++  root->ref();
++
++  this->searchaction->reset();
++  this->searchaction->setSearchingAll(TRUE);
++  this->searchaction->setInterest(SoSearchAction::FIRST);
++
++#define LOCATE_NODE(member, type, name) \
++  do { \
++    member = NULL; \
++    this->searchaction->setName(SbName(name)); \
++    this->searchaction->apply(root); \
++    if (this->searchaction->getPath() != NULL) { \
++      SoNode * node = this->searchaction->getPath()->getTail(); \
++      assert(node != NULL); \
++      if (node->isOfType(type::getClassTypeId())) \
++        member = (type *) node; \
++    } else { \
++      SoDebugError::post("So at Gui@ViewerP::createSuperScene", \
++                         "didn't locate node \"%s\"", name); \
++    } \
++  } while (FALSE)
++
++  LOCATE_NODE(this->headlight, SoDirectionalLight, "so at gui@->headlight");
++  LOCATE_NODE(this->drawstyleroot, SoSwitch, "so at gui@->drawstyleroot");
++  LOCATE_NODE(this->hiddenlineroot, SoSwitch, "so at gui@->hiddenlineroot");
++  LOCATE_NODE(this->polygonoffsetparent, SoSwitch,
++	      "so at gui@->polygonoffsetparent");
++  LOCATE_NODE(this->usersceneroot, SoSeparator, "so at gui@->userscenegraphroot");
++
++  LOCATE_NODE(this->sobasecolor, SoBaseColor, "so at gui@->basecolor");
++  LOCATE_NODE(this->socomplexity, SoComplexity, "so at gui@->complexity");
++  LOCATE_NODE(this->sodrawstyle, SoDrawStyle, "so at gui@->drawstyle");
++  LOCATE_NODE(this->solightmodel, SoLightModel, "so at gui@->lightmodel");
++  LOCATE_NODE(this->somaterialbinding, SoMaterialBinding, "so at gui@->materialbinding");
++  if (this->sobasecolor) this->sobasecolor->setOverride(TRUE);
++  if (this->socomplexity) this->socomplexity->setOverride(TRUE);
++  if (this->sodrawstyle) this->sodrawstyle->setOverride(TRUE);
++  if (this->solightmodel) this->solightmodel->setOverride(TRUE);
++  if (this->somaterialbinding) this->somaterialbinding->setOverride(TRUE);
++#ifdef HAVE_SOPOLYGONOFFSET
++  LOCATE_NODE(this->sopolygonoffset, SoPolygonOffset, "so at gui@->polygonoffset");
++  if (this->sopolygonoffset) this->sopolygonoffset->setOverride(TRUE);
++#endif // HAVE_SOPOLYGONOFFSET
++
++#undef LOCATE_NODE
++  this->searchaction->reset();
++
++  root->unrefNoDelete();
++  return (SoSeparator *) root;
++}
++
++// Returns the coordinate system the current camera is located in. If
++// there are transformations before the camera in the scene graph,
++// this must be considered before doing certain operations. \a matrix
++// and \a inverse will not contain the transformations caused by the
++// camera fields, only the transformations traversed before the camera
++// in the scene graph.
++void
++So at Gui@ViewerP::getCameraCoordinateSystem(SoCamera * cameraarg,
++                                          SoNode * root,
++                                          SbMatrix & matrix,
++                                          SbMatrix & inverse)
++{
++  this->searchaction->reset();
++  this->searchaction->setSearchingAll(TRUE);
++  this->searchaction->setInterest(SoSearchAction::FIRST);
++  this->searchaction->setNode(cameraarg);
++  this->searchaction->apply(root);
++
++  matrix = inverse = SbMatrix::identity();
++  if (this->searchaction->getPath()) {
++    this->matrixaction->apply(this->searchaction->getPath());
++    matrix = this->matrixaction->getMatrix();
++    inverse = this->matrixaction->getInverse();
++  }
++  this->searchaction->reset();
++}
++
++
++// These functions do this:
++//
++//       * when going from orthocam -> perspectivecam: set the
++//       heightAngle field to its default value (45�), and move
++//       camera to a position where the scene/model would fill about
++//       the same screenspace as it did in the orthocam
++//
++//       * when going from perspectivecam -> orthocam: keep the
++//       current position, but tune the view-volume height so the
++//       scene/model takes up about the same screenspace
++//
++// 20020522 mortene.
++
++void
++So at Gui@ViewerP::convertOrtho2Perspective(const SoOrthographicCamera * in,
++                                         SoPerspectiveCamera * out)
++{
++  out->aspectRatio.setValue(in->aspectRatio.getValue());
++  out->focalDistance.setValue(in->focalDistance.getValue());
++  out->orientation.setValue(in->orientation.getValue());
++  out->position.setValue(in->position.getValue());
++  out->viewportMapping.setValue(in->viewportMapping.getValue());
++  
++  SbRotation camrot = in->orientation.getValue();
++
++  float focaldist = in->height.getValue() / (2.0*tan(M_PI / 8.0));
++  
++  SbVec3f offset(0,0,focaldist-in->focalDistance.getValue());
++
++  camrot.multVec(offset,offset);
++  out->position.setValue(offset+in->position.getValue());
++
++  out->focalDistance.setValue(focaldist);
++  
++  // 45� is the default value of this field in SoPerspectiveCamera.
++    out->heightAngle = (float)(M_PI / 4.0);
++
++#if SO at GUI@_DEBUG && 0 // debug
++  SoDebugError::postInfo("So at Gui@ViewerP::convertOrtho2Perspective",
++                         "perspective heightAngle==%f",
++                         180.0f * out->heightAngle.getValue() / M_PI);
++#endif // debug
++}
++
++void
++So at Gui@ViewerP::convertPerspective2Ortho(const SoPerspectiveCamera * in,
++                                         SoOrthographicCamera * out)
++{
++  out->aspectRatio.setValue(in->aspectRatio.getValue());
++  out->focalDistance.setValue(in->focalDistance.getValue());
++  out->orientation.setValue(in->orientation.getValue());
++  out->position.setValue(in->position.getValue());
++  out->viewportMapping.setValue(in->viewportMapping.getValue());
++
++  float focaldist = in->focalDistance.getValue();
++
++  out->height = 2.0f * focaldist * (float)tan(in->heightAngle.getValue() / 2.0);
++
++#if SO at GUI@_DEBUG && 0 // debug
++  SoDebugError::postInfo("So at Gui@ViewerP::convertOrtho2Perspective",
++                         "ortho height==%f",
++                         out->height.getValue());
++#endif // debug
++}
++
++void
++So at Gui@ViewerP::reallyRedraw(const SbBool clearcol, const SbBool clearz)
++{
++  // Recalculate near/far planes. Must be done in reallyRedraw() --
++  // not actualRedraw() -- so the clipping planes are correct even
++  // when rendering multiple times with different camera settings.
++  if (this->camera && PUBLIC(this)->isAutoClipping()) {
++    // Temporarily turn off notification when changing near and far
++    // clipping planes, to avoid latency.
++    const SbBool notif = this->camera->isNotifyEnabled();
++    this->camera->enableNotify(FALSE);
++    this->setClippingPlanes();
++    this->camera->enableNotify(notif);
++  }
++
++  if (this->drawAsHiddenLine()) {
++
++    // First pass: render as filled, but with the background color.
++
++    this->solightmodel->model.setIgnored(FALSE); // override as SoLightModel::BASE
++    this->sodrawstyle->style.setIgnored(TRUE); // draw as-is filled/lines/points
++    this->socomplexity->type.setIgnored(TRUE); // as-is rendering space
++    this->socomplexity->value.setIgnored(TRUE); // as-is complexity on non-simple shapes
++    // textureQuality field of socomplexity node is always 0.0
++
++    this->sobasecolor->rgb.setValue(PUBLIC(this)->getBackgroundColor());
++    this->sobasecolor->rgb.setIgnored(FALSE);
++    this->somaterialbinding->value.setIgnored(FALSE); // override with OVERALL
++    this->polygonoffsetparent->whichChild = SO_SWITCH_ALL;
++    
++    PUBLIC(this)->getSceneManager()->render(clearcol, clearz);
++    
++    // Second pass, render wireframe on top.
++
++    this->sodrawstyle->style = SoDrawStyle::LINES;
++    this->sodrawstyle->style.setIgnored(FALSE); // force lines
++    this->sobasecolor->rgb.setIgnored(TRUE); // use as-is line colors
++    this->somaterialbinding->value.setIgnored(TRUE); // as-is
++    this->polygonoffsetparent->whichChild = SO_SWITCH_NONE;
++
++    PUBLIC(this)->getSceneManager()->render(FALSE, FALSE);
++
++    return;
++  }
++  if (this->drawAsWireframeOverlay()) {
++    // First pass: render as-is, with polygon offset
++
++    this->solightmodel->model.setIgnored(TRUE);
++    this->somaterialbinding->value.setIgnored(TRUE);
++    this->sobasecolor->rgb.setIgnored(TRUE);
++    this->sodrawstyle->style.setIgnored(TRUE); // draw as-is filled/lines/points
++    this->socomplexity->type.setIgnored(TRUE); // as-is rendering space
++    this->socomplexity->value.setIgnored(TRUE); // as-is complexity on non-simple shapes
++    this->socomplexity->textureQuality.setIgnored(TRUE);
++
++    this->somaterialbinding->value.setIgnored(TRUE); // override with OVERALL
++    this->polygonoffsetparent->whichChild = SO_SWITCH_ALL;
++
++    PUBLIC(this)->getSceneManager()->render(clearcol, clearz);
++
++    // Second pass, render wireframe on top.
++    this->sobasecolor->rgb.setValue(this->wireframeoverlaycolor);
++    this->sobasecolor->rgb.setIgnored(FALSE);
++    this->somaterialbinding->value.setIgnored(FALSE); // override with OVERALL
++
++    this->solightmodel->model.setIgnored(FALSE); // override as SoLightModel::BASE
++    this->sodrawstyle->style = SoDrawStyle::LINES;
++    this->sodrawstyle->style.setIgnored(FALSE); // force lines
++    this->polygonoffsetparent->whichChild = SO_SWITCH_NONE;
++    this->socomplexity->textureQuality.setIgnored(FALSE);
++
++    PUBLIC(this)->getSceneManager()->render(FALSE, FALSE);
++
++    // disable override nodes
++    (void) this->sobasecolor->rgb.enableNotify(FALSE);
++    this->sobasecolor->rgb.setIgnored(TRUE);
++    (void) this->sobasecolor->rgb.enableNotify(TRUE);
++
++    (void) this->somaterialbinding->value.enableNotify(FALSE);
++    this->somaterialbinding->value.setIgnored(TRUE);
++    (void) this->somaterialbinding->value.enableNotify(TRUE);
++
++    (void) this->solightmodel->model.enableNotify(FALSE);
++    this->solightmodel->model.setIgnored(TRUE);
++    (void) this->solightmodel->model.enableNotify(TRUE);
++
++    (void) this->socomplexity->textureQuality.enableNotify(FALSE);
++    this->socomplexity->textureQuality.setIgnored(TRUE);
++    (void) this->socomplexity->textureQuality.enableNotify(TRUE);
++
++    (void) this->sodrawstyle->style.enableNotify(FALSE);
++    this->sodrawstyle->style.setIgnored(TRUE);
++    (void) this->sodrawstyle->style.enableNotify(TRUE);
++    return;
++  }
++
++  SbBool clearzbuffer = TRUE;
++  So at Gui@Viewer::DrawStyle style = this->currentDrawStyle();
++  switch (style) {
++  case So at Gui@Viewer::VIEW_LOW_RES_LINE:
++  case So at Gui@Viewer::VIEW_LOW_RES_POINT:
++  case So at Gui@Viewer::VIEW_BBOX:
++    clearzbuffer = FALSE;
++  default:
++    break; // Include "default:" case to avoid compiler warning.
++  }
++
++  PUBLIC(this)->getSceneManager()->render(clearcol, clearzbuffer && clearz);
++}
++
++
++// *************************************************************************
++
++// Returns a boolean to indicate if the dynamic drawstyle equals
++// the static drawstyle.
++
++SbBool
++So at Gui@ViewerP::drawInteractiveAsStill(void) const
++{
++  SbBool moveasstill = this->drawstyles[So at Gui@Viewer::INTERACTIVE] == So at Gui@Viewer::VIEW_SAME_AS_STILL;
++  if (! moveasstill)
++    moveasstill = this->drawstyles[So at Gui@Viewer::INTERACTIVE] == this->drawstyles[So at Gui@Viewer::STILL];
++  if (! moveasstill)
++    moveasstill =
++      this->drawstyles[So at Gui@Viewer::INTERACTIVE] == So at Gui@Viewer::VIEW_NO_TEXTURE &&
++      this->drawstyles[So at Gui@Viewer::STILL] != So at Gui@Viewer::VIEW_AS_IS;
++  return moveasstill;
++}
++
++// Returns the current drawing style.
++So at Gui@Viewer::DrawStyle
++So at Gui@ViewerP::currentDrawStyle(void) const
++{
++  SbBool interactivemode = PUBLIC(this)->getInteractiveCount() > 0 ? TRUE : FALSE;
++
++  if (!interactivemode || this->drawInteractiveAsStill())
++    return this->drawstyles[So at Gui@Viewer::STILL];
++  else
++    return this->drawstyles[So at Gui@Viewer::INTERACTIVE];
++}
++
++// Returns a boolean to indicate if the current drawstyle settings implies
++// hidden line rendering.
++SbBool
++So at Gui@ViewerP::drawAsHiddenLine(void) const
++{
++  return ((this->currentDrawStyle() == So at Gui@Viewer::VIEW_HIDDEN_LINE) ? TRUE : FALSE);
++}
++
++// Returns a boolean to indicate if the current drawstyle settings
++// implies wirefram overlay rendering.
++SbBool
++So at Gui@ViewerP::drawAsWireframeOverlay(void) const
++{
++  return ((this->currentDrawStyle() == So at Gui@Viewer::VIEW_WIREFRAME_OVERLAY) ? TRUE : FALSE);
++}
++
++// Use the given style setting to set the correct states in the
++// rendering control nodes. This will affect the way the scene is
++// currently rendered.
++void
++So at Gui@ViewerP::changeDrawStyle(So at Gui@Viewer::DrawStyle style)
++{
++  // Turn on/off Z-buffering based on the style setting.
++  switch (style) {
++  case So at Gui@Viewer::VIEW_LOW_RES_LINE:
++  case So at Gui@Viewer::VIEW_LOW_RES_POINT:
++  case So at Gui@Viewer::VIEW_BBOX:
++    PUBLIC(this)->glLockNormal();
++    // FIXME: shouldn't this be done "lazy", i.e. before we do any
++    // actual rendering? 20001126 mortene.
++    glDisable(GL_DEPTH_TEST);
++    PUBLIC(this)->glUnlockNormal();
++    break;
++
++  default:
++    PUBLIC(this)->glLockNormal();
++    // FIXME: shouldn't this be done "lazy", i.e. before we do any
++    // actual rendering? 20001126 mortene.
++    glEnable(GL_DEPTH_TEST);
++    PUBLIC(this)->glUnlockNormal();
++    break;
++  }
++
++  // Render everything as its supposed to be done, don't override
++  // any of the settings in the ``real'' graph.
++  if (style == So at Gui@Viewer::VIEW_AS_IS) {
++    this->drawstyleroot->whichChild = SO_SWITCH_NONE;
++    return;
++  }
++
++  this->drawstyleroot->whichChild = SO_SWITCH_ALL;
++  if ((style == So at Gui@Viewer::VIEW_HIDDEN_LINE) ||
++      (style == So at Gui@Viewer::VIEW_WIREFRAME_OVERLAY)) {
++    this->hiddenlineroot->whichChild = SO_SWITCH_ALL;
++    return;
++  } else {
++    this->hiddenlineroot->whichChild = SO_SWITCH_NONE;
++  }
++
++  // Set or unset lightmodel override.
++  switch (style) {
++  case So at Gui@Viewer::VIEW_NO_TEXTURE:
++  case So at Gui@Viewer::VIEW_LOW_COMPLEXITY:
++    this->solightmodel->model.setIgnored(TRUE); // as-is BASE or PHONG
++    break;
++
++  case So at Gui@Viewer::VIEW_LINE:
++  case So at Gui@Viewer::VIEW_POINT:
++  case So at Gui@Viewer::VIEW_BBOX:
++  case So at Gui@Viewer::VIEW_LOW_RES_LINE:
++  case So at Gui@Viewer::VIEW_LOW_RES_POINT:
++    this->solightmodel->model.setIgnored(FALSE); // force BASE lighting
++    break;
++
++  default:
++    assert(FALSE); break;
++  }
++
++
++  // Set or unset drawstyle override.
++  switch (style) {
++  case So at Gui@Viewer::VIEW_NO_TEXTURE:
++  case So at Gui@Viewer::VIEW_LOW_COMPLEXITY:
++    this->sodrawstyle->style.setIgnored(TRUE); // as-is drawing style filled/lines/points
++    break;
++
++  case So at Gui@Viewer::VIEW_LINE:
++  case So at Gui@Viewer::VIEW_LOW_RES_LINE:
++  case So at Gui@Viewer::VIEW_BBOX:
++    this->sodrawstyle->style = SoDrawStyle::LINES;
++    this->sodrawstyle->style.setIgnored(FALSE); // force line rendering
++    break;
++
++  case So at Gui@Viewer::VIEW_POINT:
++  case So at Gui@Viewer::VIEW_LOW_RES_POINT:
++    this->sodrawstyle->style = SoDrawStyle::POINTS;
++    this->sodrawstyle->style.setIgnored(FALSE); // force point rendering
++    break;
++
++  default:
++    assert(FALSE); break;
++  }
++
++  // Set or unset complexity value override.
++  switch (style) {
++  case So at Gui@Viewer::VIEW_NO_TEXTURE:
++  case So at Gui@Viewer::VIEW_LINE:
++  case So at Gui@Viewer::VIEW_POINT:
++  case So at Gui@Viewer::VIEW_BBOX:
++    this->socomplexity->value.setIgnored(TRUE); // as-is complexity
++    break;
++
++  case So at Gui@Viewer::VIEW_LOW_COMPLEXITY:
++  case So at Gui@Viewer::VIEW_LOW_RES_LINE:
++  case So at Gui@Viewer::VIEW_LOW_RES_POINT:
++    this->socomplexity->value.setIgnored(FALSE); // force complexity setting of 0.1
++    break;
++
++  default:
++    assert(FALSE); break;
++  }
++
++  // Set or unset complexity textureQuality override (the value of the
++  // override-field is always 0.0, ie signalling "textures off").
++  switch (style) {
++  case So at Gui@Viewer::VIEW_HIDDEN_LINE:
++  case So at Gui@Viewer::VIEW_NO_TEXTURE:
++  case So at Gui@Viewer::VIEW_LINE:
++  case So at Gui@Viewer::VIEW_POINT:
++  case So at Gui@Viewer::VIEW_BBOX:
++  case So at Gui@Viewer::VIEW_LOW_RES_LINE:
++  case So at Gui@Viewer::VIEW_LOW_RES_POINT:
++    this->socomplexity->textureQuality.setIgnored(FALSE); // textures off
++    break;
++
++  default:
++    this->socomplexity->textureQuality.setIgnored(TRUE); // don't override
++    break;
++  }
++
++  // Set or unset complexity type override.
++  switch (style) {
++  case So at Gui@Viewer::VIEW_NO_TEXTURE:
++  case So at Gui@Viewer::VIEW_LOW_COMPLEXITY:
++  case So at Gui@Viewer::VIEW_LINE:
++  case So at Gui@Viewer::VIEW_POINT:
++  case So at Gui@Viewer::VIEW_LOW_RES_LINE:
++  case So at Gui@Viewer::VIEW_LOW_RES_POINT:
++    this->socomplexity->type.setIgnored(TRUE); // as-is
++    break;
++
++  case So at Gui@Viewer::VIEW_BBOX:
++    this->socomplexity->type = SoComplexity::BOUNDING_BOX;
++    this->socomplexity->type.setIgnored(FALSE); // force bounding box rendering
++    break;
++
++  default:
++    assert(FALSE); break;
++  }
++
++#if 0 // debug
++  SoDebugError::postInfo("So at Gui@Viewer::changeDrawStyle",
++                         "\n"
++                         "\tdrawstyle style: 0x%02x (isIgnored() == %s)\n"
++                         "\tlightmodel model: 0x%02x, (isIgnored() == %s)\n"
++                         "\tcomplexity type: 0x%02x, (isIgnored() == %s)\n"
++                         "\tcomplexity value: %f, (isIgnored() == %s)\n"
++                         "",
++                         this->sodrawstyle->style.getValue(),
++                         this->sodrawstyle->style.isIgnored() ? "T" : "F",
++                         this->solightmodel->model.getValue(),
++                         this->solightmodel->model.isIgnored() ? "T" : "F",
++                         this->socomplexity->type.getValue(),
++                         this->socomplexity->type.isIgnored() ? "T" : "F",
++                         this->socomplexity->value.getValue(),
++                         this->socomplexity->value.isIgnored() ? "T" : "F");
++#endif // debug
++}
++
++// Position the near and far clipping planes just in front of and
++// behind the scene's bounding box. This will give us the optimal
++// utilization of the z buffer resolution by shrinking it to its
++// minimum depth.
++//
++// Near and far clipping planes are specified in the camera fields
++// nearDistance and farDistance.
++void
++So at Gui@ViewerP::setClippingPlanes(void)
++{
++  // This is necessary to avoid a crash in case there is no scene
++  // graph specified by the user.
++  if (this->camera == NULL) return;
++
++  if (this->autoclipbboxaction == NULL)
++    this->autoclipbboxaction =
++      new SoGetBoundingBoxAction(PUBLIC(this)->getViewportRegion());
++  else
++    this->autoclipbboxaction->setViewportRegion(PUBLIC(this)->getViewportRegion());
++
++  this->autoclipbboxaction->apply(this->sceneroot);
++
++  SbXfBox3f xbox = this->autoclipbboxaction->getXfBoundingBox();
++
++  SbMatrix cammat;
++  SbMatrix inverse;
++  this->getCameraCoordinateSystem(this->camera, this->sceneroot, cammat, inverse);
++  xbox.transform(inverse);
++
++  SbMatrix mat;
++  mat.setTranslate(- this->camera->position.getValue());
++  xbox.transform(mat);
++  mat = this->camera->orientation.getValue().inverse();
++  xbox.transform(mat);
++  SbBox3f box = xbox.project();
++
++  // Bounding box was calculated in camera space, so we need to "flip"
++  // the box (because camera is pointing in the (0,0,-1) direction
++  // from origo.
++  float nearval = -box.getMax()[2];
++  float farval = -box.getMin()[2];
++
++  // FIXME: what if we have a weird scale transform in the scenegraph?
++  // Could we end up with nearval > farval then? Investigate, then
++  // either use an assert() (if it can't happen) or an So at Gui@Swap()
++  // (to handle it). 20020116 mortene.
++
++  // Check if scene is completely behind us.
++  // Do NOT check for orthographic cameras.
++  if (farval <= 0.0f && !this->camera->isOfType(SoOrthographicCamera::getClassTypeId())) { return; }
++
++  if (this->camera->isOfType(SoPerspectiveCamera::getClassTypeId())) {
++    // Disallow negative and small near clipping plane distance.
++    
++    float nearlimit; // the smallest value allowed for nearval
++    if (this->autoclipstrategy == So at Gui@Viewer::CONSTANT_NEAR_PLANE) {
++      nearlimit = this->autoclipvalue;
++    }
++    else {
++      assert(this->autoclipstrategy == So at Gui@Viewer::VARIABLE_NEAR_PLANE);
++      // From glFrustum() documentation: Depth-buffer precision is
++      // affected by the values specified for znear and zfar. The
++      // greater the ratio of zfar to znear is, the less effective the
++      // depth buffer will be at distinguishing between surfaces that
++      // are near each other. If r = far/near, roughly log (2) r bits
++      // of depth buffer precision are lost. Because r approaches
++      // infinity as znear approaches zero, you should never set znear
++      // to zero.
++
++      GLint depthbits[1];
++      glGetIntegerv(GL_DEPTH_BITS, depthbits);
++      
++      int use_bits = (int) (float(depthbits[0]) * (1.0f-this->autoclipvalue)); 
++      float r = (float) pow(2.0, (double) use_bits);
++      nearlimit = farval / r;
++    }
++    
++    if (nearlimit >= farval) {
++      // (The "5000" magic constant was found by fiddling around a bit
++      // on an OpenGL implementation with a 16-bit depth-buffer
++      // resolution, adjusting to find something that would work well
++      // with both a very "stretched" / deep scene and a more compact
++      // single-model one.)
++      nearlimit = farval / 5000.0f;
++    }
++    
++    // adjust the near plane if the the value is too small.
++    if (nearval < nearlimit) { nearval = nearlimit; }
++  }
++
++  // Some slack around the bounding box, in case the scene fits
++  // exactly inside it. This is done to minimize the chance of
++  // artifacts caused by the limitation of the z-buffer
++  // resolution. One common artifact if this is not done is that the
++  // near clipping plane cuts into the corners of the model as it's
++  // rotated.
++  const float SLACK = 0.001f;
++
++  // FrustumCamera can be found in the SmallChange CVS module. We
++  // should not change the nearDistance for this camera, as this will
++  // modify the frustum.
++  //
++  // FIXME: quite the hack that So at Gui@ needs to know about the
++  // FrustumCamera class. Wouldn't it be better if FrustumCamera
++  // instead registered a callback with setAutoClippingStrategy() and
++  // handled this itself?  20040908 mortene.
++  if (this->camera->getTypeId().getName() == "FrustumCamera") {
++    nearval = this->camera->nearDistance.getValue();
++    farval *= (1.0f + SLACK); 
++    if (farval <= nearval) {
++      // nothing is visible, so just set farval to som value > nearval.
++      farval = nearval + 10.0f;
++    }
++  }
++  else {
++    // For orthographic cameras also negative values nearval/farval
++    // are reasonable.
++    nearval *= (1.0f - (nearval>0?1:-1)*SLACK);
++    farval *= (1.0f + (farval>0?1:-1)*SLACK);
++  }
++
++  if (this->autoclipcb) {
++    SbVec2f nearfar(nearval, farval);
++    nearfar = this->autoclipcb(this->autoclipuserdata, nearfar);
++
++    nearval = nearfar[0];
++    farval = nearfar[1]; 
++  }
++
++  if (nearval != this->camera->nearDistance.getValue()) {
++    this->camera->nearDistance = nearval;
++  }
++  if (farval != this->camera->farDistance.getValue()) {
++    this->camera->farDistance = farval;
++  }
++
++  // FIXME: there's a possible optimization to take advantage of here,
++  // since we are able to sometimes know for sure that all geometry is
++  // completely inside the view volume. I quote from the "OpenGL FAQ
++  // and Troubleshooting Guide":
++  //
++  //  "10.050 I know my geometry is inside the view volume. How can I
++  //  turn off OpenGL's view-volume clipping to maximize performance?
++  //
++  //   Standard OpenGL doesn't provide a mechanism to disable the
++  //   view-volume clipping test; thus, it will occur for every
++  //   primitive you send.
++  //
++  //   Some implementations of OpenGL support the
++  //   GL_EXT_clip_volume_hint extension. If the extension is
++  //   available, a call to
++  //   glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT,GL_FASTEST) will inform
++  //   OpenGL that the geometry is entirely within the view volume and
++  //   that view-volume clipping is unnecessary. Normal clipping can
++  //   be resumed by setting this hint to GL_DONT_CARE. When clipping
++  //   is disabled with this hint, results are undefined if geometry
++  //   actually falls outside the view volume."
++  //
++  // 20020117 mortene.
++
++
++  // Debug assistance, can be turned on without recompilation (just
++  // set the environment variable SO at GUI@_DEBUG_CLIPPLANES):
++
++#if SO at GUI@_DEBUG
++  static int debugoutputnearfar = -1;
++  if (debugoutputnearfar == -1) {
++    const char * env = SoAny::si()->getenv("SO at GUI@_DEBUG_CLIPPLANES");
++    debugoutputnearfar = (env && atoi(env) > 0) ? 1 : 0;
++  }
++
++  if (debugoutputnearfar == 1) { // debug
++    SoDebugError::postInfo("So at Gui@Viewer::setClippingPlanes",
++                           "near, far: %f (%f), %f (%f)",
++                           nearval, this->camera->nearDistance.getValue(),
++                           farval, this->camera->farDistance.getValue());
++  }
++#endif // debug
++}
++
++// Translate camera a distance equal to the difference in projected,
++// normalized screen coordinates given by the argument.
++void
++So at Gui@ViewerP::moveCameraScreen(const SbVec2f & screenpos)
++{
++  SoCamera * cam = PUBLIC(this)->getCamera();
++  assert(cam);
++
++  if (SO at GUI@_DEBUG && 0) { // debug
++    SoDebugError::postInfo("So at Gui@Viewer::moveCameraScreen",
++                           "screenpos: <%f, %f>, campos: <%f, %f, %f>",
++                           screenpos[0], screenpos[1],
++                           cam->position.getValue()[0],
++                           cam->position.getValue()[1],
++                           cam->position.getValue()[2]);
++  }
++
++  SbViewVolume vv = cam->getViewVolume(PUBLIC(this)->getGLAspectRatio());
++  SbPlane panplane = vv.getPlane(cam->focalDistance.getValue());
++
++  SbLine line;
++  vv.projectPointToLine(screenpos + SbVec2f(0.5, 0.5f), line);
++  SbVec3f current_planept;
++  panplane.intersect(line, current_planept);
++  vv.projectPointToLine(SbVec2f(0.5f, 0.5f), line);
++  SbVec3f old_planept;
++  panplane.intersect(line, old_planept);
++
++  // Reposition camera according to the vector difference between the
++  // projected points.
++  cam->position = cam->position.getValue() - (current_planept - old_planept);
++
++  if (SO at GUI@_DEBUG && 0) { // debug
++    SoDebugError::postInfo("So at Gui@Viewer::moveCameraScreen",
++                           "newcampos: <%f, %f, %f>",
++                           cam->position.getValue()[0],
++                           cam->position.getValue()[1],
++                           cam->position.getValue()[2]);
++  }
++}
++
++// Called when viewer enters interactive mode (animation, drag, ...).
++void
++So at Gui@ViewerP::interactivestartCB(void *, So at Gui@Viewer * thisp)
++{
++  // In interactive buffer mode, doublebuffering is used during interaction.
++  if (PRIVATE(thisp)->buffertype == So at Gui@Viewer::BUFFER_INTERACTIVE) {
++    PRIVATE(thisp)->localsetbuffertype = TRUE;
++    thisp->So at Gui@RenderArea::setDoubleBuffer(TRUE);
++    PRIVATE(thisp)->localsetbuffertype = FALSE;
++  }
++
++  // Use the dynamic drawstyle.
++  if (!PRIVATE(thisp)->drawInteractiveAsStill())
++    PRIVATE(thisp)->changeDrawStyle(PRIVATE(thisp)->drawstyles[So at Gui@Viewer::INTERACTIVE]);
++}
++
++// Called when viewer goes out of interactive mode and into "frozen"
++// mode.
++void
++So at Gui@ViewerP::interactiveendCB(void *, So at Gui@Viewer * thisp)
++{
++  // In interactive buffer mode, doublebuffering is used during
++  // interaction, singelbuffering while the camera is static.
++  if (PRIVATE(thisp)->buffertype == So at Gui@Viewer::BUFFER_INTERACTIVE) {
++    PRIVATE(thisp)->localsetbuffertype = TRUE;
++    thisp->So at Gui@RenderArea::setDoubleBuffer(FALSE);
++    PRIVATE(thisp)->localsetbuffertype = FALSE;
++  }
++
++  // Back to static drawstyle.
++  if (!PRIVATE(thisp)->drawInteractiveAsStill())
++    PRIVATE(thisp)->changeDrawStyle(PRIVATE(thisp)->drawstyles[So at Gui@Viewer::STILL]);
++}
++
++// Called repeatedly during the seek animation.
++void
++So at Gui@ViewerP::seeksensorCB(void * data, SoSensor * s)
++{
++  SbTime currenttime = SbTime::getTimeOfDay();
++
++  So at Gui@Viewer * thisp = (So at Gui@Viewer *)data;
++  SoTimerSensor * sensor = (SoTimerSensor *)s;
++
++  float t =
++    float((currenttime - sensor->getBaseTime()).getValue()) / PRIVATE(thisp)->seekperiod;
++  if ((t > 1.0f) || (t + sensor->getInterval().getValue() > 1.0f)) t = 1.0f;
++  SbBool end = (t == 1.0f);
++  
++  t = (float) ((1.0 - cos(M_PI*t)) * 0.5);
++  
++  PRIVATE(thisp)->camera->position = PRIVATE(thisp)->camerastartposition +
++    (PRIVATE(thisp)->cameraendposition - PRIVATE(thisp)->camerastartposition) * t;
++  PRIVATE(thisp)->camera->orientation = 
++    SbRotation::slerp(PRIVATE(thisp)->camerastartorient,
++                      PRIVATE(thisp)->cameraendorient, 
++                      t);
++
++  if (end) thisp->setSeekMode(FALSE);
++}
++
++// Reset the frames-per-second counter upon window resize events,
++// abnormal delays, etc.
++//
++// The methods for recording FPS values are Coin extensions, not
++// available in the original Open Inventor API.
++//
++// \sa addFrametime(), recordFPS()
++void
++So at Gui@ViewerP::resetFrameCounter(void)
++{
++  this->framecount = 0;
++  for (int i = 0; i < So at Gui@ViewerP::FRAMESARRAY_SIZE; i++)
++    this->frames[i] = SbVec2f(0.0f, 0.0f);
++  this->totalcoin = 0.0f;
++  this->totaldraw = 0.0f;
++  this->lastgettimeofday = SbTime::getTimeOfDay().getValue();
++}
++
++// Adds the time spent drawing the last frame to the array of past
++// frame times. Returns the current averaged fps-value.
++//
++// The methods for recording FPS values are Coin extensions, not
++// available in the original Open Inventor API.
++//
++// \sa resetFrameCounter(), recordFPS()
++SbVec2f
++So at Gui@ViewerP::addFrametime(const double ft)
++{
++  this->framecount++;
++
++  int arrayptr = (this->framecount - 1) % FRAMESARRAY_SIZE;
++
++  this->totalcoin += (float(ft) - this->frames[arrayptr][0]);
++  float coinfps =
++    this->totalcoin / So at Gui@Min(this->framecount, (int) FRAMESARRAY_SIZE);
++
++  double timeofday = SbTime::getTimeOfDay().getValue();
++  double ct = timeofday - this->lastgettimeofday;
++  this->totaldraw += (float(ct) - this->frames[arrayptr][1]);
++  float drawfps =
++    this->totaldraw / So at Gui@Min(this->framecount, (int) FRAMESARRAY_SIZE);
++
++  this->frames[arrayptr] = SbVec2f((float)ft, (float)ct);
++  this->lastgettimeofday = timeofday;
++
++  return SbVec2f(1.0f / coinfps, 1.0f / drawfps);
++}
++
++static unsigned char fps2dfont[][12] = {
++  {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 }, //
++  {  0,  0, 12, 12,  0,  8, 12, 12, 12, 12, 12,  0 }, // !
++  {  0,  0,  0,  0,  0,  0,  0,  0,  0, 20, 20, 20 }, // \"
++  {  0,  0, 18, 18, 18, 63, 18, 18, 63, 18, 18,  0 }, // #
++  {  0,  8, 28, 42, 10, 10, 12, 24, 40, 42, 28,  8 }, // $
++  {  0,  0,  6, 73, 41, 22,  8, 52, 74, 73, 48,  0 }, // %
++  {  0, 12, 18, 18, 12, 25, 37, 34, 34, 29,  0,  0 }, // &
++  { 12, 12, 24,  0,  0,  0,  0,  0,  0,  0,  0,  0 }, // '
++  {  0,  6,  8,  8, 16, 16, 16, 16, 16,  8,  8,  6 }, // (
++  {  0, 48,  8,  8,  4,  4,  4,  4,  4,  8,  8, 48 }, //)
++  {  0,  0,  0,  0,  0,  0,  8, 42, 20, 42,  8,  0 }, // *
++  {  0,  0,  0,  8,  8,  8,127,  8,  8,  8,  0,  0 }, // +
++  {  0, 24, 12, 12,  0,  0,  0,  0,  0,  0,  0,  0 }, // ,
++  {  0,  0,  0,  0,  0,  0,127,  0,  0,  0,  0,  0 }, // -
++  {  0,  0, 24, 24,  0,  0,  0,  0,  0,  0,  0,  0 }, // .
++  {  0, 32, 32, 16, 16,  8,  8,  8,  4,  4,  2,  2 }, // /
++  {  0,  0, 28, 34, 34, 34, 34, 34, 34, 34, 28,  0 }, // 0
++  {  0,  0,  8,  8,  8,  8,  8,  8, 40, 24,  8,  0 }, // 1
++  {  0,  0, 62, 32, 16,  8,  4,  2,  2, 34, 28,  0 }, // 2
++  {  0,  0, 28, 34,  2,  2, 12,  2,  2, 34, 28,  0 }, // 3
++  {  0,  0,  4,  4,  4,126, 68, 36, 20, 12,  4,  0 }, // 4
++  {  0,  0, 28, 34,  2,  2,  2, 60, 32, 32, 62,  0 }, // 5
++  {  0,  0, 28, 34, 34, 34, 60, 32, 32, 34, 28,  0 }, // 6
++  {  0,  0, 16, 16, 16,  8,  8,  4,  2,  2, 62,  0 }, // 7
++  {  0,  0, 28, 34, 34, 34, 28, 34, 34, 34, 28,  0 }, // 8
++  {  0,  0, 28, 34,  2,  2, 30, 34, 34, 34, 28,  0 }, // 9
++  {  0,  0, 24, 24,  0,  0,  0, 24, 24,  0,  0,  0 }, // :
++  {  0, 48, 24, 24,  0,  0,  0, 24, 24,  0,  0,  0 }, // ;
++  {  0,  0,  0,  2,  4,  8, 16,  8,  4,  2,  0,  0 }, // <
++  {  0,  0,  0,  0,  0,127,  0,127,  0,  0,  0,  0 }, // =
++  {  0,  0,  0, 16,  8,  4,  2,  4,  8, 16,  0,  0 }, // >
++  {  0,  0, 16, 16,  0, 16, 28,  2,  2,  2, 60,  0 }, // ?
++  {  0,  0, 28, 32, 73, 86, 82, 82, 78, 34, 28,  0 }, // @
++  {  0,  0, 33, 33, 33, 63, 18, 18, 18, 12, 12,  0 }, // A
++  {  0,  0, 60, 34, 34, 34, 60, 34, 34, 34, 60,  0 }, // B
++  {  0,  0, 14, 16, 32, 32, 32, 32, 32, 18, 14,  0 }, // C
++  {  0,  0, 56, 36, 34, 34, 34, 34, 34, 36, 56,  0 }, // D
++  {  0,  0, 62, 32, 32, 32, 60, 32, 32, 32, 62,  0 }, // E
++  {  0,  0, 16, 16, 16, 16, 30, 16, 16, 16, 30,  0 }, // F
++  {  0,  0, 14, 18, 34, 34, 32, 32, 32, 18, 14,  0 }, // G
++  {  0,  0, 34, 34, 34, 34, 62, 34, 34, 34, 34,  0 }, // H
++  {  0,  0, 62,  8,  8,  8,  8,  8,  8,  8, 62,  0 }, // I
++  {  0,  0,112,  8,  8,  8,  8,  8,  8,  8, 62,  0 }, // J
++  {  0,  0, 33, 33, 34, 36, 56, 40, 36, 34, 33,  0 }, // K
++  {  0,  0, 30, 16, 16, 16, 16, 16, 16, 16, 16,  0 }, // L
++  {  0,  0, 33, 33, 33, 45, 45, 45, 51, 51, 33,  0 }, // M
++  {  0,  0, 34, 34, 38, 38, 42, 42, 50, 50, 34,  0 }, // N
++  {  0,  0, 12, 18, 33, 33, 33, 33, 33, 18, 12,  0 }, // O
++  {  0,  0, 32, 32, 32, 60, 34, 34, 34, 34, 60,  0 }, // P
++  {  3,  6, 12, 18, 33, 33, 33, 33, 33, 18, 12,  0 }, // Q
++  {  0,  0, 34, 34, 34, 36, 60, 34, 34, 34, 60,  0 }, // R
++  {  0,  0, 60,  2,  2,  6, 28, 48, 32, 32, 30,  0 }, // S
++  {  0,  0,  8,  8,  8,  8,  8,  8,  8,  8,127,  0 }, // T
++  {  0,  0, 28, 34, 34, 34, 34, 34, 34, 34, 34,  0 }, // U
++  {  0,  0, 12, 12, 18, 18, 18, 33, 33, 33, 33,  0 }, // V
++  {  0,  0, 34, 34, 34, 54, 85, 73, 73, 73, 65,  0 }, // W
++  {  0,  0, 34, 34, 20, 20,  8, 20, 20, 34, 34,  0 }, // X
++  {  0,  0,  8,  8,  8,  8, 20, 20, 34, 34, 34,  0 }, // Y
++  {  0,  0, 62, 32, 16, 16,  8,  4,  4,  2, 62,  0 }, // Z
++  {  0, 14,  8,  8,  8,  8,  8,  8,  8,  8,  8, 14 }, // [
++  {  0,  2,  2,  4,  4,  8,  8,  8, 16, 16, 32, 32 }, // [backslash]
++  {  0, 56,  8,  8,  8,  8,  8,  8,  8,  8,  8, 56 }, // ]
++  {  0,  0,  0,  0,  0, 34, 34, 20, 20,  8,  8,  0 }, // ^
++  {  0,127,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 }, // _
++  {  0,  0,  0,  0,  0,  0,  0,  0,  0, 24, 24, 12 }, // `
++  {  0,  0, 29, 34, 34, 30,  2, 34, 28,  0,  0,  0 }, // a
++  {  0,  0, 60, 34, 34, 34, 34, 50, 44, 32, 32, 32 }, // b
++  {  0,  0, 14, 16, 32, 32, 32, 16, 14,  0,  0,  0 }, // c
++  {  0,  0, 26, 38, 34, 34, 34, 34, 30,  2,  2,  2 }, // d
++  {  0,  0, 28, 34, 32, 62, 34, 34, 28,  0,  0,  0 }, // e
++  {  0,  0, 16, 16, 16, 16, 16, 16, 62, 16, 16, 14 }, // f
++  { 28,  2,  2, 26, 38, 34, 34, 34, 30,  0,  0,  0 }, // g
++  {  0,  0, 34, 34, 34, 34, 34, 50, 44, 32, 32, 32 }, // h
++  {  0,  0,  8,  8,  8,  8,  8,  8, 56,  0,  8,  8 }, // i
++  { 56,  4,  4,  4,  4,  4,  4,  4, 60,  0,  4,  4 }, // j
++  {  0,  0, 33, 34, 36, 56, 40, 36, 34, 32, 32, 32 }, // k
++  {  0,  0,  8,  8,  8,  8,  8,  8,  8,  8,  8, 56 }, // l
++  {  0,  0, 73, 73, 73, 73, 73,109, 82,  0,  0,  0 }, // m
++  {  0,  0, 34, 34, 34, 34, 34, 50, 44,  0,  0,  0 }, // n
++  {  0,  0, 28, 34, 34, 34, 34, 34, 28,  0,  0,  0 }, // o
++  { 32, 32, 60, 34, 34, 34, 34, 50, 44,  0,  0,  0 }, // p
++  {  2,  2, 26, 38, 34, 34, 34, 34, 30,  0,  0,  0 }, // q
++  {  0,  0, 16, 16, 16, 16, 16, 24, 22,  0,  0,  0 }, // r
++  {  0,  0, 60,  2,  2, 28, 32, 32, 30,  0,  0,  0 }, // s
++  {  0,  0, 14, 16, 16, 16, 16, 16, 62, 16, 16,  0 }, // t
++  {  0,  0, 26, 38, 34, 34, 34, 34, 34,  0,  0,  0 }, // u
++  {  0,  0,  8,  8, 20, 20, 34, 34, 34,  0,  0,  0 }, // v
++  {  0,  0, 34, 34, 34, 85, 73, 73, 65,  0,  0,  0 }, // w
++  {  0,  0, 34, 34, 20,  8, 20, 34, 34,  0,  0,  0 }, // x
++  { 48, 16,  8,  8, 20, 20, 34, 34, 34,  0,  0,  0 }, // y
++  {  0,  0, 62, 32, 16,  8,  4,  2, 62,  0,  0,  0 }, // z
++  {  0,  6,  8,  8,  8,  4, 24,  4,  8,  8,  8,  6 }, // {
++  {  0,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8 }, // |
++  {  0, 48,  8,  8,  8, 16, 12, 16,  8,  8,  8, 48 }, // }
++  {  0,  0,  0,  0,  0,  0, 78, 57,  0,  0,  0,  0 }  // ~
++};
++
++static void
++printString(const char * s)
++{
++  int i,n;
++  n = strlen(s);
++  for (i = 0; i < n; i++)
++    glBitmap(8, 12, 0.0, 2.0, 10.0, 0.0, fps2dfont[s[i] - 32]);
++}
++
++static void
++Draw2DString(const char * str, SbVec2s glsize, SbVec2f position)
++{
++  // Store GL state.
++  glPushAttrib(GL_ENABLE_BIT|GL_CURRENT_BIT);
++
++  glDisable(GL_LIGHTING);
++  glDisable(GL_DEPTH_TEST);
++  glDisable(GL_TEXTURE_2D);
++  glDisable(GL_BLEND);
++
++  glMatrixMode(GL_MODELVIEW);
++  glPushMatrix();
++  glLoadIdentity();
++
++  glMatrixMode(GL_PROJECTION);
++  glPushMatrix();
++  glLoadIdentity();
++  glOrtho(0.0, glsize[0], 0.0, glsize[1], -1, 1);
++
++  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
++
++  glColor3f(0.0, 0.0, 0.0);
++  glRasterPos2f(position[0] + 1, position[1]);
++  printString(str);
++  glRasterPos2f(position[0] - 1, position[1]);
++  printString(str);
++  glRasterPos2f(position[0], position[1] + 1);
++  printString(str);
++  glRasterPos2f(position[0], position[1] - 1);
++  printString(str);
++
++  glColor3f(1.0, 1.0, 0.0);
++  glRasterPos2f(position[0], position[1]);
++  printString(str);
++
++  glMatrixMode(GL_PROJECTION);
++  glPopMatrix();
++  glMatrixMode(GL_MODELVIEW);
++  glPopMatrix();
++
++  glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // restore default value
++
++  glPopAttrib();
++}
++
++
++// FIXME: the following is just a temporary hack to enable the FPS
++// counter. We should really write a proper interface against it, so
++// applications can set up feedback loops to control scene complexity
++// and get a nice and steady maximum framerate, for instance.
++//
++// For anyone who want to execute that task, check what TGS has done
++// first. If their API is fine, use the same approach.
++//
++// 20001124 mortene.
++
++// Draw a text string showing the current frame-per-seconds value in
++// the lower left corner of the OpenGL canvas (after recording
++// information needed to calculate the fps).
++//
++// The methods for recording FPS values are Coin extensions, not
++// available in the original Open Inventor API.
++//
++// The two displayed values can be explained as follows:
++//
++// The first number is the time it takes for the SoGLRenderAction to
++// traverse the scene graph (displayed as Hz / FPS). The second is the
++// interval between each time SoGLRenderAction::apply() is invoked
++// (i.e. the "actual" rendering rate, as experienced by the user).
++//
++// The first number is mainly useful just for internal debugging
++// purposes.
++//
++// The second number will always be <= to the first, because it will
++// also include the time stalling on glFlush() upon releasing the
++// OpenGL context after traversal (glFlush() stalls until the GPU
++// completes all OpenGL commands), and any application-code processing
++// inbetween rendering.
++//
++// There is by the way a useful "trick" to improve application
++// performance implied in that last paragraph above: if
++// application-code processing is interleaved between the completion
++// of the SoGLRenderAction traversal and the release of the OpenGL
++// context, application-code is likely to run on the CPU in parallel
++// with GPU processing OpenGL commands.
++//
++// FIXME: the above optimization trick should be documented in the
++// visible API docs somewhere, with code to show how to do it. The
++// example code would probably involve making an application-specific
++// viewer, and overriding actualRedraw()? Or can it be done by using a
++// callback mechanism somewhere? Ask pederb. 20031009 mortene.
++//
++// \sa resetFrameCounter(), addFrametime()
++void
++So at Gui@ViewerP::recordFPS(const double rendertime)
++{
++  const char * env = SoAny::si()->getenv("COIN_SHOW_FPS_COUNTER");
++  if ( !env ) {
++    COIN_SHOW_FPS_COUNTER = UNINITIALIZED_ENVVAR;
++  } else {
++    COIN_SHOW_FPS_COUNTER = atoi(env);
++  }
++
++#if 0
++  // disabled to make fps-couter dynamically adjustable
++  if (COIN_SHOW_FPS_COUNTER == UNINITIALIZED_ENVVAR) {
++    const char * env = SoAny::si()->getenv("COIN_SHOW_FPS_COUNTER");
++    COIN_SHOW_FPS_COUNTER = env ? atoi(env) : 0;
++  }
++#endif
++
++  if (COIN_SHOW_FPS_COUNTER > 0) {
++    SbVec2f fps = this->addFrametime(rendertime);
++
++    char buffer[64];
++    int nr = sprintf(buffer, "%.1f/%.1f fps", fps[0], fps[1]);
++    assert(nr < 64);
++    Draw2DString(buffer, PUBLIC(this)->getGLSize(), SbVec2f(10, 10));
++  }
++}
++
++// *************************************************************************
++
++SO at GUI@_OBJECT_ABSTRACT_SOURCE(So at Gui@Viewer);
++
++// *************************************************************************
++
++/*!
++  \enum So at Gui@Viewer::Type
++
++  Hints about what context the viewer will be used in.  Usually not
++  very interesting for the application programmer, it doesn't matter
++  much which value is used for the viewer type.  This "feature" of the
++  viewer is included just to be compatible with the old SGI Inventor
++  API.
++*/
++/*!
++  \var So at Gui@Viewer::Type So at Gui@Viewer::BROWSER
++
++  If a user-supplied scenegraph passed into the setSceneGraph()
++  function does not contain a camera, setting the viewer type to
++  BROWSER will make the viewer in that case automatically set up a
++  camera outside the scene, as part of the viewer's private and hidden
++  "supergraph".
++*/
++/*!
++  \var So at Gui@Viewer::Type So at Gui@Viewer::EDITOR
++
++  If a user-supplied scenegraph passed into the setSceneGraph()
++  function does not contain a camera, setting the viewer type to
++  EDITOR will make the viewer in that case automatically set up a
++  camera \e in the user-supplied scene.
++
++  So if you want to avoid having the So at Gui@Viewer class muck about
++  with your supplied scenegraph, set the type-flag to
++  So at Gui@Viewer::BROWSER instead, which makes an inserted camera node
++  go into the viewer's own "wrapper" scene graph instead.
++*/
++
++/*!
++  \enum So at Gui@Viewer::DrawType
++
++  Contains valid values for the first argument to the
++  So at Gui@Viewer::setDrawStyle() call. Decides the effect of the second
++  argument.
++
++  \sa So at Gui@Viewer::setDrawStyle(), So at Gui@Viewer::DrawStyle
++*/
++/*!
++  \var So at Gui@Viewer::DrawType So at Gui@Viewer::STILL
++
++  If this value is passed as the first argument of
++  So at Gui@Viewer::setDrawStyle(), the second argument decides which
++  draw style to use when the viewer camera is standing still in the
++  same position with the same orientation -- i.e. when the end user is
++  \e not interacting with the scene camera.
++*/
++/*!
++  \var So at Gui@Viewer::DrawType So at Gui@Viewer::INTERACTIVE
++
++  If this value is passed as the first argument of
++  So at Gui@Viewer::setDrawStyle(), the second argument decides which
++  draw style to use when the end user is interacting with the scene
++  camera, causing continuous animation redraws.
++*/
++
++/*!
++  \enum So at Gui@Viewer::DrawStyle
++
++  Decides drawstyle for a scene with either a still camera or an
++  animating camera.
++
++  \sa So at Gui@Viewer::setDrawStyle(), So at Gui@Viewer::DrawType
++*/
++/*!
++  \var So at Gui@Viewer::DrawStyle So at Gui@Viewer::VIEW_AS_IS
++
++  Normal rendering, draws all scene geometry in it's original style.
++*/
++/*!
++  \var So at Gui@Viewer::DrawStyle So at Gui@Viewer::VIEW_HIDDEN_LINE
++
++  Draw scene in "hidden line" mode: that is, as wireframe with no
++  "see-through".
++
++  Note that this is actually an expensive way to render, as the scene
++  must be rendered twice to achieve the effect of hiding lines behind
++  the invisible geometry.
++*/
++/*!
++  \var So at Gui@Viewer::DrawStyle So at Gui@Viewer::VIEW_WIREFRAME_OVERLAY
++
++  Render the scene as normal, but overlay a set of lines showing the
++  contours of all polygons.
++*/
++/*!
++  \var So at Gui@Viewer::DrawStyle So at Gui@Viewer::VIEW_NO_TEXTURE
++
++  Render scene without textures.
++*/
++/*!
++  \var So at Gui@Viewer::DrawStyle So at Gui@Viewer::VIEW_LOW_COMPLEXITY
++
++  Render all "complex" shape types with low complexity to improve
++  rendering performance.
++
++  "Complex shapes" in this context includes spheres, cones, cylinder,
++  NURBS surfaces, and others which are tesselated to polygons before
++  being rendered.
++*/
++/*!
++  \var So at Gui@Viewer::DrawStyle So at Gui@Viewer::VIEW_LINE
++
++  View all polygon geometry in wireframe mode.
++*/
++/*!
++  \var So at Gui@Viewer::DrawStyle So at Gui@Viewer::VIEW_POINT
++
++  Render only the vertex positions of the geometry.
++*/
++/*!
++  \var So at Gui@Viewer::DrawStyle So at Gui@Viewer::VIEW_BBOX
++
++  View the scene's bounding boxes, instead of rendering the full
++  geometry.
++
++  A very efficient way of optimizing rendering performance for scenes
++  with high primitive counts while moving the camera about is to set
++  this mode for the So at Gui@Viewer::INTERACTIVE DrawType.
++*/
++/*!
++  \var So at Gui@Viewer::DrawStyle So at Gui@Viewer::VIEW_LOW_RES_LINE
++
++  Render as wireframe and don't bother with getting them rendered
++  correctly in depth.
++*/
++/*!
++  \var So at Gui@Viewer::DrawStyle So at Gui@Viewer::VIEW_LOW_RES_POINT
++
++  Render as vertex points and don't bother with getting them rendered
++  correctly in depth.
++*/
++/*!
++  \var So at Gui@Viewer::DrawStyle So at Gui@Viewer::VIEW_SAME_AS_STILL
++
++  Always render a scene with an animating camera (ie
++  So at Gui@Viewer::INTERACTIVE DrawType) in the same manner as scene
++  with a still camera.
++*/
++
++/*!
++  \enum So at Gui@Viewer::BufferType
++  Set of valid values for So at Gui@Viewer::setBufferingType().
++*/
++/*!
++  \var So at Gui@Viewer::BufferType So at Gui@Viewer::BUFFER_SINGLE
++  Change underlying OpenGL canvas to be single-buffered.
++*/
++/*!
++  \var So at Gui@Viewer::BufferType So at Gui@Viewer::BUFFER_DOUBLE
++  Change underlying OpenGL canvas to be double-buffered.
++*/
++/*!
++  \var So at Gui@Viewer::BufferType So at Gui@Viewer::BUFFER_INTERACTIVE
++
++  Set up so animation rendering is done in a double-buffered OpenGL
++  canvas, but ordinary rendering happens directly in the front-buffer.
++
++  This mode can be useful with absurdly large scenes, as the rendering
++  will \e visibly progress, and one will avoid having the end user
++  wonder why nothing is happening while the scene is rendered to the
++  back buffer in the default So at Gui@Viewer::BUFFER_DOUBLE mode.
++*/
++
++// *************************************************************************
++
++/*
++  Return the parent node in the scene graph of the given \a node.
++  NB: this is just a quick'n'dirty thing for often executed code,
++  and doesn't cover cases where nodes have multiple parents.
++*/
++
++SoGroup *
++So at Gui@ViewerP::getParentOfNode(SoNode * root, SoNode * node) const
++{
++  assert(node && root && "called with null argument");
++
++  const SbBool oldsearch = SoBaseKit::isSearchingChildren();
++  SoBaseKit::setSearchingChildren(TRUE);
++
++  this->searchaction->reset();
++  this->searchaction->setSearchingAll(TRUE);
++  this->searchaction->setNode(node);
++  this->searchaction->apply(root);
++
++  SoPath * p = this->searchaction->getPath();
++
++  SoGroup * parent = NULL;
++  if (p) {
++    parent = (SoGroup *) ((SoFullPath *)p)->getNodeFromTail(1);
++    assert(parent && "couldn't find parent");
++  }
++
++  this->searchaction->reset();
++
++  SoBaseKit::setSearchingChildren(oldsearch);
++
++  return parent;
++}
++
++// *************************************************************************
++
++/*!
++  Constructor. \a parent, \a name and \a embed are passed on to
++  So at Gui@RenderArea, so see the documentation for our parent
++  constructor for for more information on those.
++
++  The \a t type setting hints about what context the viewer will be
++  used in.  Usually not very interesting for the application
++  programmer, but if you want to make sure the So at Gui@Viewer class
++  doesn't muck about with your supplied scenegraph, set the type-flag
++  to So at Gui@Viewer::BROWSER.  (This "feature" of the viewer is
++  included just to be compatible with the old SGI Inventor API.)
++
++  The \a build flag decides whether or not to delay building the
++  widgets / window which is going to make up the components of the
++  viewer.
++*/
++So at Gui@Viewer::So at Gui@Viewer(@WIDGET@ parent,
++                             const char * name,
++                             SbBool embed,
++                             So at Gui@Viewer::Type t,
++                             SbBool build)
++  : inherited(parent, name, embed, TRUE, TRUE, FALSE)
++{
++  PRIVATE(this) = new So at Gui@ViewerP(this);
++
++  // initialization of protected data
++  PRIVATE(this)->type = t;
++  PRIVATE(this)->viewingflag = TRUE;
++  PRIVATE(this)->altdown = FALSE;
++  PRIVATE(this)->camera = NULL;
++  PRIVATE(this)->scenegraph = NULL;
++
++  // initialization of internal data
++  PRIVATE(this)->cursoron = TRUE;
++  PRIVATE(this)->localsetbuffertype = FALSE;
++
++  PRIVATE(this)->cameratype = SoPerspectiveCamera::getClassTypeId();
++  PRIVATE(this)->buffertype = this->isDoubleBuffer() ? BUFFER_DOUBLE : BUFFER_SINGLE;
++
++  PRIVATE(this)->interactionstartCallbacks = new SoCallbackList;
++  PRIVATE(this)->interactionendCallbacks = new SoCallbackList;
++  PRIVATE(this)->interactionnesting = 0;
++
++  PRIVATE(this)->seekdistance = 50.0f;
++  PRIVATE(this)->seekdistanceabs = FALSE;
++  PRIVATE(this)->seektopoint = TRUE;
++  PRIVATE(this)->seekperiod = 2.0f;
++  PRIVATE(this)->inseekmode = FALSE;
++  PRIVATE(this)->seeksensor = new SoTimerSensor(So at Gui@ViewerP::seeksensorCB, this);
++
++  PRIVATE(this)->sceneroot = PRIVATE(this)->createSuperScene();
++  PRIVATE(this)->sceneroot->ref();
++
++  PRIVATE(this)->drawstyles[STILL] = VIEW_AS_IS;
++  PRIVATE(this)->drawstyles[INTERACTIVE] = VIEW_SAME_AS_STILL;
++
++  this->addStartCallback(So at Gui@ViewerP::interactivestartCB);
++  this->addFinishCallback(So at Gui@ViewerP::interactiveendCB);
++
++  PRIVATE(this)->adjustclipplanes = TRUE;
++  PRIVATE(this)->autoclipbboxaction = NULL;
++
++  PRIVATE(this)->stereoviewing = FALSE;
++  PRIVATE(this)->stereooffset = 0.1f;
++
++  PRIVATE(this)->wireframeoverlaycolor = SbColor(1.0f, 0.0f, 0.0f);
++
++  if (build) {
++    this->setClassName("So at Gui@Viewer");
++    @WIDGET@ widget = this->buildWidget(this->getParentWidget());
++    this->setBaseWidget(widget);
++  }
++
++  PRIVATE(this)->resetFrameCounter();
++}
++
++// *************************************************************************
++
++/*!
++  Destructor.
++*/
++
++So at Gui@Viewer::~So at Gui@Viewer()
++{
++  delete PRIVATE(this)->autoclipbboxaction;
++
++  delete PRIVATE(this)->interactionstartCallbacks;
++  delete PRIVATE(this)->interactionendCallbacks;
++
++  delete PRIVATE(this)->seeksensor;
++
++  if (PRIVATE(this)->scenegraph) this->setSceneGraph(NULL);
++  if (PRIVATE(this)->superimpositions != NULL) {
++    while ( PRIVATE(this)->superimpositions->getLength() > 0 ) {
++      SoNode * node = (SoNode *) (*PRIVATE(this)->superimpositions)[0];
++      this->removeSuperimposition(node);
++    }
++  }
++  PRIVATE(this)->sceneroot->unref();
++  delete PRIVATE(this);
++}
++
++// *************************************************************************
++
++// Note: the following function documentation block will also be used
++// for all the miscellaneous viewer subclasses, so keep it general.
++/*!
++  Set the camera we want the viewer to manipulate when interacting with
++  the viewer controls.
++
++  The camera passed in as an argument to this method \e must already
++  be part of the viewer's scenegraph.  You do \e not inject viewpoint
++  cameras to the viewer with this method.
++
++  You should rather insert a camera into the scene graph first (if
++  necessary, often one will be present already), then register it as
++  the camera used by the viewer controls with this method.
++
++  If the application code doesn't explicitly set up a camera through
++  this method, the viewer will automatically scan through the
++  scenegraph to find a camera to use. If no camera is available in the
++  scenegraph at all, it will set up it's own camera.
++
++  \sa getCamera()
++*/
++void
++So at Gui@Viewer::setCamera(SoCamera * cam)
++{
++  if (PRIVATE(this)->camera) {
++    // remove the camera from the super scene graph if we inserted a camera there
++    int idx = PRIVATE(this)->sceneroot->findChild(PRIVATE(this)->camera);
++    if (idx >= 0) {
++      PRIVATE(this)->sceneroot->removeChild(idx);
++    }
++    PRIVATE(this)->camera->unref();
++  }
++  
++  if (cam) {
++    cam->ref();
++    PRIVATE(this)->cameratype = cam->getTypeId();
++  }
++
++  PRIVATE(this)->camera = cam;
++
++  this->saveHomePosition();
++}
++
++// *************************************************************************
++
++/*!
++  Returns the camera currently used by the viewer for the user's main
++  viewpoint.
++
++  It \e is possible that this function returns \c NULL, for instance
++  if there's no scenegraph present in the viewer.  (This is mostly
++  meant as a note for developers extending the So at Gui@ library, as
++  application programmers usually controls if and when a viewer
++  contains a scenegraph, and therefore know in advance if this method
++  will return a valid camera pointer.)
++
++  \sa setCamera()
++*/
++SoCamera *
++So at Gui@Viewer::getCamera(void) const
++{
++  // This impossible to miss reminder was inserted so we don't
++  // accidentally let an So* v2 slip out the door without fixing this
++  // API design flaw. 20030903 mortene.
++#if (SO at GUI@_MAJOR_VERSION == 2)
++#error This is a reminder: when jumping to version 2 of an So* toolkit, the So at Gui@Viewer::getCamera() method should be made virtual.
++#endif // version = 2
++
++  return PRIVATE(this)->camera;
++}
++
++// *************************************************************************
++
++/*!
++  When the viewer has to make its own camera as a result of the graph
++  passed to setSceneGraph() not containing any camera nodes, this call
++  can be made in advance to decide which type the camera will be of.
++
++  Default is to use an SoPerspectiveCamera.
++
++  If this method is called when there is a scene graph and a camera
++  already set up, it will delete the old camera and set up a camera
++  with the new type if the \a t type is different from that of the
++  current camera.
++
++  \sa getCameraType()
++*/
++
++void
++So at Gui@Viewer::setCameraType(SoType t)
++{
++  if (PRIVATE(this)->camera && 
++      !PRIVATE(this)->camera->isOfType(SoPerspectiveCamera::getClassTypeId()) &&
++      !PRIVATE(this)->camera->isOfType(SoOrthographicCamera::getClassTypeId())) {
++#if SO at GUI@_DEBUG
++    SoDebugError::postWarning("So at Gui@Viewer::setCameraType",
++                              "Only SoPerspectiveCamera and SoOrthographicCamera is supported.");
++#endif // SO at GUI_DEBUG 
++    return;
++  }
++
++
++  SoType perspectivetype = SoPerspectiveCamera::getClassTypeId();
++  SoType orthotype = SoOrthographicCamera::getClassTypeId();
++  SbBool oldisperspective = PRIVATE(this)->cameratype.isDerivedFrom(perspectivetype);
++  SbBool newisperspective = t.isDerivedFrom(perspectivetype);
++
++  if ((oldisperspective && newisperspective) ||
++      (!oldisperspective && !newisperspective)) // Same old, same old..
++    return;
++
++  if (SO at GUI@_DEBUG) {
++    SbBool valid = TRUE;
++    if (t == SoType::badType()) valid = FALSE;
++    if (valid) {
++      valid = FALSE;
++      if (newisperspective) valid = TRUE;
++      if (t.isDerivedFrom(orthotype)) valid = TRUE;
++    }
++
++    if (!valid) {
++      SoDebugError::post("So at Gui@Viewer::setCameraType",
++                         "not a valid camera type: '%s'",
++                         t == SoType::badType() ?
++                         "badType" : t.getName().getString());
++      return;
++    }
++  }
++
++  SoCamera * currentcam = PRIVATE(this)->camera;
++
++  if (currentcam == NULL) {
++    // A camera has not been set up for the scene yet, so just store
++    // the type and short-cut the rest of this function.
++    PRIVATE(this)->cameratype = t;
++    return;
++  }
++
++  SoCamera * newcamera = (SoCamera *)t.createInstance();
++
++  // Transfer and convert values from one camera type to the other.
++  if (newisperspective) {
++    So at Gui@ViewerP::convertOrtho2Perspective((SoOrthographicCamera *)currentcam,
++                                             (SoPerspectiveCamera *)newcamera);
++  }
++  else {
++    So at Gui@ViewerP::convertPerspective2Ortho((SoPerspectiveCamera *)currentcam,
++                                             (SoOrthographicCamera *)newcamera);
++  }
++
++  SoGroup * cameraparent =
++    PRIVATE(this)->getParentOfNode(PRIVATE(this)->sceneroot, currentcam);
++  if (cameraparent) { cameraparent->replaceChild(currentcam, newcamera); }
++  else {
++    // camera not actually present in the scene graph, so just NULL
++    // and void.
++    newcamera->ref();
++    newcamera->unref();
++    newcamera = NULL;
++
++    // Yes, this can "legally" happen, if e.g. the camera is taken out
++    // of the scene graph by the app programmer, and no new camera was
++    // set with setCamera() -- but this is a quite odd thing to do, so
++    // we warn about this for now.
++    SoDebugError::postWarning("So at Gui@Viewer::setCameraType",
++                              "Could not find the current camera in the "
++                              "scene graph, for some odd reason.");
++  }
++
++  // The setCamera() invokation below will set the saved "home"
++  // position of the camera to the current camera position. We make
++  // no attempt to avoid this, as it would involve nasty hacks, and
++  // it shouldn't really matter.
++
++  this->setCamera(newcamera); // This will set PRIVATE(this)->cameratype.
++}
++
++// *************************************************************************
++
++/*!
++  Returns camera type which will be used when the viewer has to make its
++  own camera.
++
++  Note that this call does \e not return the current cameratype, as one
++  might expect. Use getCamera() and SoType::getTypeId() for that inquiry.
++
++  \sa setCameraType()
++*/
++
++SoType
++So at Gui@Viewer::getCameraType(void) const
++{
++  return PRIVATE(this)->cameratype;
++}
++
++// *************************************************************************
++
++/*!
++  Reposition the current camera so we can see the complete scene.
++*/
++void
++So at Gui@Viewer::viewAll(void)
++{
++  SoCamera * cam = PRIVATE(this)->camera;
++  if (cam && PRIVATE(this)->scenegraph) {
++    cam->viewAll(PRIVATE(this)->scenegraph, this->getViewportRegion());
++  }
++}
++
++// *************************************************************************
++
++/*!
++  Store the current camera settings for later retrieval with
++  resetToHomePosition().
++
++  \sa resetToHomePosition()
++*/
++void
++So at Gui@Viewer::saveHomePosition(void)
++{
++  if (! PRIVATE(this)->camera) return; // probably a scene-less viewer
++
++  // We use SoType::createInstance() to store a copy of the camera,
++  // not just assuming it's either a perspective or an orthographic
++  // camera.
++
++  SoType t = PRIVATE(this)->camera->getTypeId();
++  assert(t.isDerivedFrom(SoNode::getClassTypeId()));
++  assert(t.canCreateInstance());
++
++  if (PRIVATE(this)->storedcamera) { PRIVATE(this)->storedcamera->unref(); }
++
++  PRIVATE(this)->storedcamera = (SoNode *)t.createInstance();
++  PRIVATE(this)->storedcamera->ref();
++
++  // We copy the field data directly, instead of using
++  // SoFieldContainer::copyContents(), as that has one problematic
++  // side-effect: the new camera node used for storing the data would
++  // also get the *name* of the old camera, which would overwrite the
++  // old name->ptr entry of the global dictionary behind
++  // SoNode::getByName(). This can cause surprising and hard to find
++  // bugs for app programmers, for instance when using
++  // SoNode::getByName() to get at a camera loaded from an iv-file.
++  PRIVATE(this)->storedcamera->copyFieldValues(PRIVATE(this)->camera);
++}
++
++// *************************************************************************
++
++/*!
++  Restore the saved camera settings.
++
++  \sa saveHomePosition()
++*/
++void
++So at Gui@Viewer::resetToHomePosition(void)
++{
++  if (!PRIVATE(this)->camera) { return; } // probably a scene-less viewer
++  if (!PRIVATE(this)->storedcamera) { return; }
++  
++  SoType t = PRIVATE(this)->camera->getTypeId();
++  SoType s = PRIVATE(this)->storedcamera->getTypeId();
++
++  // most common case
++  if (t == s) {
++    // We copy the field data directly, instead of using
++    // SoFieldContainer::copyContents(), for the reason described in
++    // detail in So at Gui@Viewer::saveHomePosition().
++    PRIVATE(this)->camera->copyFieldValues(PRIVATE(this)->storedcamera);
++  }
++  // handle common case #1
++  else if (t == SoOrthographicCamera::getClassTypeId() &&
++           s == SoPerspectiveCamera::getClassTypeId()) {
++    So at Gui@ViewerP::convertPerspective2Ortho((SoPerspectiveCamera *)PRIVATE(this)->storedcamera,
++                                             (SoOrthographicCamera *)PRIVATE(this)->camera);
++  }
++  // handle common case #2
++  else if (t == SoPerspectiveCamera::getClassTypeId() &&
++           s == SoOrthographicCamera::getClassTypeId()) {
++    So at Gui@ViewerP::convertOrtho2Perspective((SoOrthographicCamera *)PRIVATE(this)->storedcamera,
++                                             (SoPerspectiveCamera *)PRIVATE(this)->camera);
++  }
++  // otherwise, cameras have changed in ways we don't understand since
++  // the last saveHomePosition() invokation, and so we're just going
++  // to ignore the reset request
++}
++
++// *************************************************************************
++
++/*!
++  Turn the camera headlight on or off.
++
++  Default is to have a headlight turned on.
++
++  \sa isHeadlight(), getHeadlight()
++*/
++
++void
++So at Gui@Viewer::setHeadlight(SbBool on)
++{
++  PRIVATE(this)->headlight->on = on;
++}
++
++// *************************************************************************
++
++/*!
++  Returns status of the viewer headlight, whether it is on or off.
++
++  \sa setHeadlight(), getHeadlight()
++*/
++
++SbBool
++So at Gui@Viewer::isHeadlight(void) const
++{
++  return PRIVATE(this)->headlight->on.getValue();
++}
++
++// *************************************************************************
++
++/*!
++  Returns the a pointer to the directional light node which is the
++  viewer headlight.
++
++  The fields of the node is available for user editing.
++
++  \sa isHeadlight(), setHeadlight()
++*/
++
++SoDirectionalLight *
++So at Gui@Viewer::getHeadlight(void) const
++{
++  return PRIVATE(this)->headlight;
++}
++
++// *************************************************************************
++
++/*!
++  Set up a drawing style. The \a type argument specifies if the given
++  \a style should be interpreted as the drawstyle during animation or
++  when the camera is static.
++
++  Default values for the drawing style is to render the scene "as is"
++  in both still mode and while the camera is moving.
++
++  See the documentation for the \a DrawType and \a DrawStyle for more
++  information.
++
++  \sa getDrawStyle()
++*/
++void
++So at Gui@Viewer::setDrawStyle(So at Gui@Viewer::DrawType type,
++                            So at Gui@Viewer::DrawStyle style)
++{
++  if (SO at GUI@_DEBUG) {
++    if ((type != STILL) && (type != INTERACTIVE)) {
++      SoDebugError::postWarning("So at Gui@Viewer::setDrawStyle",
++                                "unknown drawstyle type setting 0x%x", type);
++      return;
++    }
++  }
++
++  if (style == this->getDrawStyle(type)) {
++    if (SO at GUI@_DEBUG && 0) { // debug
++      SoDebugError::postWarning("So at Gui@Viewer::setDrawStyle",
++                                "drawstyle for type 0x%02x already 0x%02x",
++                                type, style);
++    }
++    return;
++  }
++
++  PRIVATE(this)->drawstyles[type] = style;
++  PRIVATE(this)->changeDrawStyle(PRIVATE(this)->currentDrawStyle());
++}
++
++// *************************************************************************
++
++/*!
++  Return current drawstyles for the given type (\a STILL or
++  \a INTERACTIVE).
++
++  \sa setDrawStyle()
++*/
++
++So at Gui@Viewer::DrawStyle
++So at Gui@Viewer::getDrawStyle(const So at Gui@Viewer::DrawType type) const
++{
++  if (SO at GUI@_DEBUG) {
++    if ((type != STILL) && (type != INTERACTIVE)) {
++      SoDebugError::postWarning("So at Gui@Viewer::setDrawStyle",
++                                "unknown drawstyle type setting 0x%x", type);
++      return PRIVATE(this)->drawstyles[STILL];
++    }
++  }
++
++  return PRIVATE(this)->drawstyles[type];
++}
++
++// *************************************************************************
++
++/*!
++  Set the viewer's buffer type. Available types are \c
++  So at Gui@Viewer::BUFFER_SINGLE, \c So at Gui@Viewer::BUFFER_DOUBLE and \c
++  So at Gui@Viewer::BUFFER_INTERACTIVE.
++
++  (With a buffer type of \c So at Gui@Viewer::BUFFER_INTERACTIVE, the
++  viewer will render with doublebuffering during user interaction and
++  with single buffering otherwise.)
++
++  Default is \c So at Gui@Viewer::BUFFER_DOUBLE.
++
++  \sa getBufferingType()
++*/
++
++void
++So at Gui@Viewer::setBufferingType(So at Gui@Viewer::BufferType type)
++{
++  if (type == PRIVATE(this)->buffertype) return;
++
++  if (type != BUFFER_SINGLE &&
++      type != BUFFER_DOUBLE &&
++      type != BUFFER_INTERACTIVE) {
++    if (SO at GUI@_DEBUG) {
++      SoDebugError::postWarning("So at Gui@Viewer::setBufferingType",
++                                "unknown buffer type 0x%x", type);
++    }
++    return;
++  }
++
++  PRIVATE(this)->buffertype = type;
++
++  PRIVATE(this)->localsetbuffertype = TRUE;
++  inherited::setDoubleBuffer(type == BUFFER_DOUBLE);
++  PRIVATE(this)->localsetbuffertype = FALSE;
++}
++
++// *************************************************************************
++
++/*!
++  Return the viewer's buffer type.
++
++  \sa setBufferingType()
++*/
++
++So at Gui@Viewer::BufferType
++So at Gui@Viewer::getBufferingType(void) const
++{
++  return PRIVATE(this)->buffertype;
++}
++
++// *************************************************************************
++
++// Note: this documentation for setViewing() will also be used for all
++// the miscellaneous viewer subclasses, so keep it general.
++/*!
++  Set view mode.
++
++  If the view mode is on, user events will be caught and used to
++  influence the camera position / orientation. If view mode is off,
++  all events in the viewer canvas (like for instance keypresses or
++  mouseclicks and -movements) will be passed along to the scene graph.
++
++  Default is to have the view mode active.
++
++  \sa isViewing()
++*/
++void
++So at Gui@Viewer::setViewing(SbBool enable)
++{
++  if (PRIVATE(this)->viewingflag == enable) {
++    if (SO at GUI@_DEBUG) {
++      SoDebugError::postWarning("So at Gui@Viewer::setViewing",
++                                "unnecessary called");
++    }
++    return;
++  }
++
++  PRIVATE(this)->viewingflag = enable;
++
++  // Turn off the selection indicators when we go back from picking
++  // mode into viewing mode.
++  if (PRIVATE(this)->viewingflag) {
++    SoGLRenderAction * action = this->getGLRenderAction();
++    if (action != NULL)
++      SoLocateHighlight::turnOffCurrentHighlight(action);
++  }
++}
++
++// *************************************************************************
++
++/*!
++  Return state of view mode.
++
++  \c TRUE means that the mode of the viewer is set such that user
++  interaction with the mouse is used to modify the position and
++  orientation of the camera.
++
++  \sa setViewing()
++*/
++SbBool
++So at Gui@Viewer::isViewing(void) const
++{
++  return PRIVATE(this)->viewingflag;
++}
++
++// *************************************************************************
++
++/*!
++  Set whether or not the mouse cursor representation should be visible
++  in the viewer canvas.
++
++  Default value is on.
++
++  \sa isCursorEnabled()
++*/
++
++void
++So at Gui@Viewer::setCursorEnabled(SbBool on)
++{
++  PRIVATE(this)->cursoron = on;
++}
++
++// *************************************************************************
++
++/*!
++  Returns visibility status of mouse cursor.
++
++  \sa setCursorEnabled()
++*/
++
++SbBool
++So at Gui@Viewer::isCursorEnabled(void) const
++{
++  return PRIVATE(this)->cursoron;
++}
++
++// *************************************************************************
++
++/*!
++  Turn on or off continuous automatic adjustments of the near and far
++  clipping planes.
++
++  If on, the distance from the camera position to the near and far
++  planes will be calculated to be a "best fit" around the geometry in
++  the scene, to maximize the "stretch" of values for the visible
++  geometry in the z-buffer. This is important, as z-buffer resolution
++  is usually limited enough that one will quickly see flickering in
++  the rasterization of close polygons upon lousy utilization of the
++  z-buffer.
++
++  Automatic calculations of near and far clip planes are on as
++  default.
++
++  For better control over what happens in boundary conditions (for
++  instance when the distance between near and far planes get very far,
++  or if geometry gets very close to the camera position), it is
++  possible to use the So at Gui@Viewer::setAutoClippingStrategy() method
++  to fine-tune the near/far clipping plane settings.
++
++  On a major note, be aware that turning auto-updating of near and far
++  clip planes \e off have a potentially serious detrimental effect on
++  performance, due to an important side effect: updating the near and
++  far clip planes triggers an SoGetBoundingBoxAction to traverse the
++  scene graph, which causes bounding boxes to be calculated and stored
++  in caches. The bounding box caches are then used by the
++  SoGLRenderAction traversal for view frustum culling operations. With
++  no bounding box caches, the rendering will not do culling, which can
++  cause much worse performance. Kongsberg Oil & Gas Technologies are
++  working on correcting this problem properly from within the Coin
++  library.
++
++  On a minor note, be aware that notifications will be temporarily
++  turned off for the scene's SoCamera when changing the near and far
++  clipping planes (which is done right before each redraw). This is
++  done to avoid notifications being sent through the scene graph right
++  before rendering, as that causes some latency. It is mentioned here
++  in case you have any client code which for some reason needs to
++  sense all changes to the scene camera. This is however unlikely, so
++  you can very probably ignore this.
++
++  \sa getAutoClipping()
++*/
++
++void
++So at Gui@Viewer::setAutoClipping(SbBool enable)
++{
++  if (SO at GUI@_DEBUG) {
++    if (PRIVATE(this)->adjustclipplanes == enable) {
++      SoDebugError::postWarning("So at Gui@Viewer::setAutoClipping",
++                                "unnecessary called");
++      return;
++    }
++  }
++
++  PRIVATE(this)->adjustclipplanes = enable;
++  if (enable) { this->scheduleRedraw(); }
++}
++
++/*!
++  Set the strategy used for automatic updates of the distances to the
++  near and far clipping planes.
++
++  When auto clipping is enabled, the near plane distance is calculated
++  so that it is just in front of the scene bounding box. If this near
++  plane is behind or very close to the projection point, one of the
++  following strategies will be used to calculate the new clipping
++  plane.
++
++  The VARIABLE_NEAR_PLANE strategy considers the number of z buffer
++  bits available for the current OpenGL context, and uses \a value to
++  calculate the number of bits that is lost because of the far/near
++  ratio. \a value should be in the range [0.0, 1.0]. A higher \a value
++  will increase the z-buffer precision, but also push the near plane
++  further away from the projection point.
++  
++  The CONSTANT_NEAR_PLANE strategy simply sets the near plane to 
++  \a value. If \a value at some point approaches the far clipping
++  plane distance, the near plane distance will be set to far plane 
++  distance divided by 5000.0.
++
++  The default strategy is VARIABLE_NEAR_PLANE.
++
++
++  It is also possible to register a callback method \a cb, which will
++  then be invoked after the near and far clipping planes has been
++  calculated by the So at Gui@Viewer code. The callback can then adjust
++  the values for the distance to the near and far planes to exactly
++  match the needs of the application (for instance at specific parts
++  in the scene), to limit the distance to either plane, or whatever
++  else needs to be controlled.
++
++  The signature of the So at Gui@AutoClippingCB callback must match:
++  \code
++  SbVec2f myfunc(void * data, const SbVec2f & nearfar);
++  \endcode
++
++  The first argument is the \a cbuserdata passed in along with the
++  callback function pointer itself (ie the callback function's
++  closure). The second argument is the near and far clipping plane
++  distances from the camera position, as calculated internally by the
++  viewer, including "slack".
++
++  The function callback can then modify the near and far clipping
++  plane distances to what will \e actually be used by the
++  viewer. These values will then be used unmodified for the viewer's
++  camera.
++
++  This is a good way of dynamically modifying the near and far
++  distances such that they at all times exactly matches the specific
++  layout of the application scene, for instance with regard to the
++  trade-off between z-buffer resolution and how early geometry is
++  clipped at the near plane (or at the far plane).
++
++  Note that the internal near/far calculations should be good enough
++  for the vast majority of scenes. Application programmers should only
++  need to set up their own adjustments upon "unusual" scenes, like for
++  instance scenes with a large world space, but where one would still
++  like to be able to get up extremely close on details in some parts
++  of the scene.
++
++
++  \sa setAutoClipping() 
++*/
++void 
++So at Gui@Viewer::setAutoClippingStrategy(const AutoClippingStrategy strategy,
++                                       const float value,
++                                       So at Gui@AutoClippingCB * cb,
++                                       void * cbuserdata)
++{
++  PRIVATE(this)->autoclipstrategy = strategy;
++  PRIVATE(this)->autoclipvalue = value;
++  PRIVATE(this)->autoclipcb = cb;
++  PRIVATE(this)->autoclipuserdata = cbuserdata;
++
++  if (PRIVATE(this)->autoclipstrategy == VARIABLE_NEAR_PLANE) {
++    // normalize the value so that the near plane isn't too near or
++    // too far from the projection point.  FIXME: calibrate this
++    // normalization, pederb, 2002-04-25
++    float v = So at Gui@Clamp(value, 0.0f, 1.0f); // just in case
++    v *= 0.8f;
++    v += 0.1f; // v will be in range [0.1, 0.9]
++
++    PRIVATE(this)->autoclipvalue = v;
++  }
++  if (PRIVATE(this)->adjustclipplanes) {
++    this->scheduleRedraw();
++  }
++}
++
++// *************************************************************************
++
++/*!
++  Return value of the automatic near/far clipplane adjustment indicator.
++
++  \sa setAutoClipping()
++*/
++
++SbBool
++So at Gui@Viewer::isAutoClipping(void) const
++{
++  return PRIVATE(this)->adjustclipplanes;
++}
++
++// *************************************************************************
++
++/*!
++  Turn stereo viewing on or off.
++
++  Note: this function is being obsoleted, you should use the
++  setStereoType() function instead.
++
++  Coin does "correct" stereo rendering, using the method known as
++  "parallel axis asymmetric frustum perspective projection". For more
++  information, see this link:
++
++    http://astronomy.swin.edu.au/~pbourke/opengl/stereogl/
++
++  \sa isStereoViewing(), setStereoType()
++*/
++
++void
++So at Gui@Viewer::setStereoViewing(SbBool enable)
++{
++  PRIVATE(this)->stereoviewing = enable;
++  this->scheduleRedraw();
++}
++
++/*!
++  Returns a boolean indicating whether or not we're in stereo viewing
++  mode.
++
++  NOTE: in the original InventorXt API, this method was virtual.  It is not
++  virtual here.
++
++  \sa setStereoViewing(), getStereoType()
++*/
++
++SbBool
++So at Gui@Viewer::isStereoViewing(void) const
++{
++  return PRIVATE(this)->stereoviewing;
++}
++
++// *************************************************************************
++
++/*!
++  \enum So at Gui@Viewer::StereoType
++
++  Contains list of supported stereo rendering techniques.
++
++  \sa So at Gui@Viewer::setStereoType()
++*/
++/*!
++  \var So at Gui@Viewer::StereoType So at Gui@Viewer::STEREO_NONE
++
++  Use monoscopic rendering.
++*/
++/*!
++  \var So at Gui@Viewer::StereoType So at Gui@Viewer::STEREO_ANAGLYPH
++
++  Render stereo by superimposing two images of the same scene, but with
++  different color filters over the left and right view (or "eye").
++
++  This is a way of rendering stereo which works on any display, using
++  color-filter glasses. Such glasses are usually cheap and easy to
++  come by.
++
++  \sa setAnaglyphStereoColorMasks()
++*/
++/*!
++  \var So at Gui@Viewer::StereoType So at Gui@Viewer::STEREO_QUADBUFFER
++
++  Render stereo by using OpenGL quad-buffers. This is the most common
++  interface for stereo rendering for more expensive hardware devices,
++  such as shutter glasses and polarized glasses.
++
++  The well known Crystal Eyes glasses are commonly used with this type
++  of stereo display.
++*/
++/*!
++  \var So at Gui@Viewer::StereoType So at Gui@Viewer::STEREO_INTERLEAVED_ROWS
++
++  Interleaving / interlacing rows from the left and right eye is
++  another stereo rendering method requiring special hardware. One
++  example of a provider of shutter glasses working with interleaved
++  glasses is VRex:
++
++    http://www.vrex.com/
++*/
++/*!
++  \var So at Gui@Viewer::StereoType So at Gui@Viewer::STEREO_INTERLEAVED_COLUMNS
++
++  Same basic technique as So at Gui@Viewer::STEREO_INTERLEAVED_ROWS, only
++  it is vertical lines that are interleaved / interlaced, instead of
++  horizontal lines.
++*/
++
++/*!
++  Set up stereo rendering.
++
++  Coin does "correct" stereo rendering, using the method known as
++  "parallel axis asymmetric frustum perspective projection". For more
++  information, see this link:
++
++    http://astronomy.swin.edu.au/~pbourke/opengl/stereogl/
++
++
++  Note: it is prefered that one uses this function for control of
++  which type of stereo rendering to use, instead of the older
++  So at Gui@Viewer::setStereoViewing() and
++  So at Gui@GLWidget::setQuadBufferStereo() functions.
++
++  The default is to do monoscopic rendering, i.e. the default
++  So at Gui@Viewer::StereoType value is So at Gui@Viewer::STEREO_NONE.
++
++  \sa So at Gui@Viewer::StereoType, SoCamera::setStereoAdjustment
++  \since So at Gui@ 1.2
++*/
++SbBool
++So at Gui@Viewer::setStereoType(So at Gui@Viewer::StereoType s)
++{
++  if (s == this->getStereoType()) { return TRUE; }
++
++  // We need to know this to keep compatibility with older client
++  // code, which controlled stereo rendering with setStereoViewing()
++  // and setQuadBufferStereo() only.
++  PRIVATE(this)->stereotypesetexplicit = TRUE;
++
++  switch (s) {
++  case So at Gui@Viewer::STEREO_NONE:
++    this->setQuadBufferStereo(FALSE);
++    this->setStereoViewing(FALSE);
++    break;
++
++  case So at Gui@Viewer::STEREO_ANAGLYPH:
++    this->setStereoViewing(TRUE);
++    this->setQuadBufferStereo(FALSE);
++    break;
++
++  case So at Gui@Viewer::STEREO_QUADBUFFER:
++    this->setStereoViewing(TRUE);
++    this->setQuadBufferStereo(TRUE);
++
++    // Check, in case GL quad buffers not supported with the driver
++    // config:
++    if (!this->isQuadBufferStereo()) {
++      this->setStereoViewing(FALSE);
++      return FALSE;
++    }
++    break;
++
++  case So at Gui@Viewer::STEREO_INTERLEAVED_ROWS:
++  case So at Gui@Viewer::STEREO_INTERLEAVED_COLUMNS:
++    this->setStereoViewing(TRUE);
++    this->setQuadBufferStereo(FALSE);
++    this->setStencilBuffer(TRUE);
++
++    // Check, in case GL stencil buffers not supported with the driver
++    // config:
++    if (!this->getStencilBuffer()) {
++      this->setStereoViewing(FALSE);
++      return FALSE;
++    }
++    break;
++
++  default:
++    assert(FALSE); break;
++  }
++
++  PRIVATE(this)->stereotype = s;
++  return TRUE;
++}
++
++/*!
++  Returns the current type of stereo rendering used (or
++  So at Gui@Viewer::STEREO_NONE if monoscopic).
++*/
++So at Gui@Viewer::StereoType
++So at Gui@Viewer::getStereoType(void) const
++{
++  // Stereo can be set up without using setStereoType() through the
++  // older functions setStereoViewing() and setQuadBufferStereo(), so
++  // we need to check for this separately.
++  if (!PRIVATE(this)->stereotypesetexplicit) {
++    if (this->isQuadBufferStereo()) {
++      PRIVATE(this)->stereotype = So at Gui@Viewer::STEREO_QUADBUFFER;
++    }
++    else if (this->isStereoViewing()) {
++      PRIVATE(this)->stereotype = So at Gui@Viewer::STEREO_ANAGLYPH;
++    }
++  }
++
++  return PRIVATE(this)->stereotype;
++}
++
++// *************************************************************************
++
++/*!
++  If display is configured to render in anaglyph stereo, this function
++  can be used to control which filter is used for each eye.
++
++  The default filters are red (i.e. color vector [TRUE,FALSE,FALSE])
++  for the left eye, and cyan (color vector [FALSE,TRUE,TRUE]) for the
++  right eye.
++
++  \sa So at Gui@Viewer::StereoType, setStereoType()
++*/
++void
++So at Gui@Viewer::setAnaglyphStereoColorMasks(const SbBool left[3], const SbBool right[3])
++{
++  for (unsigned int i = 0; i < 3; i++) {
++    PRIVATE(this)->stereoanaglyphmask[0][i] = left[i];
++    PRIVATE(this)->stereoanaglyphmask[1][i] = right[i];
++  }
++
++  this->scheduleRedraw();
++}
++
++/*!
++  Returns color masks for left and right eye filters in anaglyph
++  stereo.
++
++  \sa setAnaglyphStereoColorMasks()
++*/
++void
++So at Gui@Viewer::getAnaglyphStereoColorMasks(SbBool left[3], SbBool right[3])
++{
++  for (unsigned int i = 0; i < 3; i++) {
++    left[i] = PRIVATE(this)->stereoanaglyphmask[0][i];
++    right[i] = PRIVATE(this)->stereoanaglyphmask[1][i];
++  }
++}
++
++// *************************************************************************
++
++/*!
++  Set the offset between the two viewpoints when in stereo mode.
++  Default value is 0.1.
++
++  NOTE: In the original InventorXt API, this method was not virtual.
++
++  \sa getStereoOffset()
++*/
++void
++So at Gui@Viewer::setStereoOffset(const float dist)
++{
++  PRIVATE(this)->stereooffset = dist;
++  this->scheduleRedraw();
++}
++
++/*!
++  Return the offset distance between the two viewpoints when in stereo
++  mode.
++
++  \sa setStereoOffset()
++*/
++float
++So at Gui@Viewer::getStereoOffset(void) const
++{
++  return PRIVATE(this)->stereooffset;
++}
++
++// *************************************************************************
++
++/*!
++  Toggle between seeking to a point or seeking to an object.
++
++  Default is to seek to a point.
++
++  \sa isDetailSeek()
++*/
++
++void
++So at Gui@Viewer::setDetailSeek(const SbBool on)
++{
++  if (SO at GUI@_DEBUG) {
++    if (PRIVATE(this)->seektopoint == on) {
++      SoDebugError::postWarning("So at Gui@Viewer::setDetailSeek",
++                                "unnecessary called");
++      return;
++    }
++  }
++
++  PRIVATE(this)->seektopoint = on;
++}
++
++// *************************************************************************
++
++/*!
++  Returns a value indicating whether or not seeks will be performed
++  to the exact point of picking or just towards the picked object.
++
++  \sa setDetailSeek()
++*/
++
++SbBool
++So at Gui@Viewer::isDetailSeek(void) const
++{
++  return PRIVATE(this)->seektopoint;
++}
++
++// *************************************************************************
++
++/*!
++  Set the duration of animating the camera repositioning
++  after a successful seek. Call with \a seconds equal to \a 0.0 to make
++  the camera jump immediately to the correct spot.
++
++  Default value is 2 seconds.
++
++  \sa getSeekTime()
++*/
++
++void
++So at Gui@Viewer::setSeekTime(const float seconds)
++{
++  if (seconds < 0.0f) {
++    if (SO at GUI@_DEBUG) {
++      SoDebugError::postWarning("So at Gui@Viewer::setSeekTime",
++                                "an attempt was made to set a negative seek "
++                                "time duration");
++    }
++    return;
++  }
++  PRIVATE(this)->seekperiod = seconds;
++}
++
++// *************************************************************************
++
++/*!
++  Returns the camera repositioning duration following a seek action.
++
++  \sa setSeekTime()
++*/
++
++float
++So at Gui@Viewer::getSeekTime(void) const
++{
++  return PRIVATE(this)->seekperiod;
++}
++
++// *************************************************************************
++
++/*!
++  Add a function to call when user interaction with the scene starts.
++
++  \sa removeStartCallback(), addFinishCallback()
++*/
++
++void
++So at Gui@Viewer::addStartCallback(So at Gui@ViewerCB * func, void * data)
++{
++  PRIVATE(this)->interactionstartCallbacks->addCallback((SoCallbackListCB *)func, data);
++}
++
++/*!
++  Remove one of the functions which has been set up to be called when user
++  interaction with the scene starts.
++
++  \sa addStartCallback(), removeFinishCallback()
++*/
++
++void
++So at Gui@Viewer::removeStartCallback(So at Gui@ViewerCB * func, void * data)
++{
++  PRIVATE(this)->interactionstartCallbacks->removeCallback((SoCallbackListCB *)func,
++                                                  data);
++}
++
++// *************************************************************************
++
++/*!
++  Add a function to call when user interaction with the scene ends.
++
++  \sa removeFinishCallback(), addStartCallback()
++*/
++
++void
++So at Gui@Viewer::addFinishCallback(So at Gui@ViewerCB * func, void * data)
++{
++  PRIVATE(this)->interactionendCallbacks->addCallback((SoCallbackListCB *)func, data);
++}
++
++/*!
++  Remove one of the functions which has been set up to be called when user
++  interaction with the scene ends.
++
++  \sa addFinishCallback(), removeStartCallback()
++*/
++
++void
++So at Gui@Viewer::removeFinishCallback(So at Gui@ViewerCB * func, void * data)
++{
++  PRIVATE(this)->interactionendCallbacks->removeCallback((SoCallbackListCB *)func,
++                                                data);
++}
++
++// *************************************************************************
++
++/*!
++  Set the color of the overlay wireframe to \a color.
++
++  \sa getWireframeOverlayColor()
++*/
++void So at Gui@Viewer::setWireframeOverlayColor(const SbColor & color)
++{
++  PRIVATE(this)->wireframeoverlaycolor = color;
++  this->scheduleRedraw();
++}
++
++// *************************************************************************
++
++/*!
++  Returns the current color of the overlay wireframe. The default
++  color is [1,0,0], ie pure red.
++
++  \sa setWireframeOverlayColor()
++*/
++const SbColor &So at Gui@Viewer::getWireframeOverlayColor(void) const
++{
++  return PRIVATE(this)->wireframeoverlaycolor;
++}
++
++// *************************************************************************
++
++/*!
++  Overloaded to update the local bufferingtype variable.
++
++  \sa setBufferingType(), getBufferingType()
++*/
++
++void
++So at Gui@Viewer::setDoubleBuffer(const SbBool on)
++{
++  if (!PRIVATE(this)->localsetbuffertype)
++    PRIVATE(this)->buffertype = on ? BUFFER_DOUBLE : BUFFER_SINGLE;
++
++  inherited::setDoubleBuffer(on);
++}
++
++// *************************************************************************
++
++/*!
++  Give the viewer a scenegraph to render and interact with. Overridden
++  from parent class so the viewer can add it's own nodes to control
++  rendering in different styles, rendering with a headlight, etc.
++
++  The \a root node will be inserted under the \e viewer's root node,
++  which also covers the nodes necessary to implement the different
++  preferences drawing style settings.
++
++  If no camera is part of the scene graph under \a root, one will
++  automatically be instantiated and added. You can get a reference to
++  this camera by using the So at Gui@Viewer::getCamera() method.
++
++  \sa getSceneGraph(), setCameraType()
++*/
++
++void
++So at Gui@Viewer::setSceneGraph(SoNode * root)
++{
++  if ((root != NULL) && (root == PRIVATE(this)->scenegraph)) {
++    if (SO at GUI@_DEBUG) {
++      SoDebugError::postWarning("So at Gui@Viewer::setSceneGraph",
++                                "called with the same root as already set");
++    }
++    return;
++  }
++
++  // If the So at Gui@RenderArea hasn't yet set up its pointer to the
++  // So at Gui@Viewer "viewer root" (i.e. the viewer-generated root above
++  // the user-supplied root), do that first.
++  if (!inherited::getSceneGraph())
++    inherited::setSceneGraph(PRIVATE(this)->sceneroot);
++
++  if (PRIVATE(this)->scenegraph) {
++    if (this->getCamera())
++      this->setCamera(NULL);
++    // Release the old user-supplied graph.
++    PRIVATE(this)->usersceneroot->removeChild(PRIVATE(this)->scenegraph);
++    // old: PRIVATE(this)->sceneroot->removeChild(PRIVATE(this)->scenegraph);
++  }
++
++  PRIVATE(this)->scenegraph = root;
++  if (!root) return;
++
++  PRIVATE(this)->usersceneroot->addChild(PRIVATE(this)->scenegraph);
++
++  // Search for a camera in the user-supplied scenegraph.
++
++  SbBool oldsearch = SoBaseKit::isSearchingChildren();
++  SoBaseKit::setSearchingChildren(TRUE);
++
++  PRIVATE(this)->searchaction->reset();
++  PRIVATE(this)->searchaction->setType(SoCamera::getClassTypeId());
++  PRIVATE(this)->searchaction->apply(PRIVATE(this)->scenegraph);
++
++  SoBaseKit::setSearchingChildren(oldsearch);
++
++  SoCamera * scenecamera = NULL;
++  if ( PRIVATE(this)->searchaction->getPath() != NULL ) {
++    SoFullPath * fullpath =
++      (SoFullPath *) PRIVATE(this)->searchaction->getPath();
++    scenecamera = (SoCamera *)fullpath->getTail();
++  }
++
++#if 0 // debug
++  SoDebugError::postInfo("So at Gui@Viewer::setSceneGraph",
++                         "camera %sfound in graph",
++                         scenecamera ? "" : "not ");
++#endif // debug
++
++  // Make our own camera if none was available.
++  if (!scenecamera) {
++    if (SoGuiViewpointWrapper::hasViewpoints(root)) {
++      scenecamera = new SoGuiViewpointWrapper;
++      PRIVATE(this)->cameratype = SoGuiViewpointWrapper::getClassTypeId();
++      ((SoGuiViewpointWrapper*)scenecamera)->setSceneGraph(root);
++    }
++    else {
++      scenecamera = (SoCamera *) PRIVATE(this)->cameratype.createInstance();
++    }
++    
++    // If type==BROWSER, camera should be inserted in the private
++    // viewer "supergraph", if it's equal to EDITOR it should be
++    // inserted in the user-supplied scenegraph.
++    if (PRIVATE(this)->type == So at Gui@Viewer::BROWSER) {
++      PRIVATE(this)->sceneroot->insertChild(scenecamera, 1);
++    }
++    else { // PRIVATE(this)->type == So at Gui@Viewer::EDITOR
++      if (PRIVATE(this)->scenegraph->isOfType(SoGroup::getClassTypeId())) {
++        // At the uppermost leftmost position in the user-supplied
++        // scenegraph.
++        ((SoGroup *)PRIVATE(this)->scenegraph)->insertChild(scenecamera, 0);
++      }
++      else {
++        // Make an extra depth level to fit the camera node into the
++        // user-scenegraph.
++        SoGroup * g = new SoGroup;
++        g->addChild(scenecamera);
++        g->addChild(PRIVATE(this)->scenegraph);
++        PRIVATE(this)->usersceneroot->removeChild(PRIVATE(this)->scenegraph);
++        PRIVATE(this)->usersceneroot->addChild(g);
++        PRIVATE(this)->scenegraph = g;
++      }
++    }
++    if (PRIVATE(this)->cameratype != SoGuiViewpointWrapper::getClassTypeId()) {
++      scenecamera->viewAll(PRIVATE(this)->scenegraph, this->getViewportRegion());
++    }
++  }
++
++  this->setCamera(scenecamera);
++}
++
++// *************************************************************************
++
++// doc in super
++SoNode *
++So at Gui@Viewer::getSceneGraph(void)
++{
++  // Overloaded from parent class to return the root of the scene
++  // graph set by the user, without the extras added by the viewer to
++  // control rendering.
++  return PRIVATE(this)->scenegraph;
++}
++
++// *************************************************************************
++
++// Note: the following function documentation block will also be used
++// for all the miscellaneous viewer subclasses, so keep it general.
++/*!
++  Put the viewer in or out of "waiting-to-seek" mode.
++
++  If the user performs a mouse button click when the viewer is in
++  "waiting-to-seek" mode, the camera will be repositioned so the
++  camera focal point lies on the point of the geometry under the mouse
++  cursor.
++
++  \sa isSeekMode(), setDetailSeek()
++*/
++void
++So at Gui@Viewer::setSeekMode(SbBool enable)
++{
++  if (SO at GUI@_DEBUG) {
++    // User might have switched mode during seek, so if enable==FALSE,
++    // isViewing() is irrelevant.
++    if (enable) { assert(this->isViewing()); }
++  }
++
++  if (!enable && PRIVATE(this)->seeksensor->isScheduled()) {
++    PRIVATE(this)->seeksensor->unschedule();
++    this->interactiveCountDec();
++  }
++
++  PRIVATE(this)->inseekmode = enable;
++}
++
++// *************************************************************************
++
++/*!
++  Return a flag which indicates whether or not the viewer is in
++  "waiting-to-seek" mode.
++
++  (The actual animated translation will not occur until the end user
++  really \e starts the seek operation, typically by clicking with the
++  left mousebutton.)
++
++  \sa setSeekMode()
++*/
++SbBool
++So at Gui@Viewer::isSeekMode(void) const
++{
++  return PRIVATE(this)->inseekmode;
++}
++
++// *************************************************************************
++
++/*!
++  Call this method to initiate a seek action towards the 3D
++  intersection of the scene and the ray from the screen coordinate's
++  point and in the same direction as the camera is pointing.
++
++  Returns \c TRUE if the ray from the \a screenpos position intersect
++  with any parts of the onscreen geometry, otherwise \c FALSE.
++*/
++SbBool
++So at Gui@Viewer::seekToPoint(const SbVec2s screenpos)
++{
++  if (! PRIVATE(this)->camera)
++    return FALSE;
++
++  SoRayPickAction rpaction(this->getViewportRegion());
++  rpaction.setPoint(screenpos);
++  rpaction.setRadius(2);
++  rpaction.apply(PRIVATE(this)->sceneroot);
++
++  SoPickedPoint * picked = rpaction.getPickedPoint();
++  if (!picked) {
++    // FIXME: this inc seems bogus, but is needed now due to buggy
++    // code in for instance the examinerviewer
++    // processSoEvent(). 20020510 mortene.
++#if 1
++    this->interactiveCountInc(); // decremented in setSeekMode(FALSE)
++#endif // FIXME
++    this->setSeekMode(FALSE);
++    return FALSE;
++  }
++
++  SbVec3f hitpoint;
++  if (PRIVATE(this)->seektopoint) {
++    hitpoint = picked->getPoint();
++  } 
++  else {
++    SoGetBoundingBoxAction bbaction(this->getViewportRegion());
++    bbaction.apply(picked->getPath());
++    SbBox3f bbox = bbaction.getBoundingBox();
++    hitpoint = bbox.getCenter();
++  }
++
++  this->seekToPoint(hitpoint);
++  return TRUE;
++}
++
++/*!
++  Call this method to initiate a seek action towards the give 3D world
++  coordinate point in the scene, \a scenepos.
++
++  \since So at Gui@ 1.3.0
++*/
++void
++So at Gui@Viewer::seekToPoint(const SbVec3f & scenepos)
++{
++  SbVec3f hitpoint(scenepos);
++
++  PRIVATE(this)->camerastartposition = PRIVATE(this)->camera->position.getValue();
++  PRIVATE(this)->camerastartorient = PRIVATE(this)->camera->orientation.getValue();
++
++  // move point to the camera coordinate system, consider
++  // transformations before camera in the scene graph
++  SbMatrix cameramatrix, camerainverse;
++  PRIVATE(this)->getCameraCoordinateSystem(PRIVATE(this)->camera,
++                                           PRIVATE(this)->sceneroot,
++                                           cameramatrix,
++                                           camerainverse);
++  camerainverse.multVecMatrix(hitpoint, hitpoint);
++
++  float fd = PRIVATE(this)->seekdistance;
++  if (!PRIVATE(this)->seekdistanceabs)
++    fd *= (hitpoint - PRIVATE(this)->camera->position.getValue()).length()/100.0f;
++  PRIVATE(this)->camera->focalDistance = fd;
++
++  SbVec3f dir = hitpoint - PRIVATE(this)->camerastartposition;
++  dir.normalize();
++
++  // find a rotation that rotates current camera direction into new
++  // camera direction.
++  SbVec3f olddir;
++  PRIVATE(this)->camera->orientation.getValue().multVec(SbVec3f(0, 0, -1), olddir);
++  SbRotation diffrot(olddir, dir);
++  PRIVATE(this)->cameraendposition = hitpoint - fd * dir;
++  PRIVATE(this)->cameraendorient = PRIVATE(this)->camera->orientation.getValue() * diffrot;
++
++  // Subclasses that want another cameraendorient than what is
++  // computed here should override this function and set the desired
++  // orientation there
++  this->computeSeekFinalOrientation();
++
++  if (PRIVATE(this)->seeksensor->isScheduled()) {
++    PRIVATE(this)->seeksensor->unschedule();
++    this->interactiveCountDec();
++  }
++
++  PRIVATE(this)->seeksensor->setBaseTime(SbTime::getTimeOfDay());
++  PRIVATE(this)->seeksensor->schedule();
++  this->interactiveCountInc();
++}
++
++// *************************************************************************
++
++void
++So at Gui@ViewerP::setStereoEye(SoCamera * thecamera,
++                             const So at Gui@ViewerP::Eye eye,
++                             So at Gui@ViewerP::StereoData & s) const
++{
++#ifdef HAVE_SOCAMERA_SETSTEREOMODE
++
++  // SoCamera::setStereoMode() is a fairly recent addition to Coin and
++  // TGS Inventor. If available, camera eye setup is quite
++  // straightforward.
++
++  if (eye == So at Gui@ViewerP::LEFT) {
++    thecamera->setStereoAdjustment(PUBLIC(this)->getStereoOffset());
++    thecamera->setStereoMode(SoCamera::LEFT_VIEW);
++  }
++  else if (eye == So at Gui@ViewerP::RIGHT) {
++    thecamera->setStereoMode(SoCamera::RIGHT_VIEW);
++  }
++  else {
++    assert(eye == So at Gui@ViewerP::RESTORE);
++
++    thecamera->setStereoMode(SoCamera::MONOSCOPIC);
++  }
++
++#else // ! HAVE_SOCAMERA_SETSTEREOMODE
++
++  // To support older versions of Coin, and SGI/TGS Inventor, we also
++  // provide "manual" tuning of the camera left/right eye split.
++
++  if (eye == So at Gui@ViewerP::LEFT) {
++    s.camerapos = thecamera->position.getValue();
++    s.cameradir.setValue(0.0f, 0.0f, -1.0f);
++    s.offsetvec.setValue(1.0f, 0.0f, 0.0f);
++    s.offset = PUBLIC(this)->getStereoOffset() * 0.5f;
++    s.camerarot = thecamera->orientation.getValue();
++    s.camerarot.multVec(s.cameradir, s.cameradir);
++    s.camerarot.multVec(s.offsetvec, s.offsetvec);
++    s.focalpoint = s.camerapos + s.cameradir * thecamera->focalDistance.getValue();
++
++    s.nodenotify = thecamera->isNotifyEnabled();
++    s.positionnotify = thecamera->position.isNotifyEnabled();
++    s.orientationnotify = thecamera->orientation.isNotifyEnabled();
++    // turn off notification to avoid redraws
++    thecamera->enableNotify(FALSE);
++    thecamera->position.enableNotify(FALSE);
++    thecamera->orientation.enableNotify(FALSE);
++
++    thecamera->position = s.camerapos - s.offsetvec * s.offset;
++    SbVec3f dir = s.focalpoint - thecamera->position.getValue();
++    SbRotation rot(s.cameradir, dir);
++    thecamera->orientation = s.camerarot * rot;
++  }
++  else if (eye == So at Gui@ViewerP::RIGHT) {
++    thecamera->position = s.camerapos + s.offsetvec * s.offset;
++    SbVec3f dir = s.focalpoint - thecamera->position.getValue();
++    SbRotation rot(s.cameradir, dir);
++    thecamera->orientation = s.camerarot * rot;
++  }
++  else {
++    assert(eye == So at Gui@ViewerP::RESTORE);
++
++    thecamera->position = s.camerapos;
++    thecamera->orientation = s.camerarot;
++    thecamera->position.enableNotify(s.positionnotify);
++    thecamera->orientation.enableNotify(s.orientationnotify);
++    thecamera->enableNotify(s.nodenotify);
++  }
++
++#endif // ! HAVE_SOCAMERA_SETSTEREOMODE
++}
++
++void
++So at Gui@ViewerP::initStencilBufferForInterleavedStereo(void)
++{
++  const SbViewportRegion & currentvp = PUBLIC(this)->getViewportRegion();
++  if (this->stereostencilmaskvp == currentvp) { return; } // the common case
++
++  So at Gui@Viewer::StereoType s = PUBLIC(this)->getStereoType();
++  assert((s == So at Gui@Viewer::STEREO_INTERLEAVED_ROWS) ||
++         (s == So at Gui@Viewer::STEREO_INTERLEAVED_COLUMNS));
++
++  // Find out whether or not we need to regenerate the mask data.
++  SbBool allocnewmask = (this->stereostencilmask == NULL);
++
++  const SbVec2s neworigin = currentvp.getViewportOriginPixels();
++  const SbVec2s newsize = currentvp.getViewportSizePixels();
++
++  const SbVec2s oldorigin = this->stereostencilmaskvp.getViewportOriginPixels();
++  const SbVec2s oldsize = this->stereostencilmaskvp.getViewportSizePixels();
++
++  allocnewmask = allocnewmask ||
++    ((oldsize[0] + 7) / 8 * oldsize[1]) < ((newsize[0] + 7) / 8 * newsize[1]);
++
++  const SbBool fillmask = allocnewmask || (this->stereostenciltype != s) ||
++    ((s == So at Gui@Viewer::STEREO_INTERLEAVED_ROWS) && (oldsize[0] != newsize[0]));
++
++  const SbBool layoutchange = !(this->stereostencilmaskvp == currentvp);
++
++  const short bytewidth = (newsize[0] + 7) / 8;
++
++  if (allocnewmask) {
++    delete[] this->stereostencilmask;
++    this->stereostencilmask = new GLubyte[bytewidth * newsize[1]];
++  }
++
++  this->stereostencilmaskvp = currentvp;
++
++  if (fillmask) {
++    GLubyte * mask = this->stereostencilmask;
++
++    if (s == So at Gui@Viewer::STEREO_INTERLEAVED_COLUMNS) {
++      // alternating columns of 0's and 1's
++      (void)memset(mask, 0x55, bytewidth * newsize[1]);
++    }
++    else {
++      // alternating rows of 0's and 1's
++      for (short h=0; h < newsize[1]; h++) {
++        const GLubyte fill = (h % 2) ? 0xff : 0x00;
++        (void)memset(mask + (h * bytewidth), fill, bytewidth);
++      }
++    }
++
++    this->stereostenciltype = s;
++  }
++
++  if (layoutchange) {
++    glClearStencil(0x0);
++
++    glClear(GL_STENCIL_BUFFER_BIT);
++    glStencilFunc(GL_ALWAYS, GL_REPLACE, GL_REPLACE);
++
++    glMatrixMode(GL_MODELVIEW);
++    glPushMatrix();
++    glLoadIdentity();
++    glMatrixMode(GL_PROJECTION);
++    glPushMatrix();
++    glLoadIdentity();
++
++    glViewport(neworigin[0], neworigin[1], newsize[0], newsize[1]);
++
++    glOrtho(0, newsize[0], 0, newsize[1], -1.0f, 1.0f);
++
++    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
++
++    // FIXME: I've noticed a problem with this approach. If there is
++    // something in the window system obscuring part of the canvas
++    // while this is called (as could e.g. happen with a size
++    // indicator, as with the Sawfish window manager), the stencil
++    // mask will not be set up for that part. 20041019 mortene.
++    //
++    // UPDATE 20041019 mortene: discussed this with pederb, and we
++    // believe this may be due to a bug in either the OpenGL driver
++    // (Nvidia 61.11, Linux) or window system or manager (Sawfish,
++    // XFree86 v4.1.0.1). Should test on other systems to see if they
++    // show the same artifact.
++
++    glRasterPos2f(0, 0);
++    glDrawPixels(newsize[0], newsize[1], GL_STENCIL_INDEX, GL_BITMAP,
++                 this->stereostencilmask);
++
++    glMatrixMode(GL_PROJECTION);
++    glPopMatrix();
++    glMatrixMode(GL_MODELVIEW);
++    glPopMatrix();
++  }
++}
++
++// Documented in superclass. Overridden from parent class to be able
++// to do the necessary two-pass rendering e.g. if the drawing style is
++// hidden line.
++void
++So at Gui@Viewer::actualRedraw(void)
++{
++  SbTime redrawtime = SbTime::getTimeOfDay();
++  const SbBool clearcol = this->isClearBeforeRender();
++  const SbBool clearz = this->isClearZBufferBeforeRender();
++  const So at Gui@Viewer::StereoType stereotype = this->getStereoType();
++
++  if (stereotype != So at Gui@Viewer::STEREO_NONE) {
++#if HAVE_SBCOLOR4F_GETBACKGROUNDCOLOR
++    const SbColor4f bgcol = this->getSceneManager()->getBackgroundColor();
++#else
++    const SbColor4f bgcol(this->getSceneManager()->getBackgroundColor(), 0.0f);
++#endif
++    SoCamera * camera = this->getCamera();
++    So at Gui@ViewerP::StereoData tmpstorage;
++
++    // Render left eye:
++
++    PRIVATE(this)->setStereoEye(camera, So at Gui@ViewerP::LEFT, tmpstorage);
++
++    switch (stereotype) {
++    case So at Gui@Viewer::STEREO_ANAGLYPH:
++      glDrawBuffer(this->isDoubleBuffer() ? GL_BACK : GL_FRONT);
++      glClearColor(bgcol[0], bgcol[1], bgcol[2], 0.0f);
++      glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
++      glColorMask(PRIVATE(this)->stereoanaglyphmask[0][0] ? GL_TRUE : GL_FALSE,
++                  PRIVATE(this)->stereoanaglyphmask[0][1] ? GL_TRUE : GL_FALSE,
++                  PRIVATE(this)->stereoanaglyphmask[0][2] ? GL_TRUE : GL_FALSE,
++                  GL_TRUE);
++      PRIVATE(this)->reallyRedraw(FALSE, FALSE);
++      break;
++    case So at Gui@Viewer::STEREO_QUADBUFFER:
++      glDrawBuffer(this->isDoubleBuffer() ? GL_BACK_LEFT : GL_FRONT_LEFT);
++      PRIVATE(this)->reallyRedraw(clearcol, clearz);
++      break;
++    case So at Gui@Viewer::STEREO_INTERLEAVED_ROWS:
++    case So at Gui@Viewer::STEREO_INTERLEAVED_COLUMNS:
++      PRIVATE(this)->initStencilBufferForInterleavedStereo();
++      glEnable(GL_STENCIL_TEST);
++      // immutable data in the stencil buffer
++      glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
++      glStencilFunc(GL_EQUAL, 0x1, 0x1);
++      PRIVATE(this)->reallyRedraw(clearcol, clearz);
++      break;
++
++    default: assert(FALSE); break;
++    }
++
++    // Render right eye:
++
++    PRIVATE(this)->setStereoEye(camera, So at Gui@ViewerP::RIGHT, tmpstorage);
++
++    switch (stereotype) {
++    case So at Gui@Viewer::STEREO_ANAGLYPH:
++      glColorMask(PRIVATE(this)->stereoanaglyphmask[1][0] ? GL_TRUE : GL_FALSE,
++                  PRIVATE(this)->stereoanaglyphmask[1][1] ? GL_TRUE : GL_FALSE,
++                  PRIVATE(this)->stereoanaglyphmask[1][2] ? GL_TRUE : GL_FALSE,
++                  GL_TRUE);
++      PRIVATE(this)->reallyRedraw(FALSE, TRUE);
++      break;
++    case So at Gui@Viewer::STEREO_QUADBUFFER:
++      glDrawBuffer(this->isDoubleBuffer() ? GL_BACK_RIGHT : GL_FRONT_RIGHT);
++      PRIVATE(this)->reallyRedraw(clearcol, clearz);
++      break;
++    case So at Gui@Viewer::STEREO_INTERLEAVED_ROWS:
++    case So at Gui@Viewer::STEREO_INTERLEAVED_COLUMNS:
++      glStencilFunc(GL_NOTEQUAL, 0x1, 0x1);
++      PRIVATE(this)->reallyRedraw(FALSE, FALSE);
++      break;
++    default: assert(FALSE); break;
++    }
++
++    // Clean-up, post-rendering:
++
++    PRIVATE(this)->setStereoEye(camera, So at Gui@ViewerP::RESTORE, tmpstorage);
++
++    switch (stereotype) {
++    case So at Gui@Viewer::STEREO_ANAGLYPH:
++      glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // restore GL color mask
++      break;
++    case So at Gui@Viewer::STEREO_QUADBUFFER:
++      glDrawBuffer(this->isDoubleBuffer() ? GL_BACK : GL_FRONT);
++      break;
++    case So at Gui@Viewer::STEREO_INTERLEAVED_ROWS:
++    case So at Gui@Viewer::STEREO_INTERLEAVED_COLUMNS:
++      // FIXME: restore old val. 20040618 mortene.
++      glDisable(GL_STENCIL_TEST);
++      break;
++    default: assert(FALSE); break;
++    }
++  }
++  else { // No stereo:
++    PRIVATE(this)->reallyRedraw(clearcol, clearz);
++  }
++
++  if (PRIVATE(this)->superimpositions != NULL) {
++    SoGLRenderAction * raaction = this->getSceneManager()->getGLRenderAction();
++    SbBool first = TRUE;
++    SbBool zWasEnabled = FALSE;
++    for (int i = 0; i < PRIVATE(this)->superimpositions->getLength(); i++) {
++      if (PRIVATE(this)->superimpositionsenabled[i] != FALSE) {
++	if (first) {
++	  // save Z buffer state and disable
++          zWasEnabled = glIsEnabled(GL_DEPTH_TEST) ? TRUE : FALSE;
++	  glDisable(GL_DEPTH_TEST);
++          first = FALSE;
++	}
++	SoNode * scene = (SoNode *) (*PRIVATE(this)->superimpositions)[i];
++	raaction->apply(scene);
++      }
++    }
++    if (!first && zWasEnabled) glEnable(GL_DEPTH_TEST);
++  }
++
++  redrawtime = SbTime::getTimeOfDay() - redrawtime;
++  PRIVATE(this)->recordFPS(redrawtime.getValue());
++}
++
++// *************************************************************************
++
++/*!
++  To be able to trigger callback functions when user interaction starts
++  and/or stops, we need to keep track of the viewer state (i.e. are we in
++  still mode or in animation mode?).
++
++  So at Gui@Viewer automatically adds callbacks to switch between still and
++  moving draw style, and to switch between single/double buffer when
++  the buffer type is \a INTERACTIVE.
++
++  \sa interactiveCountDec(), getInteractiveCount()
++  \sa addStartCallback(), addFinishCallback()
++  \sa removeStartCallback(), removeFinishCallback()
++  \sa setDrawStyle(), setBufferingType()
++*/
++
++void
++So at Gui@Viewer::interactiveCountInc(void)
++{
++  // Catch problems with missing interactiveCountDec() calls.
++  assert(PRIVATE(this)->interactionnesting < 100);
++
++  if (++(PRIVATE(this)->interactionnesting) == 1) {
++    PRIVATE(this)->interactionstartCallbacks->invokeCallbacks(this);
++    PRIVATE(this)->resetFrameCounter();
++  }
++
++#if 0 // debug
++  SoDebugError::postInfo("So at Gui@Viewer::interactiveCountInc", "%d -> %d",
++                         PRIVATE(this)->interactionnesting - 1,
++                         PRIVATE(this)->interactionnesting);
++#endif // debug
++}
++
++// *************************************************************************
++
++/*!
++  To be able to trigger callback functions when user interaction starts
++  and/or stops, we need to keep track of the viewer state (i.e. are we in
++  still mode or in animation mode?).
++
++  So at Gui@Viewer automatically adds callbacks to switch between still and
++  moving draw style, and to switch between single/double buffer when
++  the buffer type is \a INTERACTIVE.
++
++  \sa interactiveCountInc(), getInteractiveCount()
++  \sa addStartCallback(), addFinishCallback()
++  \sa removeStartCallback(), removeFinishCallback()
++  \sa setDrawStyle(), setBufferingType()
++*/
++
++void
++So at Gui@Viewer::interactiveCountDec(void)
++{
++  // FIXME: The UI toolkits may cause the interactionnesting to go
++  // below zero by triggering press and release events in different
++  // widgets. mariusbu 20010709.
++
++  // FIXME: just to clarify; this is due to programming mistakes on
++  // our behalf and should be cleaned up. We're using a simple
++  // work-around / ignore strategy for now, though, as getting this
++  // 100% correct is hard (there are so many possible ways of user
++  // interaction with a viewer canvas) and the end-user will usually
++  // not notice any problems at all. So that's why we are using a
++  // warning instead of an assert(). 20010815 mortene.
++
++  // FIXME: here's one known way to trigger the bug: hit "s" in the
++  // examinerviewer in EXAMINE mode, then while seeking hit ESC to put
++  // the viewer in INTERACT mode. When the seek is completed, the
++  // count will become -1.  20010912 mortene.
++
++  // FIXME: and another one (tested with SoXt): click and hold LMB in
++  // the canvas while in INTERACT mode, then hit 'Esc' to switch to
++  // EXAMINE mode, then release LMB. 20020325 mortene.
++
++  if (SO at GUI@_DEBUG) {
++    if (PRIVATE(this)->interactionnesting <= 0) {
++      SoDebugError::postWarning("So at Gui@Viewer::interactiveCountDec",
++                                "interaction count nesting went below zero. "
++                                "This is due to an internal So at Gui@ bug.");
++    }
++  }
++
++  if (--(PRIVATE(this)->interactionnesting) <= 0) {
++    PRIVATE(this)->interactionendCallbacks->invokeCallbacks(this);
++    PRIVATE(this)->interactionnesting = 0;
++  }
++}
++
++// *************************************************************************
++
++/*!
++  Return current interaction count nesting. If equal to zero, the viewer
++  is in animation mode, otherwise the camera is still.
++
++  \sa interactiveCountInc(), interactiveCountDec()
++*/
++
++int
++So at Gui@Viewer::getInteractiveCount(void) const
++{
++  return PRIVATE(this)->interactionnesting;
++}
++
++// *************************************************************************
++
++/*!
++  Set the value used for calculating how close the camera and intersection
++  hit point should be made at the end of a seek operation.
++
++  The value can be interpreted as an absolute value in the given world
++  unit (which typically is meters) or as a percentage value of the
++  distance between the camera starting position and the intersection
++  hit point. This can be controlled through the
++  setSeekValueAsPercentage() method. It is as default used as an
++  absolute value.
++
++  Default value is 50 (absolute distance or percent).
++
++  \sa getSeekDistance(), setSeekValueAsPercentage(), setSeekTime()
++*/
++
++void
++So at Gui@Viewer::setSeekDistance(const float distance)
++{
++  if (distance <= 0.0f) {
++    if (SO at GUI@_DEBUG) {
++      SoDebugError::postWarning("So at Gui@Viewer::setSeekDistance",
++                                "invalid seek distance value: %f",
++                                distance);
++    }
++    return;
++  }
++  PRIVATE(this)->seekdistance = distance;
++}
++
++// *************************************************************************
++
++/*!
++  Returns the current seek distance. Value given as an absolute scalar
++  length or as a percentage value of the original distance between
++  the hitpoint and the camera starting position.
++
++  \sa setSeekDistance(), isSeekValueAsPercentage()
++*/
++
++float
++So at Gui@Viewer::getSeekDistance(void) const
++{
++  return PRIVATE(this)->seekdistance;
++}
++
++// *************************************************************************
++
++/*!
++  Control whether or not the seek distance value should be interpreted as
++  a percentage value or as an absolute distance. See documentation on
++  setSeekDistance() for more information.
++
++  \sa setSeekDistance(), isSeekValueAsPercentage()
++*/
++
++void
++So at Gui@Viewer::setSeekValueAsPercentage(const SbBool on)
++{
++  if (SO at GUI@_DEBUG) {
++    if ((on && this->isSeekValuePercentage()) ||
++        (!on && !this->isSeekValuePercentage())) {
++      SoDebugError::postWarning("So at Gui@Viewer::setSeekDistanceAsPercentage",
++                                "unnecessary called, value already %s",
++                                on ? "on" : "off");
++      return;
++    }
++  }
++
++  PRIVATE(this)->seekdistanceabs = on ? FALSE : TRUE;
++}
++
++// *************************************************************************
++
++/*!
++  Returns an boolean which indicates if the seek distance value from
++  getSeekDistance() should be interpreted as a percentage value or
++  as an absolute value.
++
++  \sa setSeekValuePercentage(), getSeekDistance()
++*/
++
++SbBool
++So at Gui@Viewer::isSeekValuePercentage(void) const
++{
++  return PRIVATE(this)->seekdistanceabs ? FALSE : TRUE;
++}
++
++// ************************************************************************
++
++/*!  
++  This method can be overridden in subclasses if the final
++  orientation of the camera after a seek should be something other
++  than what is computed in So at Gui@Viewer::seekToPoint(const SbVec3f &
++  scenepos)
++ */
++void
++So at Gui@Viewer::computeSeekFinalOrientation(void)
++{
++  
++}
++
++// *************************************************************************
++
++/*!
++  If the current camera is of perspective type, switch to
++  orthographic, and vice versa.
++
++  Automatically calls So at Gui@Viewer::setCameraType() so the change
++  will immediately take place.
++*/
++void
++So at Gui@Viewer::toggleCameraType(void)
++{
++  SoType perspectivetype = SoPerspectiveCamera::getClassTypeId();
++  SoType orthotype = SoOrthographicCamera::getClassTypeId();
++  this->setCameraType(PRIVATE(this)->cameratype.isDerivedFrom(perspectivetype)
++                      ? orthotype : perspectivetype);
++}
++
++// ************************************************************************
++
++/*!
++  Copies the settings of \a camera into our current camera.  Cameras
++  must be of the same class type.
++ */
++void
++So at Gui@Viewer::changeCameraValues(// virtual, protected
++  SoCamera * camera)
++{
++  assert(camera != NULL);
++
++  SoCamera * cam = this->getCamera();
++  if (!cam) {
++    if (SO at GUI@_DEBUG) {
++      SoDebugError::postWarning("So at Gui@Viewer::changeCameraValues",
++                                "no current camera in the scenegraph");
++    }
++    return;
++  }
++  if (cam->getTypeId() != camera->getTypeId()) {
++    if (SO at GUI@_DEBUG) {
++      SoDebugError::postWarning("So at Gui@Viewer::changeCameraValues",
++                                "tried to copy data from camera of "
++                                "different type");
++    }
++    return;
++  }
++
++  cam->copyFieldValues(camera, FALSE);
++}
++
++// *************************************************************************
++
++// doc in super
++void
++So at Gui@Viewer::sizeChanged(const SbVec2s & size)
++{
++  inherited::sizeChanged(size);
++}
++
++// *************************************************************************
++
++// Documented in superclass.
++SbBool
++So at Gui@Viewer::processSoEvent(const SoEvent * const event)
++{
++  const SoType type(event->getTypeId());
++  const SoKeyboardEvent * keyevent = NULL;
++
++  if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
++    keyevent = (SoKeyboardEvent *) event;
++    switch (keyevent->getKey()) {
++    
++    // the ESC key switches between view and interact mode
++    case SoKeyboardEvent::ESCAPE:
++      if (keyevent->getState() == SoButtonEvent::DOWN) {
++        this->setViewing(this->isViewing() ? FALSE : TRUE);
++        return TRUE;
++      }
++      break;
++
++    // Let the end-user toggle between camera-interaction mode
++    // ("viewing") and scenegraph-interaction mode with ALT key(s).
++    case SoKeyboardEvent::LEFT_ALT:
++    case SoKeyboardEvent::RIGHT_ALT:
++      if (!this->isViewing() && (keyevent->getState() == SoButtonEvent::DOWN)) {
++        PRIVATE(this)->altdown = TRUE;
++        this->setViewing(TRUE);
++        return TRUE;
++      }
++      else if (PRIVATE(this)->altdown && (keyevent->getState() == SoButtonEvent::UP)) {
++        this->setViewing(FALSE);
++        PRIVATE(this)->altdown = FALSE;
++        return TRUE;
++      }
++      break;
++    default:
++      break;
++    }
++  }
++
++  // If not viewing, break off further handling and pass the event on
++  // to the So at Gui@RenderArea, which will pass it on to the
++  // scenegraph.
++  if (!this->isViewing()) { return inherited::processSoEvent(event); }
++
++
++  if (keyevent && (keyevent->getState() == SoButtonEvent::DOWN)) {
++    switch (keyevent->getKey()) {
++    case SoKeyboardEvent::S:
++      this->setSeekMode(this->isSeekMode() ? FALSE : TRUE);
++      return TRUE;
++    case SoKeyboardEvent::HOME:
++      this->resetToHomePosition();
++      return TRUE;
++    case SoKeyboardEvent::LEFT_ARROW:
++      PRIVATE(this)->moveCameraScreen(SbVec2f(-0.1f, 0.0f));
++      return TRUE;
++    case SoKeyboardEvent::UP_ARROW:
++      PRIVATE(this)->moveCameraScreen(SbVec2f(0.0f, 0.1f));
++      return TRUE;
++    case SoKeyboardEvent::RIGHT_ARROW:
++      PRIVATE(this)->moveCameraScreen(SbVec2f(0.1f, 0.0f));
++      return TRUE;
++    case SoKeyboardEvent::DOWN_ARROW:
++      PRIVATE(this)->moveCameraScreen(SbVec2f(0.0f, -0.1f));
++      return TRUE;
++    default:
++      break;
++    }
++  }
++
++  if (this->isSeekMode()) {
++    if (type.isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) {
++      SoMouseButtonEvent * const e = (SoMouseButtonEvent *) event;
++      if (e->getButton() == SoMouseButtonEvent::BUTTON1) {
++        if (e->getState() == SoButtonEvent::DOWN) {
++          this->seekToPoint(e->getPosition());
++        }
++        else {
++          // We got an LMB UP-event while in seek-mode, and we just
++          // swallow the event.
++        }
++        return TRUE;
++      }
++    }
++  }
++
++  return FALSE;
++}
++
++// *************************************************************************
++
++/*!
++  This method is for setting up a superimposed scene graph on top
++  of the viewer scene graph.  It will be used for adding spin-rotation
++  coordinate systems, fly-viewer speed indicators and similar things.
++
++  This method is not part of the original InventorXt API.
++*/
++
++void
++So at Gui@Viewer::addSuperimposition(SoNode * scene)
++{
++  if (PRIVATE(this)->superimpositions == NULL)
++    PRIVATE(this)->superimpositions = new SbPList;
++  assert(scene != NULL);
++  scene->ref();
++  PRIVATE(this)->searchaction->reset();
++  PRIVATE(this)->searchaction->setType(SoCamera::getClassTypeId());
++  PRIVATE(this)->searchaction->setInterest(SoSearchAction::FIRST);
++  PRIVATE(this)->searchaction->apply(scene);
++  if (PRIVATE(this)->searchaction->getPath() == NULL) {
++    // FIXME: set up default environment if there is no camera in the
++    // superimposition scene - or not...
++    if (SO at GUI@_DEBUG) {
++      SoDebugError::postInfo("So at Gui@Viewer::addSuperimposition",
++                             "cameraless superimpositions are not "
++                             "supported");
++    }
++    scene->unrefNoDelete();
++    return;
++  }
++  PRIVATE(this)->superimpositions->append(scene);
++  PRIVATE(this)->superimpositionsenabled.append(TRUE);
++}
++
++// *************************************************************************
++
++/*!
++  This method is not part of the original InventorXt API.
++*/
++
++void
++So at Gui@Viewer::removeSuperimposition(SoNode * scene)
++{
++  assert(scene);
++  int idx = -1;
++  if (PRIVATE(this)->superimpositions == NULL) goto error;
++  idx = PRIVATE(this)->superimpositions->find(scene);
++  if (idx == -1) goto error;
++  assert(PRIVATE(this)->superimpositions != NULL);
++  PRIVATE(this)->superimpositions->remove(idx);
++  PRIVATE(this)->superimpositionsenabled.remove(idx);
++  scene->unref();
++  return;
++
++ error:
++  if (SO at GUI@_DEBUG) {
++    SoDebugError::post("So at Gui@Viewer::removeSuperimposition",
++                       "no such superimposition");
++  }
++  return;
++}
++
++// *************************************************************************
++
++/*!
++  This method sets whether the superimposed scene graph should be traversed
++  or not.
++
++  This method is not part of the original InventorXt API.
++*/
++
++void
++So at Gui@Viewer::setSuperimpositionEnabled(SoNode * scene,
++                                         const SbBool enable)
++{
++  int idx = -1;
++  if (PRIVATE(this)->superimpositions == NULL) goto error;
++  idx = PRIVATE(this)->superimpositions->find(scene);
++  if (idx == -1) goto error;
++  PRIVATE(this)->superimpositionsenabled[idx] = enable;
++  return;
++
++ error:
++  if (SO at GUI@_DEBUG) {
++    SoDebugError::post("So at Gui@Viewer::setSuperimpositionEnabled",
++                       "no such superimposition");
++  }
++  return;
++}
++
++// *************************************************************************
++
++/*!
++  This method returns whether the superimposed scene is rendered or not.
++
++  This method is not part of the original InventorXt API.
++*/
++
++SbBool
++So at Gui@Viewer::getSuperimpositionEnabled(SoNode * scene) const
++{
++  int idx = -1;
++  if (PRIVATE(this)->superimpositions == NULL) goto error;
++  idx = PRIVATE(this)->superimpositions->find(scene);
++  if (idx == -1) goto error;
++  return PRIVATE(this)->superimpositionsenabled[idx];
++
++ error:
++  if (SO at GUI@_DEBUG) {
++    SoDebugError::post("So at Gui@Viewer::getSuperimpositionEnabled",
++                       "no such superimposition");
++  }
++  return FALSE;
++}
++
++// *************************************************************************
++
++#undef PRIVATE
++#undef PUBLIC
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiViewer.h.in
+@@ -0,0 +1,244 @@
++#ifndef SO at GUI@_VIEWER_H
++#define SO at GUI@_VIEWER_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/**************************************************************************\
++ * 
++ *  A WORD OF ADVICE
++ *
++ *  It is fruitless to modify the contents of the So at Gui@Viewer.h file
++ *  because it is autogenerated by configure from the SoAnyViewer.h.in 
++ *  file which you will find in the src/Inventor/@Gui@/common/ directory.
++ *  Do your modifications to that file instead.
++ *  
++\**************************************************************************/
++
++// Include this first, as a workaround for building on top of SGI and
++// TGS Inventor on some Linux distributions. (The bug is in SGI/TGS
++// Inventor.)
++#include <math.h>
++
++#include <Inventor/SbTime.h>
++#include <Inventor/SoType.h>
++#include <Inventor/SbLinear.h>
++
++#include <Inventor/@Gui@/So at Gui@RenderArea.h>
++
++#ifndef SO at GUI@_INTERNAL
++#include <Inventor/events/SoKeyboardEvent.h>
++#endif // SO at GUI@_INTERNAL
++
++class SoCallbackList;
++class SoBaseColor;
++class SoCamera;
++class SoComplexity;
++class SoDirectionalLight;
++class SoDrawStyle;
++class SoGetBoundingBoxAction;
++class SoGroup;
++class SoLightModel;
++class SoMaterialBinding;
++class SoNode;
++class SoPolygonOffset;
++class SoSensor;
++class SoSeparator;
++class SoSwitch;
++class SoTimerSensor;
++
++class So at Gui@Viewer;
++
++typedef void So at Gui@ViewerCB(void * data, So at Gui@Viewer * viewer);
++typedef void So at Gui@ViewerFPSCB(float fps, void * data, So at Gui@Viewer * viewer);
++
++typedef SbVec2f So at Gui@AutoClippingCB(void * data, const SbVec2f & nearfar);
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@Viewer : public So at Gui@RenderArea {
++  SO at GUI@_OBJECT_ABSTRACT_HEADER(So at Gui@Viewer, So at Gui@RenderArea);
++
++public:
++  enum Type {
++    BROWSER,
++    EDITOR
++  };
++
++  enum DrawStyle {
++    VIEW_AS_IS,
++    VIEW_HIDDEN_LINE,
++    VIEW_NO_TEXTURE,
++    VIEW_LOW_COMPLEXITY,
++    VIEW_LINE,
++    VIEW_POINT,
++    VIEW_BBOX,
++    VIEW_LOW_RES_LINE,
++    VIEW_LOW_RES_POINT,
++    VIEW_SAME_AS_STILL,
++    VIEW_WIREFRAME_OVERLAY
++  };
++
++  enum DrawType {
++    STILL = 0,
++    INTERACTIVE
++  };
++
++  enum BufferType {
++    BUFFER_SINGLE,
++    BUFFER_DOUBLE,
++    BUFFER_INTERACTIVE
++  };
++
++  enum AutoClippingStrategy {
++    VARIABLE_NEAR_PLANE,
++    CONSTANT_NEAR_PLANE
++  };
++
++  virtual void setCamera(SoCamera * camera);
++  SoCamera * getCamera(void) const;
++
++  virtual void setCameraType(SoType type);
++  SoType getCameraType(void) const;
++
++  virtual void toggleCameraType(void);
++
++  virtual void viewAll(void);
++
++  virtual void saveHomePosition(void);
++  virtual void resetToHomePosition(void);
++
++  virtual void setHeadlight(SbBool enable);
++  SbBool isHeadlight(void) const;
++  SoDirectionalLight * getHeadlight(void) const;
++
++  virtual void setDrawStyle(So at Gui@Viewer::DrawType type, So at Gui@Viewer::DrawStyle style);
++  So at Gui@Viewer::DrawStyle getDrawStyle(const So at Gui@Viewer::DrawType type) const;
++
++  virtual void setBufferingType(So at Gui@Viewer::BufferType type);
++  So at Gui@Viewer::BufferType getBufferingType(void) const;
++
++  virtual void setViewing(SbBool enable);
++  SbBool isViewing(void) const;
++
++  virtual void setCursorEnabled(SbBool enable);
++  SbBool isCursorEnabled(void) const;
++
++  void setAutoClipping(SbBool enable);
++  SbBool isAutoClipping(void) const;
++
++  void setAutoClippingStrategy(const AutoClippingStrategy strategy,
++                               const float value = 0.6f,
++                               So at Gui@AutoClippingCB * cb = NULL,
++                               void * cbuserdata = NULL);
++
++  virtual void setStereoViewing(SbBool enable);
++  SbBool isStereoViewing(void) const;
++
++  virtual void setStereoOffset(const float dist);
++  float getStereoOffset(void) const;
++
++  enum StereoType {
++    STEREO_NONE, STEREO_ANAGLYPH, STEREO_QUADBUFFER,
++    STEREO_INTERLEAVED_ROWS, STEREO_INTERLEAVED_COLUMNS
++  };
++
++  SbBool setStereoType(So at Gui@Viewer::StereoType s);
++  So at Gui@Viewer::StereoType getStereoType(void) const;
++
++  void setAnaglyphStereoColorMasks(const SbBool left[3], const SbBool right[3]);
++  void getAnaglyphStereoColorMasks(SbBool left[3], SbBool right[3]);
++
++  void setDetailSeek(const SbBool enable);
++  SbBool isDetailSeek(void) const;
++
++  void setSeekTime(const float seconds);
++  float getSeekTime(void) const;
++
++  void addStartCallback(So at Gui@ViewerCB * func, void * data = NULL);
++  void addFinishCallback(So at Gui@ViewerCB * func, void * data = NULL);
++  void removeStartCallback(So at Gui@ViewerCB * func, void * data = NULL);
++  void removeFinishCallback(So at Gui@ViewerCB * func, void * data = NULL);
++
++  void setWireframeOverlayColor(const SbColor & color);
++  const SbColor & getWireframeOverlayColor(void) const;
++
++  virtual void setDoubleBuffer(const SbBool enable);
++
++  virtual void setSceneGraph(SoNode * root);
++  virtual SoNode * getSceneGraph(void);
++
++protected:
++  So at Gui@Viewer(@WIDGET@ parent,
++                const char * name,
++                SbBool embed,
++                Type type,
++                SbBool build);
++  ~So at Gui@Viewer();
++
++  virtual void sizeChanged(const SbVec2s & size);
++  virtual void setSeekMode(SbBool enable);
++  SbBool isSeekMode(void) const;
++  SbBool seekToPoint(const SbVec2s screenpos);
++  void seekToPoint(const SbVec3f & scenepos);
++  virtual void computeSeekFinalOrientation(void);
++
++  virtual void actualRedraw(void);
++  virtual SbBool processSoEvent(const SoEvent * const event);
++
++  void interactiveCountInc(void);
++  void interactiveCountDec(void);
++  int getInteractiveCount(void) const;
++
++  void setSeekDistance(const float distance);
++  float getSeekDistance(void) const;
++  void setSeekValueAsPercentage(const SbBool on);
++  SbBool isSeekValuePercentage(void) const;
++
++  virtual void changeCameraValues(SoCamera * camera);
++
++  void addSuperimposition(SoNode * scene);
++  void removeSuperimposition(SoNode * scene);
++  void setSuperimpositionEnabled(SoNode * scene, const SbBool enable);
++  SbBool getSuperimpositionEnabled(SoNode * scene) const;
++
++private:
++  class So at Gui@ViewerP * pimpl;
++  friend class So at Gui@ViewerP;
++  friend class So at Gui@PlaneViewer;
++};
++
++// *************************************************************************
++
++#endif // ! SO at GUI@_VIEWER_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiViewerP.h.in
+@@ -0,0 +1,205 @@
++#ifndef SOGUIVIEWERP_H
++#define SOGUIVIEWERP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/SbRotation.h>
++#include <Inventor/SbVec3f.h>
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/@Gui@/common/gl.h>
++#include <Inventor/@Gui@/common/SbGuiList.h>
++#include <Inventor/@Gui@/viewers/So at Gui@Viewer.h>
++
++class SoSeparator;
++class SoCamera;
++class SoOrthographicCamera;
++class SoPerspectiveCamera;
++class SoGetBoundingBoxAction;
++class SoNode;
++class SoTimerSensor;
++class SoDirectionalLight;
++class SoSwitch;
++class SoBaseColor;
++class SoDrawStyle;
++class SoLightModel;
++class SoMaterialBinding;
++class SoPolygonOffset;
++class SoComplexity;
++class SoSearchAction;
++class SoGetMatrixAction;
++class SoAlarmSensor;
++
++class So at Gui@ViewerP {
++public:
++  So at Gui@ViewerP(So at Gui@Viewer * publ);
++  ~So at Gui@ViewerP(void);
++
++  SoSeparator * createSuperScene(void);
++
++  static void convertOrtho2Perspective(const SoOrthographicCamera * in,
++                                       SoPerspectiveCamera * out);
++  static void convertPerspective2Ortho(const SoPerspectiveCamera * in,
++                                       SoOrthographicCamera * out);
++
++  SoCamera * camera;
++  So at Gui@Viewer::Type type;
++  SbBool viewingflag;
++  SbBool altdown;
++  SoGetBoundingBoxAction * autoclipbboxaction;
++  SoSeparator * sceneroot;
++  SoNode * scenegraph;
++
++
++  // Seek functionality
++  SoTimerSensor * seeksensor;
++  float seekperiod;
++  SbBool inseekmode;
++  SbBool seektopoint;
++  SbVec3f camerastartposition, cameraendposition;
++  SbRotation camerastartorient, cameraendorient;
++  float seekdistance;
++  SbBool seekdistanceabs;
++
++  // Home position storage.
++  SoNode * storedcamera;
++
++  SoDirectionalLight * headlight;
++
++  // Drawstyles
++  So at Gui@Viewer::DrawStyle drawstyles[2];
++  SoSwitch * drawstyleroot, * hiddenlineroot, * polygonoffsetparent;
++  SoBaseColor * sobasecolor;
++  SoComplexity * socomplexity;
++  SoDrawStyle * sodrawstyle;
++  SoLightModel * solightmodel;
++  SoMaterialBinding * somaterialbinding;
++  SoSeparator * usersceneroot;
++  SoSwitch * superimpositionroot;
++#ifdef HAVE_SOPOLYGONOFFSET
++  SoPolygonOffset * sopolygonoffset;
++#endif // HAVE_SOPOLYGONOFFSET
++  // Automatic setting of clipping planes
++  SbBool adjustclipplanes;
++
++  // Keep track of the frames-per-second counter.
++  // Const value trick for old compilers.
++  enum Constants { FRAMESARRAY_SIZE = 100 };
++  SbVec2f frames[FRAMESARRAY_SIZE];
++  float totalcoin, totaldraw;
++  double lastgettimeofday;
++  int framecount;
++  
++  // Stereo-related
++  SbBool stereoviewing, stereotypesetexplicit;
++  float stereooffset;
++  So at Gui@Viewer::StereoType stereotype;
++  SbBool stereoanaglyphmask[2][3];
++  SbViewportRegion stereostencilmaskvp;
++  GLubyte * stereostencilmask;
++  enum StencilType { ROWS, COLUMNS, NONE };
++  So at Gui@Viewer::StereoType stereostenciltype;
++  enum Eye { LEFT, RIGHT, RESTORE };
++  struct StereoData {
++    SbVec3f camerapos, cameradir, offsetvec, focalpoint;
++    SbRotation camerarot;
++    float offset;
++    SbBool nodenotify, positionnotify, orientationnotify;
++  };
++  void setStereoEye(SoCamera * camera,
++                    const So at Gui@ViewerP::Eye eye,
++                    So at Gui@ViewerP::StereoData & storage) const;
++  void initStencilBufferForInterleavedStereo(void);
++
++  // Misc
++  SoType cameratype;
++  SbBool cursoron, localsetbuffertype;
++  SoCallbackList * interactionstartCallbacks, * interactionendCallbacks;
++  int interactionnesting;
++  So at Gui@Viewer::BufferType buffertype;
++  SbColor wireframeoverlaycolor;
++
++  void reallyRedraw(const SbBool clearcol, const SbBool clearz = TRUE);
++
++  // Seek functionality
++  static void seeksensorCB(void * data, SoSensor *);
++
++  // Drawstyles
++  void changeDrawStyle(So at Gui@Viewer::DrawStyle style);
++  SbBool drawInteractiveAsStill(void) const;
++  SbBool drawAsHiddenLine(void) const;
++  SbBool drawAsWireframeOverlay(void) const;
++  So at Gui@Viewer::DrawStyle currentDrawStyle(void) const;
++
++  // Automatic setting of clipping planes
++  void setClippingPlanes(void);
++
++  // Methods to keep track of frames-per-second value.
++  void resetFrameCounter(void);
++  SbVec2f addFrametime(const double ft);
++  void recordFPS(const double rendertime);
++
++  // Misc
++  static void interactivestartCB(void *, So at Gui@Viewer * thisp);
++  static void interactiveendCB(void *, So at Gui@Viewer * thisp);
++  void moveCameraScreen(const SbVec2f & screenpos);
++  void getCameraCoordinateSystem(SoCamera * camera, SoNode * root,
++                                 SbMatrix & matrix, SbMatrix & inverse);
++
++  SoGroup * getParentOfNode(SoNode * root, SoNode * node) const;
++  SoSearchAction * searchaction;
++
++  SoGetMatrixAction * matrixaction;
++  SbPList * superimpositions;
++  SbGuiList<SbBool> superimpositionsenabled;
++  So at Gui@Viewer * pub;
++
++  // auto clipping parameters
++  So at Gui@Viewer::AutoClippingStrategy autoclipstrategy;
++  float autoclipvalue;
++  So at Gui@AutoClippingCB * autoclipcb;
++  void * autoclipuserdata;
++
++  SoAlarmSensor * redrawalarm;
++};
++
++#endif // SOGUIVIEWERP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiWalkViewer.cpp.in
+@@ -0,0 +1,118 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// This file contains the generic, "templatize-able" parts of the
++// So*WalkViewer sourcecode.
++
++// *************************************************************************
++
++/*!
++  \class So at Gui@WalkViewer Inventor/@Gui@/viewers/So at Gui@WalkViewer.h
++  \brief The So at Gui@WalkViewer class is a viewer for moving about in "walk"-like style.
++  \ingroup components viewers
++
++  This is a viewer suitable for architectural-type walk-throughs, for
++  instance.
++
++  FIXME: more class doc
++*/
++
++// *************************************************************************
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/@Gui@/viewers/So at Gui@WalkViewer.h>
++#include <Inventor/@Gui@/viewers/SoGuiWalkViewerP.h>
++#include <Inventor/SbLinear.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/nodes/SoCamera.h>
++#include <assert.h>
++#include <so at gui@defs.h>
++
++#define PRIVATE(ptr) ptr->pimpl
++#define PUBLIC(ptr) ptr->pub
++
++#ifndef DOXYGEN_SKIP_THIS
++
++SoGuiWalkViewerP::SoGuiWalkViewerP(So at Gui@WalkViewer * publ)
++{
++  PUBLIC(this) = publ;
++}
++
++SoGuiWalkViewerP::~SoGuiWalkViewerP()
++{
++}
++
++// This method dollies the camera back and forth in the scene.
++void
++SoGuiWalkViewerP::dollyCamera(const float delta) const
++{
++  SoCamera * const camera = PUBLIC(this)->getCamera();
++  if (camera == NULL) { return; } // if there's no scenegraph, for instance
++
++  SbPlane walkplane(PUBLIC(this)->getUpDirection(), camera->position.getValue());
++  SbVec3f campos = camera->position.getValue();
++  SbVec3f camvec;
++  camera->orientation.getValue().multVec(SbVec3f(0, 0, -1), camvec);
++  SbLine cross(campos + camvec,
++                campos + camvec + PUBLIC(this)->getUpDirection());
++  SbVec3f intersect;
++  walkplane.intersect(cross, intersect);
++  SbVec3f dir = intersect - campos;
++  dir.normalize();
++
++  camera->position = campos - dir * delta;
++}
++
++// This method elevates the camera up and down.
++void
++SoGuiWalkViewerP::elevateCamera(const float delta) const
++{
++  SoCamera * const camera = PUBLIC(this)->getCamera();
++  if (camera == NULL) { return; } // if there's no scenegraph, for instance
++
++  SbVec3f up = PUBLIC(this)->getUpDirection();
++  up.normalize();
++  camera->position = camera->position.getValue() - up * delta;
++}
++
++#endif // DOXYGEN_SKIP_THIS
++
++// *************************************************************************
++
++#undef PRIVATE
++#undef PUBLIC
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiWalkViewer.h.in
+@@ -0,0 +1,113 @@
++#ifndef SO at GUI@_WALKVIEWER_H
++#define SO at GUI@_WALKVIEWER_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.h>
++
++class SO at GUI@_DLL_API So at Gui@WalkViewer : public So at Gui@ConstrainedViewer {
++  SO at GUI@_OBJECT_HEADER(So at Gui@WalkViewer, So at Gui@ConstrainedViewer);
++
++public:
++  So at Gui@WalkViewer(@WIDGET@ parent = NULL,
++                    const char * name = NULL,
++                    SbBool embed = TRUE,
++                    So at Gui@FullViewer::BuildFlag flag = BUILD_ALL,
++                    So at Gui@Viewer::Type type = BROWSER);
++  ~So at Gui@WalkViewer();
++
++  virtual void setViewing(SbBool enable);
++  virtual void setCamera(SoCamera * camera);
++  virtual void setCursorEnabled(SbBool enable);
++
++  virtual void setCameraType(SoType type);
++
++protected:
++  So at Gui@WalkViewer(@WIDGET@ parent,
++                    const char * name,
++                    SbBool embed,
++                    So at Gui@FullViewer::BuildFlag flag,
++                    So at Gui@Viewer::Type type,
++                    SbBool build);
++
++  virtual const char * getDefaultWidgetName(void) const;
++  virtual const char * getDefaultTitle(void) const;
++  virtual const char * getDefaultIconTitle(void) const;
++
++  virtual void processEvent(@EVENT@ event);
++
++  virtual void setSeekMode(SbBool enable);
++  virtual void actualRedraw(void);
++
++  virtual void rightWheelMotion(float value);
++
++  virtual @WIDGET@ buildLeftTrim(@WIDGET@ parent);
++
++private:
++  class So at Gui@WalkViewerP * pimpl;
++  friend class SoGuiWalkViewerP;
++  friend class So at Gui@WalkViewerP;
++
++/// FIXME!: merge the So*WalkViewer.h parts in properly. 20020109 mortene. ////
++
++#ifdef __COIN_SOXT__
++protected:
++  virtual void leftWheel2Start(void);
++  virtual void leftWheel2Motion(float value);
++  virtual void leftWheel2Finish(void);
++  float getLeftWheel2Value(void) const;
++  void setLeftWheel2String(char * string);
++
++private:
++  void constructor(SbBool build);
++
++  Widget heightwheel;
++  float heightvalue;
++
++  void wheelarmed(void);
++  static void wheelarmedCB(Widget, XtPointer, XtPointer);
++  void wheelchanged(float value);
++  static void wheelchangedCB(Widget, XtPointer, XtPointer);
++  void wheeldisarmed(void);
++  static void wheeldisarmedCB(Widget, XtPointer, XtPointer);
++#endif // ! __COIN_SOXT__
++
++#ifdef __COIN_SOGTK__
++private:
++  void constructor(const SbBool build);
++#endif // ! __COIN_SOGTK__
++};
++
++#endif // ! SO at GUI@_WALKVIEWER_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiWalkViewerP.h.in
+@@ -0,0 +1,64 @@
++#ifndef SOGUIWALKVIEWERP_H
++#define SOGUIWALKVIEWERP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++class So at Gui@WalkViewer;
++
++// ************************************************************************
++
++// This class contains private data and methods used within the
++// SoGuiWalkViewer class.
++
++class SoGuiWalkViewerP
++{
++public:
++  ~SoGuiWalkViewerP();
++
++  void dollyCamera(const float change) const;
++  void elevateCamera(const float change) const;
++
++protected:
++  SoGuiWalkViewerP(So at Gui@WalkViewer * publ);
++  So at Gui@WalkViewer * pub;
++};
++
++// ************************************************************************
++
++#endif // ! SOGUIWALKVIEWERP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/killed-prefs.diff
+@@ -0,0 +1,355 @@
++This file contains the big diff resulting when killing off all the
++common template code for handling the preference sheet. It has been
++added to the CVS repository in case someone (important) loudly
++complains about me ripping out the prefsheet support.
++
++The native toolkit specific diff can be found in
++src/Inventor/@Gui@/viewers/.
++
++20020606 mortene.
++
++
++Index: SoGuiExaminerViewer.cpp.in
++===================================================================
++RCS file: /export/cvsroot/SoGUI/viewers/SoGuiExaminerViewer.cpp.in,v
++retrieving revision 1.17
++diff -u -w -r1.17 SoGuiExaminerViewer.cpp.in
++--- SoGuiExaminerViewer.cpp.in	6 Jun 2002 13:01:12 -0000	1.17
+++++ SoGuiExaminerViewer.cpp.in	6 Jun 2002 15:50:30 -0000
++@@ -1108,8 +1108,8 @@
++ // *************************************************************************
++ 
++ // Documented in superclass. Overrides this method to be able to draw
++-// the axis cross if selected in the preferences sheet, and to keep a
++-// continuous animation upon spin.
+++// the axis cross, if selected, and to keep a continuous animation
+++// upon spin.
++ void
++ So at Gui@ExaminerViewer::actualRedraw(void)
++ {
++Index: SoGuiExaminerViewer.h.in
++===================================================================
++RCS file: /export/cvsroot/SoGUI/viewers/SoGuiExaminerViewer.h.in,v
++retrieving revision 1.17
++diff -u -w -r1.17 SoGuiExaminerViewer.h.in
++--- SoGuiExaminerViewer.h.in	3 Jun 2002 19:28:18 -0000	1.17
+++++ SoGuiExaminerViewer.h.in	6 Jun 2002 15:50:30 -0000
++@@ -75,7 +75,6 @@
++   virtual void bottomWheelMotion(float val);
++   virtual void rightWheelMotion(float val);
++ 
++-  virtual @WIDGET@ makeSubPreferences(@WIDGET@ parent);
++   virtual void createViewerButtons(@WIDGET@ parent, SbPList * buttonlist);
++ 
++   virtual const char * getDefaultWidgetName(void) const;
++@@ -89,7 +88,6 @@
++   virtual void actualRedraw(void);
++ 
++   virtual void afterRealizeHook(void);
++-  virtual void createPrefSheet(void);
++ 
++ private:
++   class So at Gui@ExaminerViewerP * pimpl;
++Index: SoGuiFlyViewer.cpp.in
++===================================================================
++RCS file: /export/cvsroot/SoGUI/viewers/SoGuiFlyViewer.cpp.in,v
++retrieving revision 1.14
++diff -u -w -r1.14 SoGuiFlyViewer.cpp.in
++--- SoGuiFlyViewer.cpp.in	6 Jun 2002 12:40:23 -0000	1.14
+++++ SoGuiFlyViewer.cpp.in	6 Jun 2002 15:50:30 -0000
++@@ -1042,17 +1042,6 @@
++ 
++ // ************************************************************************
++ 
++-/*!
++-  FIXME: doc
++- */
++-void
++-So at Gui@FlyViewer::createPrefSheet(void)
++-{
++-  SO at GUI@_STUB();
++-}
++-
++-// ************************************************************************
++-
++ // doc in super
++ void
++ So at Gui@FlyViewer::openViewerHelpCard(void)
++@@ -1071,22 +1060,3 @@
++ }
++ 
++ // ************************************************************************
++-
++-// FIXME: this code is "left over" after we migrated to a common
++-// code-base in SoGuiFlyViewer.cpp.in. Fix up and re-enable. 20011209 mortene.
++-
++-//  void
++-//  SoXtFlyViewer::createPrefSheet(void)
++-//  {
++-//    if (! this->prefshell) {
++-//      this->prefparts = new Widget [ 16 ];
++-//      this->createPrefSheetShellAndForm(this->prefshell, this->prefsheet);
++-//      this->createDefaultPrefSheetParts(this->prefparts, this->numprefparts,
++-//        this->prefsheet);
++-//      this->prefparts[this->numprefparts] =
++-//        this->createFramedSpeedPrefSheetGuts(this->prefsheet);
++-//      if (this->prefparts[this->numprefparts] != NULL) this->numprefparts++;
++-//    }
++-//    this->layoutPartsAndMapPrefSheet(this->prefparts, this->numprefparts,
++-//      this->prefsheet, this->prefshell);
++-//  }
++Index: SoGuiFlyViewer.h.in
++===================================================================
++RCS file: /export/cvsroot/SoGUI/viewers/SoGuiFlyViewer.h.in,v
++retrieving revision 1.4
++diff -u -w -r1.4 SoGuiFlyViewer.h.in
++--- SoGuiFlyViewer.h.in	4 Jun 2002 15:16:11 -0000	1.4
+++++ SoGuiFlyViewer.h.in	6 Jun 2002 15:50:30 -0000
++@@ -66,7 +66,6 @@
++ 
++   virtual void rightWheelMotion(float value);
++ 
++-  virtual void createPrefSheet(void);
++   virtual void openViewerHelpCard(void);
++ 
++   virtual void afterRealizeHook(void);
++Index: SoGuiFullViewer.cpp.in
++===================================================================
++RCS file: /export/cvsroot/SoGUI/viewers/SoGuiFullViewer.cpp.in,v
++retrieving revision 1.18
++diff -u -w -r1.18 SoGuiFullViewer.cpp.in
++--- SoGuiFullViewer.cpp.in	6 Jun 2002 13:01:12 -0000	1.18
+++++ SoGuiFullViewer.cpp.in	6 Jun 2002 15:50:30 -0000
++@@ -105,31 +105,6 @@
++ 
++ // ************************************************************************
++ 
++-// Note: common documentation for all subclasses aswell.
++-/*!
++-  \fn void So at Gui@FullViewer::createPrefSheet(void)
++-
++-  Create preferences sheet.
++-
++-  This is a hook for constructing the preferences window in the
++-  derived viewer classes.
++-
++-  Basically, derived classes will do the following in this method:
++-
++-  \code
++-    if (! this->prefshell) {
++-      createPrefSheetShellAndForm(this->prefshell, this->prefsheet);
++-      createDefaultPrefSheetParts(this->prefparts, this->numprefparts,
++-        this->prefsheet);
++-      // add parts specific for derived viewer
++-    }
++-    layoutPartsAndMapPrefSheet(this->prefparts, this->numprefparts,
++-                               this->prefsheet, this->prefshell);
++-  \endcode
++-*/
++-
++-// ************************************************************************
++-
++ // Note: the following function documentation blocks for thumbwheel
++ // handling will also be used for all the miscellaneous viewer
++ // subclasses, so keep'em general.
++@@ -499,8 +474,6 @@
++   menu->setMenuItemTitle(HEADLIGHT_ITEM, _("Headlight"));
++   menu->newMenuItem("fullscreen", FULLSCREEN_ITEM);
++   menu->setMenuItemTitle(FULLSCREEN_ITEM, _("Fullscreen"));
++-  menu->newMenuItem("preferences", PREFERENCES_ITEM);
++-  menu->setMenuItemTitle(PREFERENCES_ITEM, _("Preferences..."));
++ 
++   menu->addMenu(ROOT_MENU, FUNCTIONS_MENU);
++   menu->addMenu(ROOT_MENU, DRAWSTYLES_MENU);
++@@ -509,8 +482,6 @@
++   menu->addMenuItem(ROOT_MENU, DECORATION_ITEM);
++   menu->addMenuItem(ROOT_MENU, HEADLIGHT_ITEM);
++   menu->addMenuItem(ROOT_MENU, FULLSCREEN_ITEM);
++-  menu->addSeparator(ROOT_MENU);
++-  menu->addMenuItem(ROOT_MENU, PREFERENCES_ITEM);
++ 
++   menu->newMenuItem("help", HELP_ITEM);
++   menu->setMenuItemTitle(HELP_ITEM, _("Help"));
++@@ -812,9 +783,6 @@
++   case FULLSCREEN_ITEM:
++     (void)PUBLIC(this)->setFullScreen(PUBLIC(this)->isFullScreen() ? FALSE : TRUE);
++     break;
++-  case PREFERENCES_ITEM:
++-    ((So at Gui@FullViewerP *)this)->selectedPrefs();
++-    break;
++ 
++   case HELP_ITEM:
++     PUBLIC(this)->openViewerHelpCard();
++Index: SoGuiFullViewer.h.in
++===================================================================
++RCS file: /export/cvsroot/SoGUI/viewers/SoGuiFullViewer.h.in,v
++retrieving revision 1.22
++diff -u -w -r1.22 SoGuiFullViewer.h.in
++--- SoGuiFullViewer.h.in	3 Jun 2002 16:27:59 -0000	1.22
+++++ SoGuiFullViewer.h.in	6 Jun 2002 15:50:30 -0000
++@@ -66,7 +66,6 @@
++ 
++   virtual void setViewing(SbBool on);
++   virtual void setCamera(SoCamera * cam);
++-  virtual void hide(void);
++ 
++   virtual void setComponentCursor(const So at Gui@Cursor & cursor);
++ 
++@@ -95,8 +94,6 @@
++   virtual void setPopupMenuString(const char * title);
++   virtual void openPopupMenu(const SbVec2s position);
++ 
++-  void setPrefSheetString(const char * title);
++-
++   virtual void leftWheelStart(void);
++   virtual void leftWheelMotion(float);
++   virtual void leftWheelFinish(void);
++@@ -126,8 +123,6 @@
++ 
++   virtual void openViewerHelpCard(void);
++ 
++-  virtual void createPrefSheet(void);
++-
++ protected:
++   @WIDGET@ leftDecoration;
++   @WIDGET@ rightDecoration;
++@@ -164,9 +159,6 @@
++   @WIDGET@ leftWheel;
++   @WIDGET@ rightWheel;
++   @WIDGET@ bottomWheel;
++-
++-  virtual bool eventFilter(QObject * obj, QEvent * e);
++-  virtual @WIDGET@ makeSubPreferences(@WIDGET@ parent);
++ #endif // __COIN_SOQT__
++ 
++ #ifdef __COIN_SOXT__ // FIXME: get rid of non-templatized code. 20020108 mortene.
++@@ -180,31 +172,9 @@
++   Widget buildFunctionsSubmenu(Widget popup);
++   Widget buildDrawStyleSubmenu(Widget popup);
++ 
++-  char * prefstring;
++   char * popupTitle;
++   SbBool popupEnabled;
++   SbPList * viewerButtonWidgets;
++-
++-  Widget prefshell;
++-  Widget prefsheet;
++-
++-  void createPrefSheetShellAndForm(Widget & shell, Widget & form);
++-  void createDefaultPrefSheetParts(Widget * widgets, int & num, Widget form);
++-  void layoutPartsAndMapPrefSheet(Widget * widgets, int num, Widget form, Widget shell);
++-
++-  Widget createSeekPrefSheetGuts(Widget parent);
++-  Widget createSeekDistPrefSheetGuts(Widget parent);
++-  Widget createZoomPrefSheetGuts(Widget parent);
++-  Widget createClippingPrefSheetGuts(Widget parent);
++-  Widget createStereoPrefSheetGuts(Widget parent);
++-  Widget createSpeedPrefSheetGuts(Widget parent);
++-
++-  Widget createFramedSeekPrefSheetGuts(Widget parent);
++-  Widget createFramedSeekDistPrefSheetGuts(Widget parent);
++-  Widget createFramedZoomPrefSheetGuts(Widget parent);
++-  Widget createFramedClippingPrefSheetGuts(Widget parent);
++-  Widget createFramedStereoPrefSheetGuts(Widget parent);
++-  Widget createFramedSpeedPrefSheetGuts(Widget parent);
++ #endif // __COIN_SOXT__
++ 
++ #ifdef __COIN_SOGTK__ // FIXME: get rid of non-templatized code. 20020108 mortene.
++@@ -212,9 +182,6 @@
++   @WIDGET@ leftWheel;
++   @WIDGET@ rightWheel;
++   @WIDGET@ bottomWheel;
++-
++-  virtual SbBool eventFilter(GtkWidget * object, GdkEvent * event);
++-  virtual GtkWidget * makeSubPreferences(GtkWidget * parent);
++ #endif // __COIN_SOGTK__
++ 
++ #ifdef __COIN_SOWIN__ // FIXME: get rid of non-templatized code. 20020108 mortene.
++@@ -236,21 +203,12 @@
++   virtual LRESULT onMeasureItem(HWND window, UINT message, WPARAM wparam, LPARAM lparam);
++ 
++ 
++-  class SoFieldSensor * zoomSensor;
++-
++   class SoWinThumbWheel * rightWheel;
++   class SoWinThumbWheel * bottomWheel;
++   class SoWinThumbWheel * leftWheel;
++ 
++-  SbVec2f zoomrange;
++-  class SoWinViewerPrefSheet * prefsheet;
++-
++   HWND viewerWidget;
++   HWND renderAreaWidget;
++-
++-  // FIXME: quick hack done while merging all the header file
++-  // definitions for So*FullViewer. 20020111 mortene.
++-  friend class SoWinViewerPrefSheet;
++ 
++ protected:
++   SbPList * viewerButtonList;
++Index: SoGuiFullViewerP.h.in
++===================================================================
++RCS file: /export/cvsroot/SoGUI/viewers/SoGuiFullViewerP.h.in,v
++retrieving revision 1.3
++diff -u -w -r1.3 SoGuiFullViewerP.h.in
++--- SoGuiFullViewerP.h.in	6 Jun 2002 13:01:12 -0000	1.3
+++++ SoGuiFullViewerP.h.in	6 Jun 2002 15:50:30 -0000
++@@ -98,7 +98,6 @@
++       DECORATION_ITEM,
++       HEADLIGHT_ITEM,
++       FULLSCREEN_ITEM,
++-      PREFERENCES_ITEM,
++ 
++       STEREO_MENU,
++       STEREO_OFF_ITEM,
++Index: SoGuiPlaneViewer.h.in
++===================================================================
++RCS file: /export/cvsroot/SoGUI/viewers/SoGuiPlaneViewer.h.in,v
++retrieving revision 1.18
++diff -u -w -r1.18 SoGuiPlaneViewer.h.in
++--- SoGuiPlaneViewer.h.in	15 May 2002 20:29:03 -0000	1.18
+++++ SoGuiPlaneViewer.h.in	6 Jun 2002 15:50:30 -0000
++@@ -73,8 +73,6 @@
++   virtual void rightWheelMotion(float value);
++   virtual void rightWheelFinish(void);
++ 
++-  virtual void createPrefSheet(void);
++-
++   virtual void createViewerButtons(@WIDGET@ parent, SbPList * buttons);
++   virtual void openViewerHelpCard(void);
++ 
++Index: SoGuiWalkViewer.h.in
++===================================================================
++RCS file: /export/cvsroot/SoGUI/viewers/SoGuiWalkViewer.h.in,v
++retrieving revision 1.7
++diff -u -w -r1.7 SoGuiWalkViewer.h.in
++--- SoGuiWalkViewer.h.in	31 May 2002 13:54:11 -0000	1.7
+++++ SoGuiWalkViewer.h.in	6 Jun 2002 15:50:30 -0000
++@@ -64,7 +64,6 @@
++ 
++   virtual @WIDGET@ buildLeftTrim(@WIDGET@ parent);
++ 
++-  virtual void createPrefSheet(void);
++   virtual void openViewerHelpCard(void);
++ 
++ private:
++@@ -85,9 +84,6 @@
++ private:
++   void constructor(SbBool build);
++ 
++-  Widget * prefparts;
++-  int numprefparts;
++-
++   Widget heightwheel;
++   float heightvalue;
++ 
++@@ -100,9 +96,6 @@
++ #endif // ! __COIN_SOXT__
++ 
++ #ifdef __COIN_SOGTK__
++-protected:
++-  virtual GtkWidget * makeSubPreferences(GtkWidget * parent);
++-
++ private:
++   void constructor(const SbBool build);
++ #endif // ! __COIN_SOGTK__
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/widgets/SoAnyThumbWheel.cpp.in
+@@ -0,0 +1,669 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <assert.h>
++#include <math.h>
++#include <stdio.h>
++
++#include <so at gui@defs.h>
++#include <Inventor/@Gui@/So at Gui@Object.h> // for __COIN_SOQT__
++#include <Inventor/@Gui@/widgets/SoAnyThumbWheel.h>
++
++#ifdef __COIN_SOQT__
++#include <qglobal.h> // for Q_WS_MAC
++#endif
++
++#ifndef M_PI
++#define M_PI 3.14159265358979323846f
++#endif // ! M_PI
++
++/*!
++  \class SoAnyThumbWheel SoAnyThumbWheel.h
++  \brief The ThumbWheel class is a helper class for managing thumb wheel
++  GUI widgets.
++  \internal
++*/
++
++/*!
++  \var int SoAnyThumbWheel::dirtyTables
++  If this flag is set, the internal tables needs to be recalculated.
++*/
++
++/*!
++  \var int SoAnyThumbWheel::dirtyVariables
++  If this flag is set, the internal variables that are calculated from the
++  tables and wheel settings need to be recalculated.
++*/
++
++static unsigned int
++int8clamp(float f) {
++  assert(f >= 0.0f);
++  if (f >= 255.0f)
++    return 255;
++  return (unsigned int) floor(f);
++} // int8clamp()
++
++// ************************************************************************
++
++/*!
++  Constructor.
++*/
++
++SoAnyThumbWheel::SoAnyThumbWheel(
++  void)
++: diameter(0)
++, width(0)
++, byteorder(ABGR)
++, boundaryhandling(ACCUMULATE)
++, movement(AUTHENTIC)
++, dirtyTables(1)
++, dirtyVariables(1)
++{
++  assert(sizeof(int) == 4 && "FIXME: use int32 datatype instead");
++
++//  this->disabledred = 1.0f;
++//  this->disabledgreen = 1.0f;
++//  this->disabledblue = 1.0f;
++
++  this->red = 220.0f / 255.0f;
++  this->green = 180.0f / 255.0f;
++  this->blue = 180.0f / 255.0f;
++  
++  this->light = 1.3f;
++  this->front = 1.2f;
++  this->normal = 1.0f;
++  this->shade = 0.8f;
++
++  for (int i = 0; i < NUMTABLES; i++)
++    this->tables[i] = NULL;
++} // SoAnyThumbWheel()
++
++/*!
++  Destructor.
++*/
++
++SoAnyThumbWheel::~SoAnyThumbWheel(
++  void)
++{
++  for (int i = 0; i < NUMTABLES; i++)
++    delete [] this->tables[i];
++} // ~ThumbWheel()
++
++// ************************************************************************
++
++/*!
++*/
++
++void
++SoAnyThumbWheel::setSize(
++  const int diameterarg,
++  const int widtharg)
++{
++  if (this->diameter != diameterarg) {
++    this->dirtyTables = 1;
++    this->dirtyVariables = 1;
++  } else if (this->width != widtharg) {
++    this->dirtyVariables = 1; // embossed squares grows...
++  } else {
++    return;
++  }
++  this->diameter = diameterarg;
++  this->width = widtharg;
++} // setSize()
++
++/*!
++*/
++
++void
++SoAnyThumbWheel::getSize(
++  int & diameterref,
++  int & widthref) const
++{
++  diameterref = this->diameter;
++  widthref = this->width;
++} // getSize()
++
++// ************************************************************************
++
++/*!
++*/
++
++void
++SoAnyThumbWheel::setColor(
++  const float redval,
++  const float greenval,
++  const float blueval)
++{
++  this->red = redval;
++  this->green = greenval;
++  this->blue = blueval;
++} // setColor()
++
++/*!
++*/
++
++void
++SoAnyThumbWheel::getColor(
++  float & redref,
++  float & greenref,
++  float & blueref) const
++{
++  redref = this->red;
++  greenref = this->green;
++  blueref = this->blue;
++} // GetColor()
++
++// ************************************************************************
++
++/*!
++*/
++
++void
++SoAnyThumbWheel::setColorFactors(
++  const float lightval,
++  const float frontval,
++  const float normalval,
++  const float shadeval)
++{
++  this->light = lightval;
++  this->front = frontval;
++  this->normal = normalval;
++  this->shade = shadeval;
++} // setColorFactors()
++
++/*!
++*/
++
++void
++SoAnyThumbWheel::getColorFactors(
++  float & lightref,
++  float & frontref,
++  float & normalref,
++  float & shaderef) const
++{
++  lightref = this->light;
++  frontref = this->front;
++  normalref = this->normal;
++  shaderef = this->shade;
++} // getColorFactors()
++
++// ************************************************************************
++
++/*!
++  This method returns the number of bitmaps required to represent all the
++  possible rotations of the thumb wheel.
++*/
++
++int
++SoAnyThumbWheel::getNumBitmaps(
++  void) const
++{
++  return this->width - 4 + 2 + 1;
++} // getNumBitmaps()
++
++// ************************************************************************
++
++/*!
++  This method draws thumb wheel bitmap \a number. \a direction decides
++  if it should be rendered in the vertical or horizontal position.
++*/
++
++void
++SoAnyThumbWheel::drawBitmap(
++  const int number,
++  void * bitmap,
++  Alignment alignment) const
++{
++  if (number == 0) {
++    drawDisabledWheel(number, bitmap, alignment);
++  } else {
++    drawEnabledWheel(number, bitmap, alignment);
++  }
++}
++
++// ************************************************************************
++
++/*!
++  This method calculates the thumb wheel value based on the users mouse
++  interaction.  origpos and origval is the mouseposition at the moment of
++  pressing the button, and origval is the thumbwheels original value at
++  that point.  deltapos is the number of pixels the mouse has moved since
++  pressing the button.
++  
++  The point in doing it this way is that the thumbwheel can easily be made
++  to behave like an authentic wheel when all of these parameters are known.
++
++  After doing a CalculateValue, you should redraw the wheel if the value has
++  changed (since last time, not compared to origval).
++*/
++
++float
++SoAnyThumbWheel::calculateValue(
++  const float origval,
++  const int origpos,
++  const int deltapos) const
++{
++  this->validate();
++
++//  fprintf(stderr, "calc(%8.4f, %d, %d)\n", origval, origpos, deltapos);
++
++  float diff = 0.0f;
++  switch (this->movement) {
++  case UNIFORM:
++    diff = this->unistep * deltapos;
++    break;
++  case AUTHENTIC:
++    int newpos = origpos + deltapos;
++    if (newpos < 0) newpos = 0;
++    if (newpos >= diameter) newpos = diameter - 1;
++    diff = this->tables[RAD][newpos] - this->tables[RAD][origpos];
++    break;
++  } // switch (this->movement)
++
++  switch (this->boundaryhandling) {
++  case MODULATE:
++    while ((origval + diff) < 0.0f         ) diff += 2.0f * float(M_PI);
++    while ((origval + diff) > (2.0f * float(M_PI))) diff -= 2.0f * float(M_PI);
++    break;
++  case CLAMP:
++    if    ((origval + diff) < 0.0f         ) diff = 0.0f - origval;
++    if    ((origval + diff) > (2.0f * float(M_PI))) diff = (2.0f * float(M_PI)) - origval;
++    break;
++  case ACCUMULATE:
++    // nothing - just add the difference on top of original value
++    break;
++  } // switch (this->boundaryhandling)
++
++  return origval + diff;
++} // calculateValue()
++
++// ************************************************************************
++
++/*!
++  This method returns the bitmap you need to display to represent a thumb
++  wheel with the given value and active state.
++*/
++
++int
++SoAnyThumbWheel::getBitmapForValue(
++  const float value,
++  const State state) const
++{
++  this->validate();
++
++  if (state == DISABLED)
++    return 0; // only one disabled bitmap in this implementation
++
++  double squarerange = (2.0 * M_PI) / this->numsquares;
++  double normalizedmodval = fmod((double) value, squarerange) / squarerange;
++  if (normalizedmodval < 0.0) normalizedmodval += 1.0;
++  int bitmap = 1 + (int) (normalizedmodval * (this->width - 4 + 2));
++  return bitmap;
++} // getBitmapForValue()
++
++// ************************************************************************
++
++/*!
++  This method sets whether to set up uints in ARGB or BGRA mode before
++  storing them in the 32-bit frame buffer.
++*/
++
++void
++SoAnyThumbWheel::setGraphicsByteOrder(
++  const GraphicsByteOrder byteorderval)
++{
++  this->byteorder = byteorderval;
++} // setGraphicsByteOrder()
++
++/*!
++*/
++
++SoAnyThumbWheel::GraphicsByteOrder
++SoAnyThumbWheel::getGraphicsByteOrder(
++  void) const
++{
++  return this->byteorder;
++} // getGraphicsByteOrder()
++
++// ************************************************************************
++
++/*!
++*/
++
++void
++SoAnyThumbWheel::setMovement(
++  const Movement movementval)
++{
++  this->movement = movementval;
++} // setMovement()
++
++/*!
++*/
++
++SoAnyThumbWheel::Movement
++SoAnyThumbWheel::getMovement(
++  void) const
++{
++  return this->movement;
++} // getMovement()
++
++// ************************************************************************
++
++void
++SoAnyThumbWheel::setBoundaryHandling(
++  const BoundaryHandling handling)
++{
++  this->boundaryhandling = handling;
++} // setBoundaryHandling()
++
++/*!
++*/
++
++SoAnyThumbWheel::BoundaryHandling
++SoAnyThumbWheel::getBoundaryHandling(
++  void) const
++{
++  return this->boundaryhandling;
++} // getBoundaryHandling()
++
++// ************************************************************************
++
++/*!
++  This method validates the ThumbWheel object, recalculating the tables and
++  state variables if necessary.  If object is already valid, no calculations
++  are performed.
++*/
++
++void
++SoAnyThumbWheel::validate(// private
++  void) const
++{
++  int i;
++
++  if (this->dirtyTables) {
++    assert(this->dirtyVariables);
++    for (i = 0; i < NUMTABLES; i++) {
++      if (this->tables[i]) delete [] this->tables[i];
++      this->tables[i] = new float [ this->diameter ];
++    }
++
++    float radius = ((float) this->diameter + 1.0f) / 2.0f;
++//    float range = 2.0f * M_PI;
++    float acos0times2 = 2.0f * (float)acos(0.0);
++
++    for (i = 0; i < this->diameter; i++) {
++      if ((float) i <= radius) {
++        this->tables[COS][i] = (radius - (float) i) / radius;
++        this->tables[RAD][i] = (float)acos(this->tables[COS][i]);
++      } else {
++        this->tables[COS][i] = ((float) i - radius) / radius;
++        this->tables[RAD][i] = acos0times2 - (float)acos(this->tables[COS][i]);
++      }
++      this->tables[SIN][i] = (float)sqrt(1.0f - this->tables[COS][i] * this->tables[COS][i]);
++    }
++
++    this->dirtyTables = 0;
++  }
++
++  if (this->dirtyVariables) {
++    assert(this->dirtyTables == 0);
++    if ((this->diameter % 2) == 0)
++      this->unistep = this->tables[RAD][this->diameter/2] -
++                      this->tables[RAD][(this->diameter/2)-1];
++    else
++      this->unistep = (this->tables[RAD][(this->diameter/2)+1] -
++                       this->tables[RAD][(this->diameter/2)-1]) / 2.0f;
++
++    this->squarespacing = 2.0f * this->unistep;
++    this->shadelength = this->unistep; // remove?
++
++    int squares = (int) floor(((2.0f * M_PI) /
++                         ((((float) width - 4.0f) * this->unistep) + this->squarespacing)) + 0.5f);
++    this->numsquares = (float)squares;
++    this->squarelength = (float(2.0 * M_PI) / (float) squares) - this->squarespacing;
++
++    this->dirtyVariables = 0;
++  }
++} // validate()
++
++// ************************************************************************
++
++inline unsigned int
++SoAnyThumbWheel::swapWord(
++  unsigned int orig) const
++{
++  // orig is RGBA
++  unsigned int copy;
++  if (this->byteorder == ABGR) {
++    copy = (orig & 0x000000ff) <<  24;
++    copy |= (orig & 0x0000ff00) << 8;
++    copy |= (orig & 0x00ff0000) >> 8;
++    copy |= (orig & 0xff000000) >> 24;
++  } else if (this->byteorder == ARGB) {
++    copy = orig >> 8;             // RGB
++    // FIXME: QImage::hasAlphaBuffer() is ignored on Qt4 on Mac OS X,
++    // thus we must explicitly set the alpha component to 0xff (opaque).
++    // Bug reported to Trolltech. 20050805 kyrah.
++#if (defined(Q_WS_MAC) && (QT_VERSION >= 0x040000))
++    copy |= 0xff << 24;  // A    
++#else
++    copy |= (orig & 0xff) << 24;  // A    
++#endif
++  } else if (this->byteorder == BGRA) {
++    copy = orig & 0x00ff00ff;          // G & A
++    copy |= (orig & 0x0000ff00) << 16; // B
++    copy |= (orig & 0xff000000) >> 16; // R
++  } else {
++    copy = orig; // ?
++  }
++  return copy;
++} // swapWord()
++
++/*!
++  This method draws a wheel that has been disabled from being rotated.
++*/
++
++void
++SoAnyThumbWheel::drawDisabledWheel(// private
++  const int number,
++  void * bitmap,
++  Alignment alignment) const
++{
++  assert(number == 0);
++
++  this->validate();
++
++  unsigned int * buffer = (unsigned int *) bitmap;
++
++  for (int j = 0; j < this->diameter; j++) {
++    unsigned int lightval, frontval, normalval, shadeval;
++    lightval = int8clamp(255.0f * this->tables[SIN][j] * 1.15f);
++    frontval = 0;
++    normalval = int8clamp(255.0f * this->tables[SIN][j]);
++    shadeval = int8clamp(255.0f * this->tables[SIN][j] * 0.85f);
++
++    // rgbx
++    lightval = (lightval << 24) | (lightval << 16) | (lightval << 8);
++    frontval = (frontval << 24) | (frontval << 16) | (frontval << 8);
++    normalval = (normalval << 24) | (normalval << 16) | (normalval << 8);
++    shadeval = (shadeval << 24) | (shadeval << 16) | (shadeval << 8);
++
++    if (this->byteorder != RGBA) {
++      lightval = this->swapWord(lightval);
++      frontval = this->swapWord(frontval);
++      normalval = this->swapWord(normalval);
++      shadeval = this->swapWord(shadeval);
++    }
++
++    if (alignment == VERTICAL) {
++      buffer[j*this->width] = lightval;
++      for (int i = 1; i < (width - 1); i++)
++        buffer[(j*this->width)+i] = normalval;
++      buffer[(j*this->width)+(this->width-1)] = shadeval;
++    } else {
++      buffer[j] = lightval;
++      for (int i = 1; i < (this->width-1); i++)
++        buffer[j+(i*this->diameter)] = normalval;
++      buffer[j+((this->width-1)*this->diameter)] = shadeval;
++    }
++  }
++} // drawDisabledWheel()
++
++// ************************************************************************
++
++/*
++  This method draws the thumb wheel.
++  Shading/lighting aliasing can still be done better...
++  Can also optimize the drawing to use less computing power...
++*/
++
++void
++SoAnyThumbWheel::drawEnabledWheel(
++  const int number,
++  void * bitmap,
++  Alignment alignment) const
++{
++  this->validate();
++
++  int numEnabledBitmaps = this->width - 4 + 2;
++  assert(number > 0 && number <= numEnabledBitmaps);
++
++  float modulo = (2.0f * (float)M_PI) / this->numsquares;
++  float radian = modulo - (((2.0f * (float)M_PI) / this->numsquares) * (((float) (number - 1)) / (float) numEnabledBitmaps));
++
++  int newsquare = 1;
++  int flag = 1;
++  unsigned int * buffer = (unsigned int *) bitmap;
++  for (int j = 0; j < this->diameter; j++) {
++    unsigned int lightval, frontval, normalval, shadeval, color;
++
++    lightval  = (int8clamp(255.0f * this->red * this->tables[SIN][j] * this->light) << 24) +
++             (int8clamp(255.0f * this->green * this->tables[SIN][j] * this->light) << 16) +
++             (int8clamp(255.0f * this->blue * this->tables[SIN][j] * this->light) << 8);
++    frontval  = (int8clamp(255.0f * this->red * this->tables[SIN][j] * this->front) << 24) +
++             (int8clamp(255.0f * this->green * this->tables[SIN][j] * this->front) << 16) +
++             (int8clamp(255.0f * this->blue * this->tables[SIN][j] * this->front) << 8);
++    normalval = (int8clamp(255.0f * this->red * this->tables[SIN][j] * this->normal) << 24) +
++             (int8clamp(255.0f * this->green * this->tables[SIN][j] * this->normal) << 16) +
++             (int8clamp(255.0f * this->blue * this->tables[SIN][j] * this->normal) << 8);
++    shadeval  = (int8clamp(255.0f * this->red * this->tables[SIN][j] * this->shade) << 24) +
++             (int8clamp(255.0f * this->green * this->tables[SIN][j] * this->shade) << 16) +
++             (int8clamp(255.0f * this->blue * this->tables[SIN][j] * this->shade) << 8);
++
++    if (this->byteorder != RGBA) {
++      lightval = this->swapWord(lightval);
++      normalval = this->swapWord(normalval);
++      frontval = this->swapWord(frontval);
++      shadeval = this->swapWord(shadeval);
++    }
++
++    if (newsquare) {
++      color=frontval;
++      newsquare = 0;
++      flag = 1;
++    } else {
++      if (flag == 1) {
++        if (j < (this->diameter * 2 / 3))
++          color = shadeval;
++        else
++          color = normalval;
++        flag = 0;
++      } else {
++        color = normalval;
++      }
++    }
++
++    if (alignment == VERTICAL) {
++      buffer[(this->width*j)] = frontval;
++      buffer[(this->width*j)+1] = frontval;
++      if (flag == 1) buffer[(this->width*j)+2] = frontval;
++      else           buffer[(this->width*j)+2] = shadeval;
++
++      for (int i = 3; i < (this->width-2); i++)
++        buffer[(j*this->width)+i] = color;
++
++      if (flag == 1) buffer[(this->width*j)+this->width-3] = frontval;
++      else           buffer[(this->width*j)+this->width-3] = normalval;
++      buffer[(this->width*j)+this->width-2] = frontval;
++      buffer[(this->width*j)+this->width-1] = frontval;
++    } else {
++
++      buffer[j] = frontval;
++      buffer[j+this->diameter] = frontval;
++      if (flag == 1) buffer[j+(this->diameter*2)] = frontval;
++      else           buffer[j+(this->diameter*2)] = shadeval;
++
++      for (int i = 2; i < (this->width-2); i++)
++        buffer[j+(i*this->diameter)] = color;
++
++      if (flag == 1) buffer[j+(this->diameter*(this->width-3))] = frontval;
++      else           buffer[j+(this->diameter*(this->width-3))] = normalval;
++      buffer[j+(this->diameter*(this->width-2))] = frontval;
++      buffer[j+(this->diameter*(this->width-1))] = frontval;
++    }
++
++    if (j < (this->diameter - 1)) {
++      radian += this->tables[RAD][j+1] - this->tables[RAD][j];
++      if (radian > modulo) {
++        if (alignment == VERTICAL) {
++          int color = 0;
++          if (j > (this->diameter * 2 / 3))
++            color = lightval;
++          else if (j > (this->diameter / 3))
++            color = frontval;
++          if (color != 0)
++            for (int i = 3; i < (this->width-2); i++)
++              buffer[(j*this->width)+i] = color;
++        } else {
++          int color = 0;
++          if (j > (this->diameter * 2 / 3))
++            color = lightval;
++          else if (j > (this->diameter / 3))
++            color = frontval;
++          if (color != 0)
++            for (int i = 3; i < (this->width-2); i++)
++              buffer[j+(this->diameter*i)] = color;
++        }
++        radian = (float) fmod(radian, modulo);
++        newsquare = 1;
++      }
++    }
++  }
++} // drawEnabledWheel()
++
++// ************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/widgets/SoAnyThumbWheel.h.in
+@@ -0,0 +1,99 @@
++#ifndef SOANY_THUMBWHEEL_H
++#define SOANY_THUMBWHEEL_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++class SoAnyThumbWheel {
++public:
++  enum State              { DISABLED, ENABLED };
++  enum Alignment          { VERTICAL, HORIZONTAL };
++  enum BoundaryHandling   { MODULATE, ACCUMULATE, CLAMP };
++  enum Movement           { UNIFORM, AUTHENTIC };
++  enum GraphicsByteOrder  { ABGR, RGBA, ARGB, BGRA };
++
++  SoAnyThumbWheel(void);
++  ~SoAnyThumbWheel(void);
++
++  void setSize(const int diameter, const int width);
++  void getSize(int & diameter, int & width) const;
++
++  void setColor(const float red, const float green, const float blue);
++  void getColor(float & red, float & green, float & blue) const;
++  void setColorFactors(const float light, const float front, const float normal, const float shade);
++  void getColorFactors(float & light, float & front, float & normal, float & shade) const;
++
++  int getNumBitmaps(void) const;
++  void drawBitmap(const int number, void * bitmap, Alignment alignment) const;
++  float calculateValue(const float origValue, const int origPosition, const int deltaPosition) const;
++  int getBitmapForValue(const float value, const State state) const;
++
++  void setGraphicsByteOrder(const GraphicsByteOrder byteorder);
++  GraphicsByteOrder getGraphicsByteOrder(void) const;
++
++  void setMovement(const Movement movement);
++  Movement getMovement(void) const;
++
++  void setBoundaryHandling(const BoundaryHandling handling);
++  BoundaryHandling getBoundaryHandling(void) const;
++
++private:
++  unsigned int swapWord(unsigned int) const;
++
++  int diameter, width;
++  // float disabledred, disabledgreen, disabledblue; // not implemented
++  float red, green, blue;
++  float light, front, normal, shade;
++
++  GraphicsByteOrder  byteorder;
++  BoundaryHandling   boundaryhandling;
++  Movement           movement;
++
++  enum Tables { SIN, COS, RAD, NUMTABLES };
++
++  mutable float * tables [ NUMTABLES ];
++  mutable int dirtyTables;
++  mutable int dirtyVariables;
++  mutable float squarelength, squarespacing, shadelength, unistep, numsquares;
++
++  void drawDisabledWheel(const int number, void * bitmap, Alignment alignment) const;
++  void drawEnabledWheel(const int number, void * bitmap, Alignment alignment) const;
++
++  void validate(void) const;
++
++}; // class SoAnyThumbWheel
++
++// ************************************************************************
++
++#endif // ! SOANY_THUMBWHEEL_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/widgets/SoGuiPopupMenu.cpp.in
+@@ -0,0 +1,359 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/*!
++  \class So at Gui@PopupMenu Inventor/@Gui@/widgets/So at Gui@PopupMenu.h
++  \brief The So at Gui@PopupMenu class implements a common interface for popup
++  menu management for all the Coin GUI toolkit libraries.
++
++  The point of this class is to enable client code to be exactly the
++  same for all GUI libraries, even without being template-based.
++*/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <assert.h>
++
++#include <Inventor/SoLists.h>
++#include <Inventor/errors/SoDebugError.h>
++
++#include <so at gui@defs.h>
++#include <Inventor/@Gui@/widgets/So at Gui@PopupMenu.h>
++#include <Inventor/@Gui@/widgets/@Gui at NativePopupMenu.h>
++#include <Inventor/@Gui@/common/SbGuiList.h>
++
++// *************************************************************************
++
++// Documentation for abstract methods.
++
++/*!
++  \fn void So at Gui@PopupMenu::popUp(@WIDGET@ inside, int x, int y)
++
++  Invokes this popup menu instance.
++
++  The coordinates for the popup will be used relative to the origo of
++  the widget argument.
++*/
++
++// *************************************************************************
++
++// The private data for the So at Gui@PopupMenu.
++
++class So at Gui@PopupMenuP {
++public:
++  SbGuiList<int> menuitems;
++  SbGuiList<int> radiogroups;
++  SbPList * callbacks;
++  SbPList * userdata;
++};
++
++
++#define PRIVATE(o) (o->pimpl)
++
++// *************************************************************************
++
++/*!
++  Instantiation method.
++
++  So at Gui@PopupMenu is implemented with this "factory" method instead of
++  a public constructor to provide a completely generic interface on
++  top of the toolkit's native popup menu implementation.
++*/
++So at Gui@PopupMenu *
++So at Gui@PopupMenu::createInstance(void)
++{
++  return new @Gui at NativePopupMenu();
++}
++
++
++/*!
++  The class constructor is protected, as So at Gui@PopupMenu uses a factory
++  instantiation method.
++*/
++So at Gui@PopupMenu::So at Gui@PopupMenu(void)
++{
++  PRIVATE(this) = new So at Gui@PopupMenuP;
++
++  PRIVATE(this)->callbacks = NULL;
++  PRIVATE(this)->userdata = NULL;
++} // So at Gui@PopupMenu()
++
++/*!
++  Destructor.
++*/
++So at Gui@PopupMenu::~So at Gui@PopupMenu()
++{
++  delete PRIVATE(this)->callbacks;
++  delete PRIVATE(this)->userdata;
++  delete PRIVATE(this);
++} // ~So at Gui@PopupMenu()
++
++// *************************************************************************
++
++void
++So at Gui@PopupMenu::setMenuItemMarked(int itemid, SbBool marked)
++{
++  // forward to native implementation
++  this->_setMenuItemMarked(itemid, marked);
++
++  if (marked) {
++    const int radiogroupid = this->getRadioGroup(itemid);
++    if (radiogroupid != -1) {
++      this->setRadioGroupMarkedItem(itemid);
++    }
++  }
++}
++
++// *************************************************************************
++
++/*!
++*/
++
++int
++So at Gui@PopupMenu::newRadioGroup(
++  int groupid)
++{
++  const int numGroupedItems = PRIVATE(this)->radiogroups.getLength();
++  int id = groupid;
++  if (id != -1) {
++    SbBool hit = FALSE;
++    int i;
++    for (i = 0; i < numGroupedItems && hit == FALSE; i++) {
++      if (PRIVATE(this)->radiogroups[i] == id)
++        hit = TRUE;
++    }
++    if (hit) {
++#if SO at GUI@_DEBUG
++      SoDebugError::postInfo("So at Gui@PopupMenu::NewRadioGroup",
++        "requested group id already taken");
++#endif // SO at GUI@_DEBUG
++      return -1; 
++    }
++  } else {
++    id = 0;
++    SbBool found;
++    do {
++      id++;
++      found = FALSE;
++      int i;
++      for (i = 0; i < numGroupedItems && found == FALSE; i++) {
++        if (PRIVATE(this)->radiogroups[i] == id)
++          found = TRUE;
++      }
++    } while (found);
++  }
++  // id is OK here
++  PRIVATE(this)->menuitems.append(-1); // fake menu item
++  PRIVATE(this)->radiogroups.append(id); // register id in array
++  return id;
++} // newRadioGroup()
++
++/*!
++*/
++
++int
++So at Gui@PopupMenu::getRadioGroup(
++  int itemid)
++{
++  assert(itemid != -1);
++  const int numGroupedItems = PRIVATE(this)->radiogroups.getLength();
++  int i;
++  for (i = 0; i < numGroupedItems; i++) {
++    if (PRIVATE(this)->menuitems[i] == itemid)
++      return PRIVATE(this)->radiogroups[i];
++  }
++  return -1;
++} // getRadioGroup()
++
++/*!
++*/
++
++int
++So at Gui@PopupMenu::getRadioGroupSize(
++  int groupid)
++{
++  int count = 0;
++  const int numItems = PRIVATE(this)->radiogroups.getLength();
++  int i;
++  for (i = 0; i < numItems; i++) {
++    if (PRIVATE(this)->radiogroups[i] == groupid &&
++         PRIVATE(this)->menuitems[i] != -1)
++      count++;
++  }
++  return count;
++} // getRadioGroupSize()
++
++/*!
++*/
++
++void
++So at Gui@PopupMenu::addRadioGroupItem(
++  int groupid,
++  int itemid)
++{
++  PRIVATE(this)->menuitems.append(itemid);
++  PRIVATE(this)->radiogroups.append(groupid);
++} // addRadioGroupItem()
++
++/*!
++*/
++
++void
++So at Gui@PopupMenu::removeRadioGroupItem(
++  int itemid)
++{
++  assert(itemid != -1);
++  const int numGroupedItems = PRIVATE(this)->menuitems.getLength();
++  int i;
++  for (i = 0; i < numGroupedItems; i++) {
++    if (PRIVATE(this)->menuitems[i] == itemid) {
++      PRIVATE(this)->menuitems.remove(i);
++      PRIVATE(this)->radiogroups.remove(i);
++      return;
++    }
++  }
++} // removeRadioGroupItem()
++
++// *************************************************************************
++
++void
++So at Gui@PopupMenu::setRadioGroupMarkedItem(int itemid)
++{
++  const int idx = PRIVATE(this)->menuitems.find(itemid);
++  assert(idx != -1);
++  const int groupid = PRIVATE(this)->radiogroups[idx];
++
++  if (groupid == -1) {
++    SoDebugError::post("So at Gui@PopupMenu::setRadioGroupMarkedItem",
++                       "item not in a radio group");
++    return;
++  }
++
++  const int numItems = PRIVATE(this)->menuitems.getLength();
++  for (int i = 0; i < numItems; i++) {
++    if (i == idx) { continue; }
++    if (PRIVATE(this)->radiogroups[i] == groupid) {
++      const int item = PRIVATE(this)->menuitems[i];
++      if (item != -1) { // FIXME: should this be an assert? 20050622 mortene.
++        if ( this->getMenuItemMarked(item) ) {
++          this->setMenuItemMarked(item, FALSE);
++        }
++      }
++    }
++  }
++}
++
++int
++So at Gui@PopupMenu::getRadioGroupMarkedItem(int groupid)
++{
++  const int numItems = PRIVATE(this)->menuitems.getLength();
++  int i;
++  for (i = 0; i < numItems; i++) {
++    if (PRIVATE(this)->radiogroups[i] == groupid) {
++      int item = PRIVATE(this)->menuitems[i];
++      if (item != -1 && this->getMenuItemMarked(item))
++        return item;
++    }
++  }
++  return -1;
++}
++
++// *************************************************************************
++
++/*!
++*/
++
++void
++So at Gui@PopupMenu::addMenuSelectionCallback(
++  So at Gui@MenuSelectionCallback * callback,
++  void * user)
++{
++  if (PRIVATE(this)->callbacks == NULL) {
++    PRIVATE(this)->callbacks = new SbPList;
++    PRIVATE(this)->userdata = new SbPList;
++  }
++  PRIVATE(this)->callbacks->append((void *) callback);
++  PRIVATE(this)->userdata->append(user);
++} // addMenuSelectionCallback()
++
++/*!
++*/
++
++void
++So at Gui@PopupMenu::removeMenuSelectionCallback(
++  So at Gui@MenuSelectionCallback * callback,
++  void * user)
++{
++  if (PRIVATE(this)->callbacks == NULL) {
++#if SO at GUI@_DEBUG
++    SoDebugError::postInfo("So at Gui@PopupMenu::RemoveMenuSelectionCallback",
++      "no callbacks at all");
++#endif // SO at GUI@_DEBUG
++    return;
++  }
++  int numCallbacks = PRIVATE(this)->callbacks->getLength();
++  int i;
++  for (i = 0; i < numCallbacks; i++) {
++    if ((*PRIVATE(this)->callbacks)[i] == (void *) callback &&
++         (*PRIVATE(this)->userdata)[i] == user) {
++      PRIVATE(this)->callbacks->remove(i);
++      PRIVATE(this)->userdata->remove(i);
++      i--;
++      numCallbacks--;
++    }
++  }
++} // removeMenuSelectionCallback()
++
++/*!
++*/
++
++void
++So at Gui@PopupMenu::invokeMenuSelection(
++  int itemid)
++{
++  if (PRIVATE(this)->callbacks == NULL)
++    return;
++  const int numCallbacks = PRIVATE(this)->callbacks->getLength();
++  int i;
++  for (i = 0; i < numCallbacks; i++) {
++    So at Gui@MenuSelectionCallback * cb = (So at Gui@MenuSelectionCallback *)
++      (*PRIVATE(this)->callbacks)[i];
++    (*cb)(itemid, (*PRIVATE(this)->userdata)[i]);
++  }
++} // invokeMenuSelection()
++
++// *************************************************************************
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/widgets/SoGuiPopupMenu.h.in
+@@ -0,0 +1,108 @@
++#ifndef SO at GUI@_POPUPMENU_H
++#define SO at GUI@_POPUPMENU_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/SbBasic.h>
++
++#include <Inventor/@Gui@/So at Gui@Component.h>
++
++// *************************************************************************
++
++typedef void So at Gui@MenuSelectionCallback(int itemid, void * user);
++
++class SO at GUI@_DLL_API So at Gui@PopupMenu { // abstract interface class
++public:
++  static So at Gui@PopupMenu * createInstance(void);
++  virtual ~So at Gui@PopupMenu();
++
++  virtual int newMenu(const char * name, int menuid = -1) = 0;
++  virtual int getMenu(const char * name) = 0;
++  virtual void setMenuTitle(int id, const char * title) = 0;
++  virtual const char * getMenuTitle(int id) = 0;
++
++  virtual int newMenuItem(const char * name, int itemid = -1) = 0;
++  virtual int getMenuItem(const char * name) = 0;
++  virtual void setMenuItemTitle(int itemid, const char * title) = 0;
++  virtual const char * getMenuItemTitle(int itemid) = 0;
++  virtual void setMenuItemEnabled(int itemid, SbBool enabled) = 0;
++  virtual SbBool getMenuItemEnabled(int itemid) = 0;
++  void setMenuItemMarked(int itemid, SbBool marked);
++  virtual SbBool getMenuItemMarked(int itemid) = 0;
++
++  virtual void addMenu(int menuid, int submenuid, int pos = -1) = 0;
++  virtual void addMenuItem(int menuid, int itemid, int pos = -1) = 0;
++  virtual void addSeparator(int menuid, int pos = -1) = 0;
++  virtual void removeMenu(int menuid) = 0;
++  virtual void removeMenuItem(int itemid) = 0;
++
++  virtual void popUp(@WIDGET@ inside, int x, int y) = 0;
++
++  int newRadioGroup(int groupid = -1);
++  int getRadioGroup(int itemid);
++  int getRadioGroupSize(int groupid);
++  void addRadioGroupItem(int groupid, int itemid);
++  void removeRadioGroupItem(int itemid);
++
++  // FIXME: bad interface. Should be internal/private, and the name is
++  // wrong.  According to what this actually does, it should be
++  // something like "unmarkOtherOfRadioGroup()". 20050622 mortene.
++  void setRadioGroupMarkedItem(int itemid);
++#if SO at GUI@_MAJOR_VERSION == 2
++#error fix API above
++#endif // SO at GUI@_MAJOR_VERSION
++
++  int getRadioGroupMarkedItem(int groupid);
++
++  void addMenuSelectionCallback(So at Gui@MenuSelectionCallback * callback,
++                                void * data);
++  void removeMenuSelectionCallback(So at Gui@MenuSelectionCallback * callback,
++                                   void * data);
++
++protected:
++  So at Gui@PopupMenu(void);
++
++  virtual void _setMenuItemMarked(int itemid, SbBool marked) = 0;
++
++  void invokeMenuSelection(int itemid);
++
++private:
++  class So at Gui@PopupMenuP * pimpl;
++
++}; // class So at Gui@PopupMenu
++
++// *************************************************************************
++
++#endif // ! SO at GUI@_POPUPMENU_H
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..13e85d3
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1 @@
+add_sogui.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/soqt.git



More information about the debian-science-commits mailing list