// $Source: /usr/local/SimSoft/Sfx3D/src/gsl/gui.cpp,v $
// $Revision: 1.3 $
// $Author: baum $
// $Date: 2001/12/04 16:27:05 $
//
// Login name of the user who locked the revision
// $Locker:  $
// Tag name used to checkout the file
// $Name:  $
// State assigned to revision
// $State: Exp $
//
//
// $Log: gui.cpp,v $
// Revision 1.3  2001/12/04 16:27:05  baum
// -Verschiedene Bugs entfernt
//
// Revision 1.2  2001/11/29 15:18:09  baum
// -Realzeitsteuerung eingebaut
// -Handsteuerung eingebaut
//

#include <stdlib.h>
#include <string.h>
#include <ctype.h>          

#include "execontx.h"

#include "DynArray.h"
#include "Messager.h"
#include "FileSys.h"
#include "Strings.h"
#include "StrmSet.h"
#include "IniFile.h"
#include "ProgArgs.h" /**< Ergaenzung von Rudi. 07.08.2002. Fuer Braun-Projekt. */

#include "MathDefs.h"
#include "Vec2D.h"
#include "Vec3D.h"

#include "XGraph/Linequad.h"
#include "XGraph/XGraph.h"
#include "XGraph/AllViews.h"

#include "transp.h"
#include "arbplan.h"
#include "route.h"
#include "sfxprg.h"
#include "programm.h"
#include "ereignis.h"
#include "serialio.h"
#include "realzeit.h"
#include "msps.h"//miro,14.02.01---modeltechnik
#define _GUI_CPP
#include "gui.h"

#include "tcl.h"
#include "tk.h"


//==================================================================
//		stuff for SFXGui
//==================================================================
char DlgBuffer[255];
char buf[255];
char NameBuffer[255];
Tcl_Interp *SFXInterp;
SFXViewHandler *MyViewHandler;

//==================================================================
//		Implementation
//		for class SFXViewHandler
//==================================================================

/*static*/ unsigned SFXViewHandler::ClassId = 0;

SFXViewHandler::SFXViewHandler (Tcl_Interp* interp, const SFXModel& model)
 :  ObjModel      ((SFXModel*) &model),
    ObjInterp     (interp),
    ObjDlgHandler (new SFXDialogHandler (model)),
    ObjPosed      (false),
    ObjStopAfterPosed (false),
    ObjCountOfDisposedViews (0),
    ObjWinHeight  (300),
    ObjWinWidth   (300),
    ObjBgColor    (1.0, 1.0, 1.0),
    ObjGridWrap   (),
    ObjGridSize   (2.0),
    ObjWithGrid   (true),
    ObjWireframe  (false),
    ObjLighting   (true),
    ObjAntialiasing (false),
    ObjFogging    (false),
    ObjFogDensity (0.01),
    ObjLightPos   (0.9, 0.8, 1.0),
    ObjLightDir   (-ObjLightPos),
    ObjViewPoint  (),
    ObjTimeUpdate (1),
    ObjLastTimeUpdate (),
    ObjViews      (2) {
  if (!ToglView::isInitialized ()) {
    ToglView::setup (interp);
    Tcl_CreateCommand(interp, "SFXView", SFXViewHandler::ViewDialog,
        (ClientData) this, (Tcl_CmdDeleteProc *) 0);
    Tcl_CreateCommand(interp, "SFXContext", SFXViewHandler::ContextDialog,
        (ClientData) this, (Tcl_CmdDeleteProc *) 0);
  }

  ObjWinWidth  = IniFile::DefIniFile.readInt    ("GRAFIK", "WinWidth", 300);
  ObjWinHeight = IniFile::DefIniFile.readInt    ("GRAFIK", "WinHeight", 300);
  ObjWithGrid  = IniFile::DefIniFile.readBool   ("GRAFIK", "WithGrid", true);
  ObjGridSize  = IniFile::DefIniFile.readDouble ("GRAFIK", "GridSize", 2.0);
  ObjWireframe = IniFile::DefIniFile.readBool   ("GRAFIK", "Wireframe", false);
  ObjAntialiasing = IniFile::DefIniFile.readBool("GRAFIK", "Antialiasing", false);
  ObjFogging   = IniFile::DefIniFile.readBool   ("GRAFIK", "Fogging", false);
  ObjFogDensity= IniFile::DefIniFile.readDouble ("GRAFIK", "FogDensity", 0.01);
  ObjLighting  = IniFile::DefIniFile.readBool   ("GRAFIK", "Lighting", true);

  double x, y, z;
  sprintf (DlgBuffer, IniFile::DefIniFile.readString ("GRAFIK", "LightPosition", "0.9 0.8 1.0"));
  sscanf (DlgBuffer, " %lf %lf %lf", &x, &y, &z);
  ObjLightPos = Vec3D (x, y, z);
  sprintf (DlgBuffer, IniFile::DefIniFile.readString ("GRAFIK", "LightDirection", "-0.9 -0.8 -1.0"));
  sscanf (DlgBuffer, " %lf %lf %lf", &x, &y, &z);
  ObjLightDir = Vec3D (x, y, z);

  sprintf (DlgBuffer, IniFile::DefIniFile.readString ("GRAFIK", "BackgroundColor", "1.0 1.0 1.0"));
  sscanf (DlgBuffer, " %lf %lf %lf", &x, &y, &z);
  ObjBgColor = RGBAColor (x, y, z);

  sprintf (DlgBuffer, IniFile::DefIniFile.readString ("GRAFIK", "CamPosition", "5.0 5.0 10.0"));
  sscanf (DlgBuffer, " %lf %lf %lf", &x, &y, &z);
  Vec3D CamPos = Vec3D (x, y, z);

  sprintf (DlgBuffer, IniFile::DefIniFile.readString ("GRAFIK", "CamFocus", "5.0 5.0 -1.0"));
  sscanf (DlgBuffer, " %lf %lf %lf", &x, &y, &z);
  Vec3D CamFocus = Vec3D (x, y, z);

  sprintf (DlgBuffer, IniFile::DefIniFile.readString ("GRAFIK", "CamUp", "0.0  1.0  0.0"));
  sscanf (DlgBuffer, " %lf %lf %lf", &x, &y, &z);
  Vec3D CamUp = Vec3D (x, y, z);
  ObjViewPoint = ViewPoint (CamPos, CamFocus, CamUp);

  const Map<typBaustein, GeoObject>& m (model.Permanents ());
  for (m.First (); m (); m++)
    ObjGridWrap.adjust (m ()->WrapForParent ());
  ObjGridWrap.sort ();
  ObjGridWrap.Max = Vec3D (ObjGridWrap.Max.X (), ObjGridWrap.Max.Y (), ObjGridWrap.Min.Z ());
/*
  ObjCamFocus = Vec3D (ObjGridWrap.Min + ((ObjGridWrap.Max - ObjGridWrap.Min) * 0.5));
  ObjCamPos   = ObjCamFocus + (EZ * (((ObjGridWrap.Max - ObjGridWrap.Min) * 0.5).len () / (Angle (20).tan ())));
  ObjCamPos   = ObjCamPos.projOn (EZ);*/
}

SFXViewHandler::~SFXViewHandler () {
  if (!EPPoseFunc)    EPPoseFunc    = NULL;
  if (!EPDisposeFunc) EPDisposeFunc = NULL;
  delete ObjDlgHandler;

  while (ObjViews.Last ())
    removeView (ObjViews.Last ());
  Pattern::removeDisplayLists ();
}

void SFXViewHandler::createView (int xPos, int yPos) {
  Ustring wName = (Ustring (".top") + Ustring (ClassId++));
  if (!ObjViews.Count ()) {
    if (hlaTimeRegulating && hlaTimeConstrained && hlaAsynchronousDelivery) {
      sprintf (DlgBuffer, "makeSFXView %s \"SIMFLEX: %s (Hauptansicht - HLA: reg, con, asyn)\" %d %d",
	       wName.str (), ObjModel->ModelName ().str (), ObjWinWidth, ObjWinHeight);
    } else if (hlaTimeRegulating && hlaAsynchronousDelivery) {
      sprintf (DlgBuffer, "makeSFXView %s \"SIMFLEX: %s (Hauptansicht - HLA: reg,  asyn)\" %d %d",
	       wName.str (), ObjModel->ModelName ().str (), ObjWinWidth, ObjWinHeight);
    } else if (hlaTimeConstrained && hlaAsynchronousDelivery) {
      sprintf (DlgBuffer, "makeSFXView %s \"SIMFLEX: %s (Hauptansicht - HLA: con, asyn)\" %d %d",
	       wName.str (), ObjModel->ModelName ().str (), ObjWinWidth, ObjWinHeight);
    } else if (hlaTimeRegulating && hlaTimeConstrained) {
      sprintf (DlgBuffer, "makeSFXView %s \"SIMFLEX: %s (Hauptansicht - HLA: reg, con)\" %d %d",
	       wName.str (), ObjModel->ModelName ().str (), ObjWinWidth, ObjWinHeight);
    } else if (hlaTimeRegulating) {
      sprintf (DlgBuffer, "makeSFXView %s \"SIMFLEX: %s (Hauptansicht - HLA: reg)\" %d %d",
	       wName.str (), ObjModel->ModelName ().str (), ObjWinWidth, ObjWinHeight);
    } else if (hlaTimeConstrained) {
      sprintf (DlgBuffer, "makeSFXView %s \"SIMFLEX: %s (Hauptansicht - HLA: con)\" %d %d",
	       wName.str (), ObjModel->ModelName ().str (), ObjWinWidth, ObjWinHeight);
    } else if (hlaAsynchronousDelivery) {
      sprintf (DlgBuffer, "makeSFXView %s \"SIMFLEX: %s (Hauptansicht - HLA: asyn)\" %d %d",
	       wName.str (), ObjModel->ModelName ().str (), ObjWinWidth, ObjWinHeight);
    } else if (hla) {
      sprintf (DlgBuffer, "makeSFXView %s \"SIMFLEX: %s (Hauptansicht - HLA)\" %d %d",
	       wName.str (), ObjModel->ModelName ().str (), ObjWinWidth, ObjWinHeight);
    } else {
    sprintf (DlgBuffer, "makeSFXView %s \"SIMFLEX: %s (Hauptansicht)\" %d %d ",
             wName.str (), ObjModel->ModelName ().str (), ObjWinWidth, ObjWinHeight);
    }
  } else {
    if (hlaTimeRegulating && hlaTimeConstrained && hlaAsynchronousDelivery) {
      sprintf (DlgBuffer, "makeSFXView %s \"SIMFLEX: %s (HLA: reg, con, asyn)\" %d %d",
	       wName.str (), ObjModel->ModelName ().str (), ObjWinWidth, ObjWinHeight);
    } else if (hlaTimeRegulating && hlaAsynchronousDelivery) {
      sprintf (DlgBuffer, "makeSFXView %s \"SIMFLEX: %s (HLA: reg,  asyn)\" %d %d",
	       wName.str (), ObjModel->ModelName ().str (), ObjWinWidth, ObjWinHeight);
    } else if (hlaTimeConstrained && hlaAsynchronousDelivery) {
      sprintf (DlgBuffer, "makeSFXView %s \"SIMFLEX: %s (HLA: con, asyn)\" %d %d",
	       wName.str (), ObjModel->ModelName ().str (), ObjWinWidth, ObjWinHeight);
    } else if (hlaTimeRegulating && hlaTimeConstrained) {
      sprintf (DlgBuffer, "makeSFXView %s \"SIMFLEX: %s (HLA: reg, con)\" %d %d",
	       wName.str (), ObjModel->ModelName ().str (), ObjWinWidth, ObjWinHeight);
    } else if (hlaTimeRegulating) {
      sprintf (DlgBuffer, "makeSFXView %s \"SIMFLEX: %s (HLA: reg)\" %d %d",
	       wName.str (), ObjModel->ModelName ().str (), ObjWinWidth, ObjWinHeight);
    } else if (hlaTimeConstrained) {
      sprintf (DlgBuffer, "makeSFXView %s \"SIMFLEX: %s (HLA: con)\" %d %d",
	       wName.str (), ObjModel->ModelName ().str (), ObjWinWidth, ObjWinHeight);
    } else if (hlaAsynchronousDelivery) {
      sprintf (DlgBuffer, "makeSFXView %s \"SIMFLEX: %s (HLA: asyn)\" %d %d",
	       wName.str (), ObjModel->ModelName ().str (), ObjWinWidth, ObjWinHeight);
    } else if (hla) {
      sprintf (DlgBuffer, "makeSFXView %s \"SIMFLEX: %s (HLA)\" %d %d",
	       wName.str (), ObjModel->ModelName ().str (), ObjWinWidth, ObjWinHeight);
    } else {
    sprintf (DlgBuffer, "makeSFXView %s \"SIMFLEX: %s\" %d %d ",
             wName.str (), ObjModel->ModelName ().str (), ObjWinWidth, ObjWinHeight);
    }
  }


  if (Tcl_GlobalEval (ObjInterp, DlgBuffer) == TCL_ERROR)
      Msg.Warning ("SFXViewHandler::createView", "TCL_ERROR: %s", ObjInterp->result);

  ToglView* newView = new ToglView (xPos, yPos, ObjWinWidth, ObjWinHeight, ObjBgColor,
                                    wName.str (), (wName + ".menu.ansicht").str ());
  Vec3D focus = Vec3D (ObjGridWrap.Min + ((ObjGridWrap.Max - ObjGridWrap.Min) * 0.5));
  Vec3D pos = EZ * (((ObjGridWrap.Max - ObjGridWrap.Min) * 0.5).len ()
                    / (Angle (newView->Camera()->VisualAngle ()).tan ()));
  double dist = pos.len () + (focus.len () * 0.5);
  newView->addViewPoint (Ustring ("Default"), ObjViewPoint);
  newView->addViewPoint (Ustring ("Iso"), ViewPoint (focus + (Vec3D (-1.0, -1.0, 1.0) * dist),
                                                     focus, Vec3D (1.0, 1.0, 1.0)));
  newView->addViewPoint (Ustring ("Top"), ViewPoint (focus + (EZ * dist), focus, EY));
  newView->addViewPoint (Ustring ("Front"), ViewPoint (focus + (-EY * dist), focus, EZ));
  newView->addViewPoint (Ustring ("Back"), ViewPoint (focus + (EY * dist), focus, EZ));
  newView->addViewPoint (Ustring ("Left"), ViewPoint (focus + (-EX * dist), focus, EZ));
  newView->addViewPoint (Ustring ("Right"), ViewPoint (focus + (EX * dist), focus, EZ));
  newView->setToViewPoint (Ustring ("Default"));
  
  double x,y,z;
  for (unsigned i = 1; i<=9;i++) {
   sprintf (NameBuffer,"CamPosition%i",i); 
   sprintf (DlgBuffer, IniFile::DefIniFile.readString ("GRAFIK", NameBuffer, ""));
   if (strlen(DlgBuffer) !=0) {
      sscanf (DlgBuffer, " %lf %lf %lf", &x, &y, &z);
      Vec3D CamPos = Vec3D (x, y, z);
      sprintf (NameBuffer,"CamFocus%i",i); 
      sprintf (DlgBuffer, IniFile::DefIniFile.readString ("GRAFIK", NameBuffer, ""));
      sscanf (DlgBuffer, " %lf %lf %lf", &x, &y, &z);
      Vec3D CamFocus = Vec3D (x, y, z);
      sprintf (NameBuffer,"CamUp%i",i);  
      sprintf (DlgBuffer, IniFile::DefIniFile.readString ("GRAFIK", NameBuffer, ""));
      sscanf (DlgBuffer, " %lf %lf %lf", &x, &y, &z);
      Vec3D CamUp = Vec3D (x, y, z);
      newView->addViewPoint (Ustring(i), ViewPoint (CamPos, CamFocus, CamUp));
   }
  }
  
  newView->Camera()->setNearClipDist (0.2);
  newView->Camera()->setFarClipDist (Max ((ObjGridWrap.Max - ObjGridWrap.Min).len () * 1.8, 100.0));
  newView->setCallback (new SFXCallback ());
  newView->Light ()->setPosition (ObjLightPos);
  newView->Light ()->setDirection (ObjLightDir);
  ObjModel->ModelSpace ()->insertView (*newView);
  ObjViews.append (*newView);

  Vec3D gridOffset (1.0, 1.0, 0.0);
  newView->setGrid (ObjGridSize, ObjGridWrap.Min - gridOffset, ObjGridWrap.Max + gridOffset);

  if (ObjWithGrid)
    newView->showGrid ();
  if (ObjWireframe)
    newView->wireOn ();
  else {
    if (ObjLighting)
      newView->lightOn ();
    if (ObjAntialiasing)
      newView->smoothOn ();
    if (ObjFogging)
      newView->fogOn ();
  }
  newView->setFogDensity (ObjFogDensity);
  newView->flush ();

  while (Tcl_DoOneEvent (TCL_ALL_EVENTS|TCL_DONT_WAIT) != 0);
  ObjPosed = true;

  if (!EPPoseHandler)
    EPPoseHandler = this;
  if (!EPPoseFunc)
    EPPoseFunc    = SFXViewHandler::poseViews;
  if (!EPDisposeFunc)
    EPDisposeFunc = SFXViewHandler::disposeViews;
}

/*static*/ void SFXViewHandler::poseViews (SFXViewHandler* forWhom) {
  if (!forWhom->ObjPosed) {
    forWhom->ObjModel->restoreCycle ();
    forWhom->ObjTimeUpdate = SimTime (1);
    forWhom->ObjLastTimeUpdate = Modellzeit ();
    forWhom->ObjPosed = true;
    if (forWhom->ObjCountOfDisposedViews) {
      for (forWhom->ObjViews.First (); forWhom->ObjViews (); forWhom->ObjViews++) {
        sprintf (DlgBuffer, "wm deiconify %s", forWhom->ObjViews ()->ToplevelName ());
        Tcl_GlobalEval (forWhom->ObjInterp, DlgBuffer);
      }
      forWhom->ObjCountOfDisposedViews = 0;
    }
    else {
      for (forWhom->ObjViews.First (); forWhom->ObjViews (); forWhom->ObjViews++)
        forWhom->ObjViews ()->pose (forWhom->ObjModel->ModelSpace ());
    }
    if (forWhom->ObjStopAfterPosed) {
      sprintf (DlgBuffer, ".knoeppe.startstop.stop invoke ");
      Tcl_GlobalEval (forWhom->ObjInterp, DlgBuffer);
    }
  }
}

/*static*/ void SFXViewHandler::disposeViews (SFXViewHandler* forWhom,
                                              bool minimize   /*= true*/,
                                              bool wasRunning /*= true*/) {
  if (forWhom->ObjPosed) {
    forWhom->ObjStopAfterPosed = (wasRunning ? false : true);
    forWhom->ObjModel->freezCycle ();
    forWhom->ObjTimeUpdate = SimTime (3600);
    forWhom->ObjLastTimeUpdate = Modellzeit ().Hours () * SimTime::SecondsPerHour ();
    forWhom->ObjPosed = false;
    if (minimize) {
      forWhom->ObjCountOfDisposedViews = forWhom->ObjViews.Count ();
      for (forWhom->ObjViews.First (); forWhom->ObjViews (); forWhom->ObjViews++) {
        sprintf (DlgBuffer, "wm iconify %s", forWhom->ObjViews ()->ToplevelName ());
        Tcl_GlobalEval (forWhom->ObjInterp, DlgBuffer);
      }
    }
    else {
      for (forWhom->ObjViews.First (); forWhom->ObjViews (); forWhom->ObjViews++)
        forWhom->ObjViews ()->dispose ();
    }
  }
}

bool SFXViewHandler::isPosed () const {
  return ObjPosed;
}

const SimTime& SFXViewHandler::TimeUpdate () const {
  return ObjTimeUpdate;
}

const SimTime& SFXViewHandler::LastTimeUpdate () const {
  return ObjLastTimeUpdate;
}

void  SFXViewHandler::markTimeUpdate () {
  ObjLastTimeUpdate = Modellzeit ();
}

void SFXViewHandler::flushViews () {
  if (ObjPosed) {
    for (ObjViews.First (); ObjViews (); ObjViews++)
      ObjViews ()->flush ();
  }
}

void SFXViewHandler::removeView (ToglView* view) {
 // if (ObjPosed) {
    Ustring top (view->ToplevelName ());
    if (view->Callback ()) delete view->Callback ();
    delete ObjViews.remove (*view);
    Tk_DestroyWindow (Tk_NameToWindow (ObjInterp, top.str (), Tk_MainWindow (ObjInterp)));
 // }
}

void SFXViewHandler::setViewToDefault (ToglView* view) {
  view->Camera()->setVisualAngle (40.0);
  view->setToViewPoint (Ustring ("Default"));
  view->flush ();
}

void SFXViewHandler::setViewToViewpoint (ToglView* view,Ustring point) {
  view->Camera()->setVisualAngle (40.0);
  view->setToViewPoint (point);
  view->flush ();
}

void SFXViewHandler::setCamToDefault (ToglView* view) {
  const GeoObject* possibleCamObject (view->Camera ()->CameraObject ());
  if (possibleCamObject) {
    typTransportEinheit* zTE (MySFXModel->Temporaries ().findKey (*possibleCamObject));
    if (zTE) zTE->setDestroyFunction (NULL);
    view->Camera ()->setToGlobal ();
  }
  ((SFXCallback*) view->Callback ())->setToStandard ();
}

void SFXViewHandler::setCamToWalk (ToglView* view) {
  const GeoObject* possibleCamObject (view->Camera ()->CameraObject ());
  if (possibleCamObject) {
    typTransportEinheit* zTE (MySFXModel->Temporaries ().findKey (*possibleCamObject));
    if (zTE) zTE->setDestroyFunction (NULL);
    view->Camera ()->setToGlobal ();
  }
  ((SFXCallback*) view->Callback ())->setToWalking ();
}

void SFXViewHandler::setCamToZoom (ToglView* view) {
  const GeoObject* possibleCamObject (view->Camera ()->CameraObject ());
  if (possibleCamObject) {
    typTransportEinheit* zTE (MySFXModel->Temporaries ().findKey (*possibleCamObject));
    if (zTE) zTE->setDestroyFunction (NULL);
    view->Camera ()->setToGlobal ();
  }
  ((SFXCallback*) view->Callback ())->setToZooming ();
}

void SFXViewHandler::setCamToLight (ToglView* view) {
  const GeoObject* possibleCamObject (view->Camera ()->CameraObject ());
  if (possibleCamObject) {
    typTransportEinheit* zTE (MySFXModel->Temporaries ().findKey (*possibleCamObject));
    if (zTE) zTE->setDestroyFunction (NULL);
    view->Camera ()->setToGlobal ();
  }
  Vec3D pos (view->Light ()->Position ());
  // CamUp will be recalc by camera
  view->Camera ()->setCamera (pos, pos + view->Light ()->Direction (),
                              view->Camera ()->CameraUp ());
  ((SFXCallback*) view->Callback ())->setToLight ();
  view->flush ();
}

void SFXViewHandler::setCamToPermObj (ToglView* view, GeoObject* go) {
  view->MySpace ()->MySelection ()->removeAll ();
  view->Camera ()->setToLocal (go);
  Tcl_SetVar2 (SFXInterp, "sfxMouseHandling", (char*) view->WidgetName (), "10", TCL_GLOBAL_ONLY);
  ((SFXCallback*) view->Callback ())->setToCamSetting ();
  view->flush ();
}

void SFXViewHandler::setCamToTempObj (ToglView* view, GeoObject* go) {
  view->MySpace ()->MySelection ()->removeAll ();
  view->Camera ()->setToLocal (go);
  MySFXModel->Temporaries ().findKey (*go)->setDestroyFunction (hangUpObject);
  Tcl_SetVar2 (SFXInterp, "sfxMouseHandling", (char*) view->WidgetName (), "10", TCL_GLOBAL_ONLY);
  ((SFXCallback*) view->Callback ())->setToCamSetting ();
  view->flush ();
}

void SFXViewHandler::setObjectToFocus (ToglView* view, GeoObject* go) {
  WrapBox box;
  box.adjust (go->WrapForParent ());
  Vec3D distance = Vec3D (view->Camera ()->ViewDir ().unit () *
                          (((box.Max - box.Min)).len () /
                            (Angle (view->Camera ()->VisualAngle ()).tan ())));
  view->Camera ()->setCamera (go->Pos () - distance, go->Pos (), view->Camera ()->CameraUp ());
  view->flush ();
}

void SFXViewHandler::saveSettings (ToglView* view) {
  ObjWinWidth = view->Width ();
  IniFile::DefIniFile.writeInt    ("GRAFIK", "WinWidth", ObjWinWidth);
  ObjWinHeight = view->Height ();
  IniFile::DefIniFile.writeInt    ("GRAFIK", "WinHeight", ObjWinHeight);
  ObjWithGrid = view->hasToShowGrid ();
  IniFile::DefIniFile.writeBool   ("GRAFIK", "WithGrid", ObjWithGrid);
  IniFile::DefIniFile.writeDouble ("GRAFIK", "GridSize", ObjGridSize);
  ObjWireframe = view->isWireOn ();
  IniFile::DefIniFile.writeBool   ("GRAFIK", "Wireframe", ObjWireframe);
  ObjAntialiasing = view->isSmoothOn ();
  IniFile::DefIniFile.writeBool   ("GRAFIK", "Antialiasing", ObjAntialiasing);
  ObjFogging = view->isFogOn ();
  IniFile::DefIniFile.writeBool   ("GRAFIK", "Fogging", ObjFogging);
  ObjFogDensity = view->FogDensity ();
  IniFile::DefIniFile.writeDouble ("GRAFIK", "FogDensity", ObjFogDensity);
  ObjLighting = view->isLightOn ();
  IniFile::DefIniFile.writeBool   ("GRAFIK", "Lighting", ObjLighting);

  ObjLightPos = view->Light ()->Position ();
  sprintf (DlgBuffer, " %4.2f %4.2f %4.2f", ObjLightPos.X(), ObjLightPos.Y(), ObjLightPos.Z());
  IniFile::DefIniFile.writeString ("GRAFIK", "LightPosition", DlgBuffer);
  ObjLightDir = view->Light ()->Direction ();
  sprintf (DlgBuffer, " %4.2f %4.2f %4.2f", ObjLightDir.X(), ObjLightDir.Y(), ObjLightDir.Z());
  IniFile::DefIniFile.writeString ("GRAFIK", "LightDirection", DlgBuffer);
  ObjBgColor = view->BgColor ();
  sprintf (DlgBuffer, " %4.2f %4.2f %4.2f", ObjBgColor.Col[0], ObjBgColor.Col[1], ObjBgColor.Col[2]);
  IniFile::DefIniFile.writeString ("GRAFIK", "BackgroundColor", DlgBuffer);
  Vec3D CamPos = view->Camera ()->CameraPos ();
  sprintf (DlgBuffer, " %4.2f %4.2f %4.2f", CamPos.X(), CamPos.Y(), CamPos.Z());
  IniFile::DefIniFile.writeString ("GRAFIK", "CamPosition", DlgBuffer);
  Vec3D CamFocus = view->Camera ()->Focus ();
  sprintf (DlgBuffer, " %4.2f %4.2f %4.2f", CamFocus.X(), CamFocus.Y(), CamFocus.Z());
  IniFile::DefIniFile.writeString ("GRAFIK", "CamFocus", DlgBuffer);
  Vec3D CamUp = view->Camera ()->CameraUp ();
  sprintf (DlgBuffer, " %4.2f %4.2f %4.2f", CamUp.X(), CamUp.Y(), CamUp.Z());
  IniFile::DefIniFile.writeString ("GRAFIK", "CamUp", DlgBuffer);
  ObjViewPoint = ViewPoint (CamPos, CamFocus, CamUp);
  view->removeViewPoint (Ustring ("Default"));
  view->addViewPoint (Ustring ("Default"), ObjViewPoint);
  
  const  Map<Ustring, ViewPoint>& vp (view->ViewPoints());
  for (Ustring* vpName = vp.First(); vp() ; vpName = vp.Next ()) {
     if (*vpName->str() >= '1' && *vpName->str() <= '9') {
      sprintf (DlgBuffer, " %4.2f %4.2f %4.2f", vp()->CameraPos().X(), vp()->CameraPos().Y(), vp()->CameraPos().Z());
      sprintf(NameBuffer, "CamPosition%c",*vpName->str());
      IniFile::DefIniFile.writeString ("GRAFIK", NameBuffer, DlgBuffer);
      sprintf (DlgBuffer, " %4.2f %4.2f %4.2f", vp()->Focus().X(), vp()->Focus().Y(), vp()->Focus().Z());
      sprintf(NameBuffer, "CamFocus%c",*vpName->str());
      IniFile::DefIniFile.writeString ("GRAFIK", NameBuffer, DlgBuffer);
      sprintf (DlgBuffer, " %4.2f %4.2f %4.2f",  vp()->CameraUp().X(), vp()->CameraUp().Y(), vp()->CameraUp().Z());
      sprintf(NameBuffer, "CamUp%c",*vpName->str());
      IniFile::DefIniFile.writeString ("GRAFIK", NameBuffer, DlgBuffer);
    
      cout << " Viewpoint " << *vpName << endl;
      cout << " CamPos "<< vp()->CameraPos().X() << " " << vp()->CameraPos().Y() << " " << vp()->CameraPos().Z() << endl;
     }
  }
}

/*static*/ void SFXViewHandler::hangUpObject (GeoObject* gObj) {
  const DynArray<ToglView> v (MyViewHandler->ObjViews);
  for (v.First (); v (); v++)
    if (v ()->Camera ()->CameraObject () == gObj) {
      v ()->Camera ()->setToGlobal ();
      v ()->MySpace()->MySelection ()->remove (*gObj);
     ((SFXCallback*) v ()->Callback ())->setToStandard ();
    }
}

/*static*/ int SFXViewHandler::ViewDialog (ClientData cD, Tcl_Interp */*interp*/,
                                           int argc, const char *argv[]) {
  SFXViewHandler* vh = (SFXViewHandler*) cD;
  if (argc > 2) {
    ToglView* view = NULL;
    for (vh->ObjViews.First (); vh->ObjViews (); vh->ObjViews++)
      if (!strcmp (vh->ObjViews ()->WidgetName (), argv[2])) {
        view = vh->ObjViews ();
        break;
      }
    if (!view) {
      Msg.Warning ("SFXViewHandler::ViewDialog", "Can't find WidgetName >%s<", argv[2]);
      return TCL_ERROR;
    }
    if (*argv[1] == 'M') {
      if (!strcmp ("MouseDefault", argv[1])) {
        if (view) vh->setCamToDefault (view);
      }
      else if (!strcmp ("MouseWalk", argv[1])) {
        if (view) {
         vh->setCamToWalk (view);
         unsigned i = 0;      
         while(!baustein[i]) i++;
         GeoObject *go = baustein[i]->GibGeoObject();
         
         WrapBox box;
         box.adjust (go->WrapForParent ());
        // Vec3D distance = Vec3D (view->Camera ()->ViewDir ().unit () *
           Vec3D distance = Vec3D (EX *
                          (((box.Max - box.Min)).len () /
                            (Angle (view->Camera ()->VisualAngle ()).tan ())));
         view->Camera ()->setCamera (Vec3D((go->Pos () - distance).X(),(go->Pos () - distance).Y(),2.0), Vec3D(go->Pos ().X(),go->Pos ().Y(),2.0),EZ);
      
         view->flush();
        }
      }
      else if (!strcmp ("MouseZoom", argv[1])) {
        if (view) vh->setCamToZoom (view);
      }
      else if (!strcmp ("MouseLight", argv[1])) {
        if (view) vh->setCamToLight (view);
      }
    }
    else if (*argv[1] == 'C') {
      if (!strcmp ("CamToTempObject", argv[1])) {
        if (view) {
          GeoObject* go;
          sscanf (argv[3], "%p", &go);
          if (MySFXModel->Temporaries ().findKey (*go))
            vh->setCamToTempObj (view, go);
        }
      }
      else if (!strcmp ("CamToPermObject", argv[1])) {
        if (view) {
          GeoObject* go;
          sscanf (argv[3], "%p", &go);
          vh->setCamToPermObj (view, go);
        }
      }
    }
    else if (!strcmp ("ViewDefault", argv[1])) {
      if (view) vh->setViewToDefault (view);
    }
    
    else if (!strcmp ("SaveViewPoint", argv[1])) {
      if (view) {
         
         view->removeViewPoint (Ustring(argv[4]));
         view->addViewPoint (Ustring(argv[4]), ViewPoint (view->Camera ()->CameraPos (), view->Camera ()->Focus (), view->Camera ()->CameraUp ()));
      }
    }

   else if (!strcmp ("ShowViewPoint", argv[1])) {
      if (view) vh->setViewToViewpoint(view,Ustring(argv[4]));  
    }
    
    else if (!strcmp ("KeyPress-w", argv[1])) {
      if (view){  
         view->Camera ()->walk(1.0);
         view->flush ();
      }
    }
    else if (!strcmp ("KeyPress-s", argv[1])) {
      if (view){  
         view->Camera ()->walk(-1.00);
         view->flush ();
      }
    }
    else if (!strcmp ("KeyPress-a", argv[1])) {
      if (view){  
         view->Camera ()->rotateCamera (Angle (2.0), 0.0);
         view->flush ();
      }
    }
    else if (!strcmp ("KeyPress-d", argv[1])) {
      if (view){  
         view->Camera ()->rotateCamera (Angle (-2.0), 0.0);
         view->flush ();
      }
    }
    else if (!strcmp ("KeyPress-BildHoch", argv[1])) {
      if (view) {
         view->Camera ()->move(Vec3D(0.0,0.0,0.5));
         view->flush ();
      }  
    }
    else if (!strcmp ("KeyPress-BildRunter", argv[1])) {
      if (view) {
         view->Camera ()->move(Vec3D(0.0,0.0,-0.5));
         view->flush ();
      }
    }
    
    
    else if (!strcmp ("ObjectToFocus", argv[1])) {
      if (view) {
        GeoObject* go;
        sscanf (argv[3], "%p", &go);
        vh->setObjectToFocus (view, go);
      }
    }
    else if (!strcmp ("SaveSettings", argv[1])) {
      vh->saveSettings (view);
    }
    else if (!strcmp ("Quit", argv[1])) {
      if (vh->ObjViews.First () != view || vh->ObjViews.Count () == 1)
        vh->removeView (view);
      else
        Msg.Warning ("SFXViewHandler::ViewDialog",
                     "Die Hauptansicht muss als letzte Ansicht geschlossen werden!");
    }
    else {
      return TCL_ERROR;
    }
    return TCL_OK;
  }
  return TCL_ERROR;
}

/*static*/ int SFXViewHandler::ContextDialog (ClientData cD, Tcl_Interp */*interp*/,
                                              int argc, const char *argv[]) {
  SFXViewHandler* vh = (SFXViewHandler*) cD;
  if (argc > 1) {
    if (*argv[1] == 'P') {
      if (!strcmp ("PermState", argv[1])) {
        SFXPermStateDlg::create (baustein [atoi (argv[2])], vh->ObjDlgHandler);
      }
      else if (!strcmp ("PermControl", argv[1])) {
        SFXPermControlDlg::create (baustein [atoi (argv[2])], vh->ObjDlgHandler);
      }
      else if (!strcmp ("PermUserData", argv[1])) {
        SFXPermUserDataDlg::create (baustein [atoi (argv[2])], vh->ObjDlgHandler);
      }
      else if (!strcmp ("PermPara", argv[1])) {
//        SFXPermStateDlg::create (baustein [atoi (argv[2])], vh->ObjDlgHandler);
      }
      else if (!strcmp ("PermLocking", argv[1])) {
        baustein [atoi (argv[2])]->sperrungEinleiten ();
      }
      else if (!strcmp ("PermActivating", argv[1])) {
        baustein [atoi (argv[2])]->aktivieren (0);
      }
    }
    else if (*argv[1] == 'T') {
      if (!strcmp ("TempState", argv[1])) {
        GeoObject* go;
        sscanf (argv[2], "%p", &go);
        typTransportEinheit* w = MySFXModel->Temporaries ().findKey (*go);
        if (w) SFXTempDialog::create (w, vh->ObjDlgHandler);
      }
      else if (!strcmp ("TempUserData", argv[1])) {
        GeoObject* go;
        sscanf (argv[2], "%p", &go);
        typTransportEinheit* w = MySFXModel->Temporaries ().findKey (*go);
        if (w) SFXTempUserDataDialog::create (w, vh->ObjDlgHandler);
      }
    }
    else if (!strcmp ("RouteState", argv[1])) {
      GeoObject* go;
      sscanf (argv[2], "%p", &go);
      typTransportEinheit* w = MySFXModel->Temporaries ().findKey (*go);
      if (w) SFXRouteDialog::create (w->TransportRoute (), vh->ObjDlgHandler);
    }
    else if (*argv[1] == 'S') {
      if (!strcmp ("SetVals", argv[1])) {
        SFXBaseDialog* dlg = vh->ObjDlgHandler->findDialog (Ustring (argv[2]));
        if (dlg) dlg->setVals ();
      }
      else if (!strcmp ("StartWorkSchedule", argv[1])) {
        typArbeitsplan* a = MySFXModel->findWorkSchedule (atoi (argv[2]));
        if (a)
          bestelleArbeitsplan (a->Nummer (), 
            a->Vorgaenge ().First ()->ZielBaustein ()->Nummer ());
      }
    }
    else if (!strcmp ("WorkScheduleState", argv[1])) {
      GeoObject* go;
      sscanf (argv[2], "%p", &go);
      typTransportEinheit* w = MySFXModel->Temporaries ().findKey (*go);
      if (w) SFXWorkScheduleDialog::create (w->Arbeitsplan (), vh->ObjDlgHandler);
    }
    else if (!strcmp ("Quit", argv[1])) {
      SFXBaseDialog* dlg = vh->ObjDlgHandler->findDialog (Ustring (argv[2]));
      if (dlg) dlg->dispose ();
    }
    else {
      return TCL_ERROR;
    }
    return TCL_OK;
  }
  return TCL_ERROR;
}

//==================================================================
//		Declaration
//		for class SFXVDialogHandler
//==================================================================

SFXDialogHandler::SFXDialogHandler (const SFXModel& model)
 : ObjDialoge    (2),
   ObjTiming     (1000), // 1000 millisecs = 1 sec!!!
   ObjModel      ((SFXModel*) &model),
   ObjTimerToken (NULL)
 { }

SFXDialogHandler::~SFXDialogHandler () {
  if (ObjTimerToken) Tcl_DeleteTimerHandler (ObjTimerToken);
  while (ObjDialoge.Last ()) ObjDialoge.Last ()->dispose ();
}

SFXBaseDialog* SFXDialogHandler::findDialog (const Ustring& widgetName) const {
  for (ObjDialoge.First (); ObjDialoge (); ObjDialoge++)
    if (ObjDialoge ()->WidgetName () == widgetName) return ObjDialoge ();
  return NULL;
}


void SFXDialogHandler::addDialog (const SFXBaseDialog& dlg) {
  ObjDialoge.append (dlg);
  if (!ObjTimerToken)
    ObjTimerToken = Tk_CreateTimerHandler (ObjTiming, updateTiming, (ClientData) this);
}

void SFXDialogHandler::removeDialog (const SFXBaseDialog& dlg) {
  ObjDialoge.remove (dlg);
  if (ObjDialoge.isEmpty () && ObjTimerToken) {
    Tcl_DeleteTimerHandler (ObjTimerToken);
    ObjTimerToken = NULL;
  }
}

unsigned SFXDialogHandler::Timing () const {
  return ObjTiming;
}

unsigned SFXDialogHandler::setTiming (unsigned time) {
  return (ObjTiming = time);
}

/*static*/ void SFXDialogHandler::updateTiming (ClientData cd) {
  SFXDialogHandler* who = (SFXDialogHandler*) cd;
  for (who->ObjDialoge.First (); who->ObjDialoge (); who->ObjDialoge++)
    who->ObjDialoge ()->update ();
  if (who->ObjTimerToken)
    who->ObjTimerToken = Tk_CreateTimerHandler (who->ObjTiming, updateTiming, (ClientData) who);
}

//==================================================================
//		Declarations
//		for the Dialog classes
//==================================================================

SFXBaseDialog::SFXBaseDialog (SFXDialogHandler* dlgHandler)
 : ObjWidgetName (),
   ObjDlgHandler (dlgHandler),
   ObjVarNames   (8) {
  ObjDlgHandler->addDialog (*this);
}

SFXBaseDialog::~SFXBaseDialog () {
  Tk_DestroyWindow (Tk_NameToWindow (SFXInterp, ObjWidgetName.str (),
                    Tk_MainWindow (SFXInterp)));
  int last = ObjVarNames.Last ();
  for (int i = 0; i <= last; i++) {
    if (ObjVarNames[i]) {
      Tcl_UnsetVar (SFXInterp, ObjVarNames[i]->str (), TCL_GLOBAL_ONLY);
      delete ObjVarNames[i];
    }
  }
  ObjDlgHandler->removeDialog (*this);
}

const Ustring& SFXBaseDialog::WidgetName () const {
  return ObjWidgetName;
}

/*virtual*/ void SFXBaseDialog::dispose () {
  delete this;
}

//==================================================================

SFXPermDialog::SFXPermDialog (typBaustein* perm, SFXDialogHandler* dlgHandler)
 : SFXBaseDialog (dlgHandler),
   ObjPermanent  (perm)
 { }

//==================================================================

/*static*/ Ustring 
  SFXPermStateDlg::ClassTerms ("{WechslZ Zustand Meldung Bestellung Belegung Buchung");

/*static*/ SFXBaseDialog* SFXPermStateDlg::create (typBaustein* perm, SFXDialogHandler* dlgHandler) {
  Ustring n (".permStateDlg");
  n += Ustring (perm->Nummer ());
  SFXBaseDialog* d = dlgHandler->findDialog (n);
  if (d) {
    sprintf (DlgBuffer, "focus %s", n.str ());
    Tcl_GlobalEval (SFXInterp, DlgBuffer);
    return d;
  }
  else return new SFXPermStateDlg (perm, dlgHandler);
}

/*virtual*/ void SFXPermStateDlg::update  () const {
  Tcl_SetVar (SFXInterp, ObjVarNames[0]->str (), Ustring (ObjPermanent->ZustandZeit ()).str (), TCL_GLOBAL_ONLY);
  Tcl_SetVar (SFXInterp, ObjVarNames[1]->str (), ObjPermanent->ZustandTxt ().str (), TCL_GLOBAL_ONLY);
  Tcl_SetVar (SFXInterp, ObjVarNames[2]->str (), Ustring (ObjPermanent->AnzahlMeldungen ()).str (), TCL_GLOBAL_ONLY);
  Tcl_SetVar (SFXInterp, ObjVarNames[3]->str (), Ustring (ObjPermanent->AnzahlArbeitsliste ()).str (), TCL_GLOBAL_ONLY);
  Tcl_SetVar (SFXInterp, ObjVarNames[4]->str (), Ustring (ObjPermanent->Belegung ()).str (), TCL_GLOBAL_ONLY);
  Tcl_SetVar (SFXInterp, ObjVarNames[5]->str (), Ustring (ObjPermanent->Buchung ()).str (), TCL_GLOBAL_ONLY);
  unsigned i = 6;
  if (ObjPermanent->AuslGeschichte ())
    Tcl_SetVar (SFXInterp, ObjVarNames[i++]->str (), Ustring (ObjPermanent->AuslGeschichte ()->Mittel ()).str (), TCL_GLOBAL_ONLY);
  if (ObjPermanent->BelGeschichte ())
    Tcl_SetVar (SFXInterp, ObjVarNames[i++]->str (), Ustring (ObjPermanent->BelGeschichte ()->Mittel ()).str (), TCL_GLOBAL_ONLY);
  if (ObjPermanent->StoerGeschichte ())
    Tcl_SetVar (SFXInterp, ObjVarNames[i]->str (), Ustring (ObjPermanent->StoerGeschichte ()->Mittel ()).str (), TCL_GLOBAL_ONLY);
}

SFXPermStateDlg::SFXPermStateDlg  (typBaustein* perm, SFXDialogHandler* dlgHandler)
 : SFXPermDialog (perm, dlgHandler) {
  ObjWidgetName = ".permStateDlg";
  ObjWidgetName += Ustring (perm->Nummer ());
  unsigned i = 0;
  for ( ; i < 6; i++) {
    sprintf (DlgBuffer, "sfxVal(%s%d)", ObjWidgetName.str (), i);
    ObjVarNames[i] = new Ustring (DlgBuffer);
  }
  sprintf (DlgBuffer, "sfxVal(%s%d)", ObjWidgetName.str (), i);
  if (ObjPermanent->AuslGeschichte ())
   ObjVarNames[i++] = new Ustring (DlgBuffer);
  sprintf (DlgBuffer, "sfxVal(%s%d)", ObjWidgetName.str (), i);
  if (ObjPermanent->BelGeschichte ())
   ObjVarNames[i++] = new Ustring (DlgBuffer);
  sprintf (DlgBuffer, "sfxVal(%s%d)", ObjWidgetName.str (), i);
  if (ObjPermanent->StoerGeschichte ())
   ObjVarNames[i] = new Ustring (DlgBuffer);
  sprintf (DlgBuffer, "makeSFXDialog %s \"Baustein %d\" Bausteinstatus %s",
           ObjWidgetName.str (), perm->Nummer (), ClassTerms.str ());
  if (ObjPermanent->AuslGeschichte ())  strcat (DlgBuffer, " Auslastung");
  if (ObjPermanent->BelGeschichte ())   strcat (DlgBuffer, " Belegung");
  if (ObjPermanent->StoerGeschichte ()) strcat (DlgBuffer, " Stoerung");
  strcat (DlgBuffer,"}");
  if (Tcl_GlobalEval (SFXInterp, DlgBuffer) == TCL_ERROR)
    Msg.Warning ("SFXPermStateDlg::SFXPermStateDlg", "TCL_ERROR: %s", SFXInterp->result);
  update ();
}

//==================================================================

/*static*/ Ustring 
  SFXPermControlDlg::ClassTermsWithAvis ("{Strategie Prioritaet DirAvisSoll "
                                         "DirAvisIst IndAvisSoll IndAvisIst}");

/*static*/ Ustring 
  SFXPermControlDlg::ClassTermsWithoutAvis ("{Strategie Prioritaet}");

/*static*/ SFXBaseDialog* SFXPermControlDlg::create (typBaustein* perm, SFXDialogHandler* dlgHandler) {
  Ustring n (".permAvisDlg");
  n += Ustring (perm->Nummer ());
  SFXBaseDialog* d = dlgHandler->findDialog (n);
  if (d) {
    sprintf (DlgBuffer, "focus %s", n.str ());
    Tcl_GlobalEval (SFXInterp, DlgBuffer);
    return d;
  }
  else return new SFXPermControlDlg (perm, dlgHandler);
}

/*virtual*/ void SFXPermControlDlg::update  () const {
  if (ObjAvis) {
    Tcl_SetVar (SFXInterp, ObjVarNames[3]->str (), Ustring (ObjAvis->DirIstAnzahl ()).str (), TCL_GLOBAL_ONLY);
    Tcl_SetVar (SFXInterp, ObjVarNames[5]->str (), Ustring (ObjAvis->IndIstAnzahl ()).str (), TCL_GLOBAL_ONLY);
  }
}

/*virtual*/ void SFXPermControlDlg::setVals () const {
  const char* val;
  val = Tcl_GetVar (SFXInterp, ObjVarNames[0]->str (), TCL_GLOBAL_ONLY);
  ObjPermanent->setStrategie (atoi (val));
  val = Tcl_GetVar (SFXInterp, ObjVarNames[1]->str (), TCL_GLOBAL_ONLY);
  ObjPermanent->setPrioritaet (atoi (val));
  if (ObjAvis) {
    val = Tcl_GetVar (SFXInterp, ObjVarNames[2]->str (), TCL_GLOBAL_ONLY);
    ObjAvis->setDirSollAnzahl (atoi (val));
    val = Tcl_GetVar (SFXInterp, ObjVarNames[4]->str (), TCL_GLOBAL_ONLY);
    ObjAvis->setIndSollAnzahl (atoi (val));
  }
}

SFXPermControlDlg::SFXPermControlDlg  (typBaustein* perm, SFXDialogHandler* dlgHandler)
 : SFXPermDialog (perm, dlgHandler),
  ObjAvis (perm->Avis ()) {
  ObjWidgetName = ".permControlDlg";
  ObjWidgetName += Ustring (perm->Nummer ());
  unsigned limit = (ObjAvis ? 6 : 2);
  for (unsigned i = 0; i < limit; i++) {
    sprintf (DlgBuffer, "sfxVal(%s%d)", ObjWidgetName.str (), i);
    ObjVarNames[i] = new Ustring (DlgBuffer);
  }
  sprintf (DlgBuffer, "makeSFXDialog %s \"Baustein %d\" Steuerparameter %s",
           ObjWidgetName.str (), perm->Nummer (),
           (ObjAvis ? ClassTermsWithAvis.str () : ClassTermsWithoutAvis.str ()));
  if (Tcl_GlobalEval (SFXInterp, DlgBuffer) == TCL_ERROR)
    Msg.Warning ("SFXPermControlDlg::SFXPermControlDlg", "TCL_ERROR: %s",
                  SFXInterp->result);

  Tcl_SetVar (SFXInterp, ObjVarNames[0]->str (), Ustring (ObjPermanent->Strategie ()).str (), TCL_GLOBAL_ONLY);
  sprintf (DlgBuffer, "%s.frame0.wert configure -state normal -bg white; "
                      "bind %s.frame0.wert <Return> {SFXContext SetVals %s; "
                      "focus [tk_focusNext %%W]}",
                       ObjWidgetName.str (), ObjWidgetName.str (), ObjWidgetName.str ());
  Tcl_GlobalEval (SFXInterp, DlgBuffer);
  Tcl_SetVar (SFXInterp, ObjVarNames[1]->str (), Ustring (ObjPermanent->Prioritaet ()).str (), TCL_GLOBAL_ONLY);
  sprintf (DlgBuffer, "%s.frame1.wert configure -state normal -bg white; "
                      "bind %s.frame1.wert <Return> {SFXContext SetVals %s; "
                      "focus [tk_focusNext %%W]}",
                       ObjWidgetName.str (), ObjWidgetName.str (), ObjWidgetName.str ());
  Tcl_GlobalEval (SFXInterp, DlgBuffer);
  if (ObjAvis) {
    Tcl_SetVar (SFXInterp, ObjVarNames[2]->str (), Ustring (ObjAvis->DirSollAnzahl ()).str (), TCL_GLOBAL_ONLY);
    sprintf (DlgBuffer, "%s.frame2.wert configure -state normal -bg white; "
                        "bind %s.frame2.wert <Return> {SFXContext SetVals %s; "
                        "focus [tk_focusNext %%W]}",
                         ObjWidgetName.str (), ObjWidgetName.str (), ObjWidgetName.str ());
    Tcl_GlobalEval (SFXInterp, DlgBuffer);
    Tcl_SetVar (SFXInterp, ObjVarNames[4]->str (), Ustring (ObjAvis->IndSollAnzahl ()).str (), TCL_GLOBAL_ONLY);
    sprintf (DlgBuffer, "%s.frame4.wert configure -state normal -bg white; "
                        "bind %s.frame4.wert <Return> {SFXContext SetVals %s; "
                        "focus [tk_focusNext %%W]}",
                         ObjWidgetName.str (), ObjWidgetName.str (), ObjWidgetName.str ());
    Tcl_GlobalEval (SFXInterp, DlgBuffer);
  }
  update ();
}

//==================================================================

/*static*/ SFXBaseDialog* SFXPermUserDataDlg::create (typBaustein* perm, SFXDialogHandler* dlgHandler) {
  Ustring n (".permUserDataDlg");
  n += Ustring (perm->Nummer ());
  SFXBaseDialog* d = dlgHandler->findDialog (n);
  if (d) {
    sprintf (DlgBuffer, "focus %s", n.str ());
    Tcl_GlobalEval (SFXInterp, DlgBuffer);
    return d;
  }
  else return new SFXPermUserDataDlg (perm, dlgHandler);
}

/*virtual*/ void SFXPermUserDataDlg::update  () const {
  UserData* ud = ObjPermanent->getUserData ();
  if (ud) {
    char *paras  = ud->ParaString ();
    char parastr[100];
    char *tok = strtok (paras, " ");
    if (tok) strcpy (parastr, tok);
    int count = ObjVarNames.Count ();
    for (int i = 0; i < count; i++) {
      Tcl_SetVar (SFXInterp, ObjVarNames[i]->str (), parastr, TCL_GLOBAL_ONLY);
      tok = strtok (NULL, " ");
      if (tok) strcpy (parastr, tok);
    }
  }
}

SFXPermUserDataDlg::SFXPermUserDataDlg (typBaustein* perm, SFXDialogHandler* dlgHandler)
 : SFXPermDialog (perm, dlgHandler) {
  ObjWidgetName = ".permUserDataDlg";
  ObjWidgetName += Ustring (perm->Nummer ());
  UserData* ud = ObjPermanent->getUserData ();
  if (ud) {
    char *labels  = ud->LabelString ();
    Ustring label = labels;
    char *labelstr = new char [strlen (labels) + 5];
    char *tok = strtok (labels, " ");
    if (tok) strcpy (labelstr, tok);
    unsigned i = 0;
    while (tok) {
      sprintf (DlgBuffer, "sfxVal(%s%d)", ObjWidgetName.str (), i);
      ObjVarNames[i++] = new Ustring (DlgBuffer);
      tok = strtok (NULL, " ");
      if (tok) strcpy (labelstr, tok);
    }
    sprintf (DlgBuffer, "makeSFXDialog %s \"Baustein %d\" USERDATA {%s}",
      ObjWidgetName.str (), perm->Nummer (), label.str ());
    if (Tcl_GlobalEval (SFXInterp, DlgBuffer) == TCL_ERROR)
      Msg.Warning ("SFXPermUserDataDlg::SFXPermUserDataDlg", "TCL_ERROR: %s", SFXInterp->result);
    update ();
    delete labelstr;
  }
}

//==================================================================

/*static*/ Ustring 
  SFXTempDialog::ClassTerms ("{Ziel Station Laufzeit ArbPlan DLZ Artikel Menge "
                             "Vorgang VorgangsZeit Programm}");

/*static*/ SFXBaseDialog* SFXTempDialog::create (typTransportEinheit* temp, SFXDialogHandler* dlgHandler) {
  Ustring n (".tempStateDlg");
  n += Ustring (temp->ID ());
  SFXBaseDialog* d = dlgHandler->findDialog (n);
  if (d) {
    sprintf (DlgBuffer, "focus %s", n.str ());
    Tcl_GlobalEval (SFXInterp, DlgBuffer);
    return d;
  }
  else return new SFXTempDialog (temp, dlgHandler);
}

/*virtual*/ void SFXTempDialog::update  () const {
  if (MySFXModel->Temporaries ().find (*ObjTemporary) && ObjTemporary->Station ()) {
    typVorgang* v = ObjTemporary->Vorgang ();
    Tcl_SetVar (SFXInterp, ObjVarNames[0]->str (), Ustring (v->ZielBaustein ()->Nummer ()).str (), TCL_GLOBAL_ONLY);
    Tcl_SetVar (SFXInterp, ObjVarNames[1]->str (), Ustring (ObjTemporary->Station ()->Nummer ()).str (), TCL_GLOBAL_ONLY);
    Tcl_SetVar (SFXInterp, ObjVarNames[2]->str (), Ustring (ObjTemporary->Laufzeit ().inMinutes ()).str (), TCL_GLOBAL_ONLY);
    Tcl_SetVar (SFXInterp, ObjVarNames[3]->str (), Ustring (ObjTemporary->Arbeitsplan ()->Nummer ()).str (), TCL_GLOBAL_ONLY);
    Tcl_SetVar (SFXInterp, ObjVarNames[4]->str (), ObjTemporary->Arbeitsplan ()->DlzRegister ()
                                                           ? Ustring (ObjTemporary->Arbeitsplan ()->DlzRegister ()->Mittel ()).str ()
                                                           : Ustring ("unknown").str (), TCL_GLOBAL_ONLY);
    Tcl_SetVar (SFXInterp, ObjVarNames[5]->str (), Ustring (ObjTemporary->Artikel ()).str (), TCL_GLOBAL_ONLY);
    Tcl_SetVar (SFXInterp, ObjVarNames[6]->str (), Ustring (ObjTemporary->Menge ()).str (), TCL_GLOBAL_ONLY);
    Tcl_SetVar (SFXInterp, ObjVarNames[7]->str (), Ustring (v->Nummer ()).str (), TCL_GLOBAL_ONLY);
    Tcl_SetVar (SFXInterp, ObjVarNames[8]->str (), Ustring (v->Dauer ().inMinutes ()).str (), TCL_GLOBAL_ONLY);
    Tcl_SetVar (SFXInterp, ObjVarNames[9]->str (), Ustring (v->ProgNr ()).str (), TCL_GLOBAL_ONLY);
  }
  else {
    sprintf (DlgBuffer, "wm title %s \"Leaves System\"", ObjWidgetName.str ());
    Tcl_GlobalEval (SFXInterp, DlgBuffer);
  }
}

SFXTempDialog::SFXTempDialog (typTransportEinheit* temp, SFXDialogHandler* dlgHandler)
 : SFXBaseDialog (dlgHandler),
   ObjTemporary  (temp) {
  ObjWidgetName = ".tempStateDlg";
  ObjWidgetName += Ustring (temp->ID ());
  for (unsigned i = 0; i < 10; i++) {
    sprintf (DlgBuffer, "sfxVal(%s%d)", ObjWidgetName.str (), i);
    ObjVarNames[i] = new Ustring (DlgBuffer);
  }
  sprintf (DlgBuffer, "makeSFXDialog %s \"Transporteinheit %d\" TEStatus %s",
                       ObjWidgetName.str (), temp->ID (), ClassTerms.str ());
  if (Tcl_GlobalEval (SFXInterp, DlgBuffer) == TCL_ERROR)
    Msg.Warning ("SFXTempDialog::SFXTempDialog", "TCL_ERROR: %s", SFXInterp->result);
  update ();
}

//==================================================================

/*static*/ SFXBaseDialog* SFXTempUserDataDialog::create (typTransportEinheit* temp, SFXDialogHandler* dlgHandler) {
  Ustring n (".tempUserDataDlg");
  n += Ustring (temp->ID ());
  SFXBaseDialog* d = dlgHandler->findDialog (n);
  if (d) {
    sprintf (DlgBuffer, "focus %s", n.str ());
    Tcl_GlobalEval (SFXInterp, DlgBuffer);
    return d;
  }
  else return new SFXTempUserDataDialog (temp, dlgHandler);
}
           
/*virtual*/ void SFXTempUserDataDialog::update  () const {
  UserData* ud = ObjTemporary->getUserData ();
  if (ud) { 
    char *paras  = ud->ParaString ();
    char parastr[100];
    char *tok = strtok (paras, " ");
    if (tok) strcpy (parastr, tok);
    int count = ObjVarNames.Count ();
    for (int i = 0; i < count; i++) {
      Tcl_SetVar (SFXInterp, ObjVarNames[i]->str (), parastr, TCL_GLOBAL_ONLY);
      tok = strtok (NULL, " ");
      if (tok) strcpy (parastr, tok);
    }
  }
}

SFXTempUserDataDialog::SFXTempUserDataDialog (typTransportEinheit* temp,
                                              SFXDialogHandler* dlgHandler)
 : SFXBaseDialog (dlgHandler),
   ObjTemporary  (temp) {
  ObjWidgetName = ".tempUserDataDlg";
  ObjWidgetName += Ustring (temp->ID ());
  UserData* ud = ObjTemporary->getUserData ();
  if (ud) {
    char *labels  = ud->LabelString ();
    Ustring label = labels;
    char *labelstr = new char [strlen (labels) + 5];
    char *tok = strtok (labels, " ");
    if (tok) strcpy (labelstr, tok);
    unsigned i = 0;
    while (tok) {
      sprintf (DlgBuffer, "sfxVal(%s%d)", ObjWidgetName.str (), i);
      ObjVarNames[i++] = new Ustring (DlgBuffer);
      tok = strtok (NULL, " ");
      if (tok) strcpy (labelstr, tok);
    }
    sprintf (DlgBuffer, "makeSFXDialog %s \"Transporteinheit %d\" USERDATA {%s}",
             ObjWidgetName.str (), temp->ID (), label.str ());
    if (Tcl_GlobalEval (SFXInterp, DlgBuffer) == TCL_ERROR)
      Msg.Warning ("SFXTempUserDataDlg::SFXTempUserDataDlg", "TCL_ERROR: %s", SFXInterp->result);
    update ();
    delete labelstr;
  }
}

//==================================================================

/*static*/ Ustring 
  SFXRouteDialog::ClassTerms ("{Start Ziel Teile}");

/*static*/ SFXBaseDialog* SFXRouteDialog::create (typTransportRoute* route, SFXDialogHandler* dlgHandler) {
  Ustring n (".routeStateDlg");
  n += Ustring (route->Nummer ());
  SFXBaseDialog* d = dlgHandler->findDialog (n);
  if (d) {
    sprintf (DlgBuffer, "focus %s", n.str ());
    Tcl_GlobalEval (SFXInterp, DlgBuffer);
    return d;
  }
  else return new SFXRouteDialog (route, dlgHandler);
}

/*virtual*/ void SFXRouteDialog::update  () const {
  Tcl_SetVar (SFXInterp, ObjVarNames[0]->str (), Ustring (ObjRoute->Stationen ().First ()->Nummer ()).str (), TCL_GLOBAL_ONLY);
  Tcl_SetVar (SFXInterp, ObjVarNames[1]->str (), Ustring (ObjRoute->Stationen ().Last ()->Nummer ()).str (), TCL_GLOBAL_ONLY);
  Tcl_SetVar (SFXInterp, ObjVarNames[2]->str (), Ustring (ObjRoute->TempEin () - ObjRoute->TempAus ()).str (), TCL_GLOBAL_ONLY);
}

SFXRouteDialog::SFXRouteDialog (typTransportRoute* route, SFXDialogHandler* dlgHandler)
 : SFXBaseDialog (dlgHandler),
   ObjRoute      (route) {
  ObjWidgetName = ".routeStateDlg";
  ObjWidgetName += Ustring (route->Nummer ());
  for (unsigned i = 0; i < 3; i++) {
    sprintf (DlgBuffer, "sfxVal(%s%d)", ObjWidgetName.str (), i);
    ObjVarNames[i] = new Ustring (DlgBuffer);
  }
  sprintf (DlgBuffer, "makeSFXDialog %s \"Route %d\" Transportroute %s",
                       ObjWidgetName.str (), ObjRoute->Nummer (), ClassTerms.str ());
  if (Tcl_GlobalEval (SFXInterp, DlgBuffer) == TCL_ERROR)
    Msg.Warning ("SFXRouteDialog::SFXRouteDialog", "TCL_ERROR: %s", SFXInterp->result);
  update ();
}

//==================================================================

/*static*/ Ustring 
  SFXWorkScheduleDialog::ClassTerms ("{WechselZeit Vorgaenge Start Ziel Teile DLZ}");

/*static*/ SFXBaseDialog* SFXWorkScheduleDialog::create (typArbeitsplan* ws, SFXDialogHandler* dlgHandler) {
  Ustring n (".wsStateDlg");
  n += Ustring (ws->Nummer ());
  SFXBaseDialog* d = dlgHandler->findDialog (n);
  if (d) {
    sprintf (DlgBuffer, "focus %s", n.str ());
    Tcl_GlobalEval (SFXInterp, DlgBuffer);
    return d;
  }
  else return new SFXWorkScheduleDialog (ws, dlgHandler);
}

/*virtual*/ void SFXWorkScheduleDialog::update  () const {
  Tcl_SetVar (SFXInterp, ObjVarNames[0]->str (), 
    Ustring (ObjWorkSchedule->Wechselzeit ().inMinutes ()).str (), TCL_GLOBAL_ONLY);
  Tcl_SetVar (SFXInterp, ObjVarNames[1]->str (), 
    Ustring (ObjWorkSchedule->Vorgaenge ().Count ()).str (), TCL_GLOBAL_ONLY);
  Tcl_SetVar (SFXInterp, ObjVarNames[2]->str (), 
    Ustring (ObjWorkSchedule->Vorgaenge ().First ()->ZielBaustein ()->Nummer ()).str (), 
             TCL_GLOBAL_ONLY);
  Tcl_SetVar (SFXInterp, ObjVarNames[3]->str (), 
    Ustring (ObjWorkSchedule->Vorgaenge ().Last ()->ZielBaustein ()->Nummer ()).str (), 
             TCL_GLOBAL_ONLY);
  Tcl_SetVar (SFXInterp, ObjVarNames[4]->str (), 
    Ustring (ObjWorkSchedule->TempEin () - ObjWorkSchedule->TempAus ()).str (), TCL_GLOBAL_ONLY);
  Tcl_SetVar (SFXInterp, ObjVarNames[5]->str (), ObjWorkSchedule->DlzRegister ()
    ? Ustring (ObjWorkSchedule->DlzRegister ()->Mittel ()).str ()
    : Ustring ("unknown").str (), TCL_GLOBAL_ONLY);
}

SFXWorkScheduleDialog::SFXWorkScheduleDialog (typArbeitsplan* ws, SFXDialogHandler* dlgHandler)
 : SFXBaseDialog   (dlgHandler),
   ObjWorkSchedule (ws) {
  ObjWidgetName = ".wsStateDlg";
  ObjWidgetName += Ustring (ws->Nummer ());
  for (unsigned i = 0; i < 6; i++) {
    sprintf (DlgBuffer, "sfxVal(%s%d)", ObjWidgetName.str (), i);
    ObjVarNames[i] = new Ustring (DlgBuffer);
  }
  sprintf (DlgBuffer, "makeSFXDialog %s \"Arbeitsplan %d\" Arbeitsplan %s",
                       ObjWidgetName.str (), ObjWorkSchedule->Nummer (), ClassTerms.str ());
  if (Tcl_GlobalEval (SFXInterp, DlgBuffer) == TCL_ERROR)
    Msg.Warning ("SFXWorkScheduleDialog::SFXWorkScheduleDialog", "TCL_ERROR: %s",
                  SFXInterp->result);
  update ();
}

//==================================================================
//		Implementation
//		for class SFXCallback
//==================================================================

class SFXCBTimerData {
  public:
    SFXCBTimerData  (SFXCallback* cb, OGLView* view) : CB (cb), View (view) {};
    ~SFXCBTimerData () {};

    SFXCallback* CB;
    OGLView*     View;
};

/*static*/ Pattern *SFXCallback::ClassRedRect;
/*static*/ unsigned SFXCallback::ClassRefCounter;
/*static*/ double SFXCallback::ClassMinViewAngle = 10.0;
/*static*/ double SFXCallback::ClassMaxViewAngle = 120.0;

/*static*/ void SFXCallback::setup () {
  Attribute *red   = ColorAttribute::create (RGBAColor("red"));
  red->setName ("_ZoomRedAttr");

  Primitive *p = LineQuad::create (Vec2D (), Vec2D (1.0, 1.0));
  p->setName ("_ZoomCubePrim");
  GeoPattern *gp = GeoPattern::create (*p, *red);
  gp->setName ("_ZoomGeoPat");

  ClassRedRect   = Pattern::create (*gp);
  ClassRedRect->setName ("_ZoomRedPat");
  ClassRedRect->incRef ();
}

/*static*/ void SFXCallback::cleanup () {
  ClassRedRect->decRef ();
  Pattern::clean ();
}

// constructor
SFXCallback::SFXCallback ()
  : OGLViewCallback    (),
    ObjStartX          (0),
    ObjStartY          (0),
    ObjDelta           (0),
    ObjCursor          (0),
    ObjTimerData       (NULL),
    ObjWalkTimer       (NULL),
    ObjZoomRect        (),
    ObjButtonHandling  (StdButton),
    ObjMotionHandling  (StdMotion),
    ObjPassiveHandling (Passive)   {
  if (!(ClassRefCounter++)) setup ();
  ObjZoomRect.insert (*(ClassRedRect));
}


SFXCallback::~SFXCallback () {
  ObjZoomRect.remove (*(ClassRedRect));
  if (!(--ClassRefCounter)) cleanup ();
}

void SFXCallback::setToStandard   () {
  ObjButtonHandling = StdButton;
  ObjMotionHandling = StdMotion;
}

void SFXCallback::setToCamSetting () {
  ObjButtonHandling = CamSetButton;
  ObjMotionHandling = CamSetMotion;
}

void SFXCallback::setToWalking () {
  ObjButtonHandling = StdButton;
  ObjMotionHandling = WalkMotion;
}

void SFXCallback::setToZooming () {
  ObjButtonHandling = ZoomButton;
  ObjMotionHandling = ZoomMotion;
}

void SFXCallback::setToLight () {
  ObjButtonHandling = StdButton;
  ObjMotionHandling = LightMotion;
}

void SFXCallback::MouseButtonCB  (OGLView* view, int button, int state, int x, int y) {
  if (view->isPosed ())
    ObjButtonHandling (this, view, button, state, x, y);
}

void SFXCallback::MouseMotionCB  (OGLView* view, int state, int x, int y) {
  if (view->isPosed ())
    ObjMotionHandling (this, view, state, x, y);
}

void SFXCallback::MousePassiveCB (OGLView* view, int x, int y) {
  if (view->isPosed ())
    ObjPassiveHandling (this, view, x, y);
}

/*static*/ void SFXCallback::walkTiming (ClientData cd) {
  SFXCBTimerData *tb = (SFXCBTimerData*) cd;
  if (tb->CB->ObjWalkTimer) {
    tb->View->Camera()->walk (tb->CB->ObjDelta);
    tb->View->flush ();
    tb->CB->ObjWalkTimer = Tk_CreateTimerHandler (200, walkTiming, (ClientData) cd);
  }
}

//==================================================================
//		Button Callbacks
//==================================================================

void SFXCallback::StdButton (SFXCallback *who, OGLView* view, int button, int state, int x, int y) {
  if (button == Button1) {            // Left-Mouse-Button
    if (state < Button1Mask) {        // Button1_Down
      who->ObjStartX = x;
      who->ObjStartY = y;
      view->doSelect (view, who->ObjSelectedObjects, x, y, 2, 2);
      if (who->ObjSelectedObjects.Count()) {
        GeoObject *target = who->ObjSelectedObjects.Last ();
        if (who->ObjCursor) {
          sprintf (DlgBuffer, "%s configure -cursor {} ", ((ToglView*)view)->WidgetName ());
          Tcl_GlobalEval (SFXInterp, DlgBuffer);
          who->ObjCursor = 0;
        }
        if (! (view->MySpace()->MySelection()->hasSelection (*target))) {
          if ((target = view->MySpace()->MySelection()->couldSelect (*target)) != NULL) {
            view->MySpace()->MySelection()->removeAll();
            view->MySpace()->MySelection()->insert (*target);
            Ustring name (((ToglView*)view)->WidgetName ());
            sprintf (DlgBuffer,
              "%s configure -cursor X_cursor; "
              "global sfxStatusText(%s); set sfxStatusText(%s) \"%s\"; update idletasks;",
              name.str (), name.str (), name.str (), StatusText (*target));
            Tcl_GlobalEval (SFXInterp, DlgBuffer);
            who->ObjCursor = 1;
          }
          else {
            view->MySpace()->MySelection()->removeAll();
          }
          view->MySpace()->flushAllViews();
        }
        who->ObjSelectedObjects.removeAll ();
      } // Count
      else if (view->MySpace()->MySelection()->hasSelection()) {
        view->MySpace()->MySelection()->removeAll();
        sprintf (DlgBuffer, "sfxStatusText(%s)", ((ToglView*)view)->WidgetName ());
        Tcl_SetVar (SFXInterp, DlgBuffer, "                          ", TCL_GLOBAL_ONLY);
        view->MySpace()->flushAllViews();
      }
    } // Button1Mask
    else
      if (who->ObjWalkTimer) {
        Tk_DeleteTimerHandler (who->ObjWalkTimer);
        delete who->ObjTimerData;
        who->ObjTimerData = NULL;
        who->ObjWalkTimer = NULL;
      }
  } //Button1

  else if (button == Button3) {
    if (state < Button3Mask) {        // Button3_Down
      view->doSelect (view, who->ObjSelectedObjects, x, y, 2, 2);
      if (who->ObjSelectedObjects.Count()) {
        GeoObject *target = view->MySpace()->MySelection()->couldSelect (*(who->ObjSelectedObjects.Last()));
        if (target) {
          if (view->MySpace()->MySelection()->hasSelection (*target)) {
            typBaustein* b = MySFXModel->Permanents ().findKey (*target);
            if (b)
              sprintf  (DlgBuffer, "SelectPermMenu %s %p %d %d %d %d ",
                       ((ToglView*)view)->WidgetName (), target, b->Nummer (),
                         x, y,
		       (b->getUserData () && b->getUserData ()->LabelString ())
                          ? 1 : 0);
            else {
              typTransportEinheit* w = MySFXModel->Temporaries ().findKey (*target);
              if (w)
                sprintf  (DlgBuffer, "SelectTempMenu %s %p %d %d %d %d %d %d ",
                       ((ToglView*)view)->WidgetName (), target, w->ID (),
                       (w->TransportRoute () ? w->TransportRoute ()->Nummer ()
                         : 0), w->Arbeitsplan ()->Nummer (), x, y,
			(w->getUserData () && w->getUserData()->LabelString ())
                         ? 1 : 0);
            }
            if (Tcl_Eval (SFXInterp, DlgBuffer) == TCL_ERROR)
              Msg.Warning ("SFXCallback::StdButton", "TCL_ERROR: %s", SFXInterp->result);
          } // hasSelection
          else {
            view->MySpace ()->MySelection ()->removeAll ();
            view->MySpace ()->MySelection ()->insert (*target);
            view->MySpace ()->flushAllViews ();
            typBaustein* b = MySFXModel->Permanents ().findKey (*target);
            if (b)
              sprintf  (DlgBuffer, "SelectPermMenu %s %p %d %d %d %d ",
                       ((ToglView*)view)->WidgetName (), target, b->Nummer (),
                         x, y, 
                       (b->getUserData () && b->getUserData ()->LabelString ())
                        ? 1 : 0);
            else {
              typTransportEinheit* w = MySFXModel->Temporaries ().findKey (*target);
              if (w)
                sprintf  (DlgBuffer, "SelectTempMenu %s %p %d %d %d %d %d %d ",
                       ((ToglView*)view)->WidgetName (), target, w->ID (),
                       (w->TransportRoute () ? 
                        w->TransportRoute ()->Nummer () : 0), 
                        w->Arbeitsplan ()->Nummer (), x, y,
 			(w->getUserData () && w->getUserData()->LabelString ())
                         ? 1 : 0);
            }
            if (Tcl_Eval (SFXInterp, DlgBuffer) == TCL_ERROR)
              Msg.Warning ("SFXCallback::StdButton", "TCL_ERROR: %s", SFXInterp->result);
          } // couldSelect
        }
        who->ObjSelectedObjects.removeAll ();
      } // Count
      else {
        if (view->MySpace()->MySelection()->hasSelection ()) {
          view->MySpace()->MySelection()->removeAll();
          view->MySpace()->flushAllViews();
        }
      }
    } // Button3Mask
  } // Button3
}

void SFXCallback::CamSetButton (SFXCallback *who, OGLView* view, int /*button*/, int state, int x, int y) {
 if (!(state < Button1Mask)) {        // Button1_Up
    if (!(view->Camera ()->CameraObject ())) {
      view->doSelect (view, who->ObjSelectedObjects, x, y, 2, 2);
      if (who->ObjSelectedObjects.Count ()) {
        if (view->MySpace ()->MySelection()->couldSelect (*(who->ObjSelectedObjects.Last ()))) {
          view->Camera ()->setToLocal (who->ObjSelectedObjects.Last ());
          who->ObjSelectedObjects.removeAll ();
          view->flush ();
        }
      }
    }
  }
}

void SFXCallback::ZoomButton (SFXCallback *who, OGLView *view, int button, int state, int x, int y) {
  if (button == Button1) {            // Left-Mouse-Button
    if (state < Button1Mask) {        // Button1_Down
      who->ObjStartX = x;
      who->ObjStartY = y;
      who->ObjZoomRect.setPos (view->Camera()->PositionFromPixels (x, y));
      who->ObjZoomRect.setXTo (view->Camera()->ViewDir ().cross (view->Camera()->CameraUp ()));
      who->ObjZoomRect.setZTo (-view->Camera()->ViewDir ());
      who->ObjZoomRect.setScale (Vec3D (0.01, 0.01, 0.01));
      who->ObjZoomRect.setParent (*(view->MySpace()));
      view->flush ();
    }
    else {                            // Button1_Up
      if (who->ObjStartX != x && who->ObjStartY != y) {
        WrapBox box;
        box.adjust (view->Camera()->PositionFromPixels (who->ObjStartX, who->ObjStartY));
        box.adjust (view->Camera()->PositionFromPixels (x, y));
        box.sort ();
        Vec3D focus = box.Min + ((box.Max - box.Min) * 0.5);
        Vec3D distance = Vec3D (view->Camera ()->ViewDir ().unit () *
                                (((box.Max - box.Min)).len () /
                                  (Angle (view->Camera ()->VisualAngle ()).tan ())));
        view->Camera ()->setCamera (focus - distance, focus, view->Camera ()->CameraUp ());
        who->ObjZoomRect.clearParent (0);
        who->setToStandard ();
        Tcl_SetVar2 (SFXInterp, "sfxMouseHandling", (char*)((ToglView*) view)->WidgetName (), "0", TCL_GLOBAL_ONLY);
        view->flush ();
      }
    }
  }
}

//==================================================================
//		Motion Callbacks
//==================================================================

void SFXCallback::StdMotion (SFXCallback *who, OGLView* view, int state, int /*x*/, int /*y*/) {
  if (state & Button1Mask && (who->ObjDeltaX  || who->ObjDeltaY)) {// Motion with Left-Mouse-Button
    if (state & ShiftMask) {                                       // with ShiftKey
      view->Camera()->move (view->Camera()->VectorFromPixels (who->ObjDeltaX, who->ObjDeltaY));
    }
    else {
      view->Camera ()->rotateFocus (Angle (who->ObjDeltaX), Angle (who->ObjDeltaY));
    }
    view->flush ();
  } // Button1Mask
  else if ((state & Button3Mask) && who->ObjDeltaY) {
    if (state & ShiftMask) {       // with ShiftKey
      double newAngle = view->Camera ()->VisualAngle () - who->ObjDeltaY;
      if (newAngle > ClassMinViewAngle && newAngle < ClassMaxViewAngle)
        view->Camera ()->setVisualAngle (newAngle);
    }
    else
      view->Camera ()->zoom (who->ObjDeltaY * 0.1);
    view->flush ();
  }
}

void SFXCallback::WalkMotion (SFXCallback *who, OGLView* view, int state, int /*x*/, int y) {
  if (state & Button1Mask) {        // Motion with Left-Mouse-Button
   // if (state & ShiftMask)          // with ShiftKey
      if (fabs (who->ObjDeltaY) > 1) {             //drehen wenn die Bewegung in
        view->Camera ()->rotateCamera (0.0, Angle (who->ObjDeltaY * 0.3));
        view->flush ();
      }
      else who->ObjDeltaY = who->ObjPrevY;
    //else if (state & ControlMask)   // with ControlKey
      if (fabs (who->ObjDeltaX) > 1) {
        view->Camera ()->rotateCamera (Angle (who->ObjDeltaX * 0.3), 0.0);
        view->flush ();
      }
      else who->ObjDeltaX = who->ObjPrevX;
    /*else {                        // kein drhen sondern bewegen
      who->ObjDelta = (int) ((who->ObjStartY - y) * 0.1);
      if (!who->ObjWalkTimer && who->ObjDelta) {
        who->ObjTimerData = new SFXCBTimerData (who, view);
        who->ObjWalkTimer = Tk_CreateTimerHandler (10, walkTiming, (ClientData) who->ObjTimerData);
      }
    }
    */
  } // Button1Mask
  /*
  else if ((state & Button3Mask) && who->ObjDeltaY) {
    if (state & ShiftMask) {       // with ShiftKey
      double newAngle = view->Camera ()->VisualAngle () - who->ObjDeltaY;
      if (newAngle > ClassMinViewAngle && newAngle < ClassMaxViewAngle)
        view->Camera ()->setVisualAngle (newAngle);
    }
    else
      
      view->Camera ()->walk(1.0);
      //view->Camera ()->zoom (who->ObjDeltaY * 0.1);
    view->flush ();
  }
   */
}

void SFXCallback::CamSetMotion (SFXCallback *who, OGLView* view, int state, int /*x*/, int /*y*/) {
  if (state & Button1Mask) {        // Button1_Down
    if (state & ShiftMask)          // with ShiftKey
      if (fabs (who->ObjDeltaY) > 3) {
        view->Camera ()->rotateCamera (0.0, Angle (who->ObjDeltaY * 0.3));
        view->flush ();
      }
      else who->ObjDeltaY = who->ObjPrevY;
    else if (state & ControlMask)   // with ControlKey
      if (fabs (who->ObjDeltaX) > 3) {
        view->Camera ()->rotateCamera (Angle (who->ObjDeltaX * 0.3), 0.0);
        view->flush ();
      }
      else who->ObjDeltaX = who->ObjPrevX;
    else if (who->ObjDeltaX  || who->ObjDeltaY) {
      view->Camera()->move (view->Camera()->VectorFromPixels (who->ObjDeltaX, who->ObjDeltaY));
      view->flush ();
    }
  }
  else if ((state & Button3Mask) && who->ObjDeltaY) {  // Button3_Down
    if (state & ShiftMask) {        // with ShiftKey
      double newAngle = view->Camera ()->VisualAngle () - who->ObjDeltaY;
      if (newAngle > ClassMinViewAngle && newAngle < ClassMaxViewAngle)
        view->Camera ()->setVisualAngle (newAngle);
    }
    else
      view->Camera ()->zoom (who->ObjDeltaY * 0.1);
    view->flush ();
  }
}

void SFXCallback::ZoomMotion  (SFXCallback *who, OGLView *view, int state, int x, int y) {
  if (state & Button1Mask) {           // Motion with Left-Mouse-Button
    if (who->ObjStartX != x || who->ObjStartY != y) {
      Vec3D xLen (view->Camera()->VectorFromPixels (fabs (x - who->ObjStartX), 0));
      Vec3D yLen (view->Camera()->VectorFromPixels (0, fabs (y - who->ObjStartY)));
      who->ObjZoomRect.setPos (view->Camera()->PositionFromPixels (Min (x, who->ObjStartX), Max (y, who->ObjStartY)));
      who->ObjZoomRect.setScale (Vec3D (xLen.len (), yLen.len (), 1.0));
      view->flush ();
    }
  }
}

void SFXCallback::LightMotion  (SFXCallback *who, OGLView* view, int state,
                                int /*x*/, int /*y*/) {
  if (state & Button1Mask && (who->ObjDeltaX  || who->ObjDeltaY)) {// Motion with Left-Mouse-Button
    if (state & ShiftMask) {                                       // with ShiftKey
      view->Camera()->move (view->Camera()->VectorFromPixels (who->ObjDeltaX, who->ObjDeltaY));
    }
    else {
      view->Camera ()->rotateFocus (Angle (who->ObjDeltaX), Angle (who->ObjDeltaY));
    }
    view->Light()->setDirection (view->Camera()->ViewDir ());
    view->Light()->setPosition (view->Camera()->CameraPos ());
    view->flush ();
  } // Button1Mask
  else if ((state & Button3Mask) && who->ObjDeltaY) {
    if (state & ShiftMask) {        // with ShiftKey
      double newAngle = view->Light ()->CutOff () - who->ObjDeltaY;
      if (newAngle > 1.0 && newAngle < 180.0)
        view->Light ()->setCutOff (newAngle);
    }
    else if (state & ControlMask) { // with ControlKey
      view->Camera ()->walk (who->ObjDeltaY * 0.1);
      view->Light()->setPosition (view->Camera()->CameraPos ());
    }
    else {
      view->Camera ()->zoom (who->ObjDeltaY * 0.1);
      view->Light()->setDirection (view->Camera()->ViewDir ());
      view->Light()->setPosition (view->Camera()->CameraPos ());
    }
    view->flush ();
  }
}

//==================================================================
//		Passivemotion Callback
//==================================================================

void SFXCallback::Passive (SFXCallback *who, OGLView* view, int x, int y) {
  if (view->MySpace()->MySelection()->hasSelection ()) {
    if (view->doSelectOfSubset (view->MySpace()->MySelection()->SelectedObjects (), x, y, 2, 2)) {
      sprintf (DlgBuffer, "%s configure -cursor X_cursor ", ((ToglView*)view)->WidgetName ());
      Tcl_GlobalEval (SFXInterp, DlgBuffer);
      who->ObjCursor = 1;
    }
    else if (who->ObjCursor) {
      sprintf (DlgBuffer, "%s configure -cursor {} ", ((ToglView*)view)->WidgetName ());
      Tcl_GlobalEval (SFXInterp, DlgBuffer);
      who->ObjCursor = 0;
    }
  }
}

/*static*/ char* SFXCallback::StatusText (const GeoObject& obj) {
  const Map<typBaustein, GeoObject>& p (MySFXModel->Permanents  ());
  typBaustein* b;
  if ((b = p.findKey (obj)) != NULL) {
    sprintf (buf, "Baustein %d  Typ:%s  Zustand:%s",
             b->Nummer (), b->BstTypTxt ().str (), b->ZustandTxt ().str ());
  }
  else {
    const Map<typTransportEinheit, GeoObject>& t (MySFXModel->Temporaries ());
    typTransportEinheit* w;
    if ((w = t.findKey (obj)) != NULL) {
      sprintf (buf, "TransportEinheit %d  Arbeitsplan:%d",
               w->ID (), w->Arbeitsplan ()->Nummer ());
    }
    return "unknown Object";
  }
  return buf;
}

//==================================================================
//		Tcl/Tk-Interface
//==================================================================

Ustring ExpName; // Modellname
Ustring ExtName; // Modellendung (.2gs oder .xml)

bool timer_sim_on = true;
bool Sfx3D_on      = false;

double  ZeitFaktor = 0.0;

//miro, feb2003, inifile einstellungen im sfx3d-menu darstellen
int    debugfenster 	 = IniFile::DefIniFile.readInt ("IO", "dprintf_DEBUG", 0);
int    initprog       = IniFile::DefIniFile.readInt ("FFS", "Initprog", 0);
int    testprog    	 = IniFile::DefIniFile.readInt ("FFS", "Testprog", 0);
int    prgtest      	 = IniFile::DefIniFile.readInt ("FFS", "Prgtest", 0);
int    logfile     	 = IniFile::DefIniFile.readInt ("FFS", "Output_in_Datei", 0);
//miro, feb2003, inifile einstellungen im sfx3d-menu darstellen

Tk_TimerToken timerToken = NULL;
NCInterpreter NCInterp;//global, um NC-Programme nicht nur am Start, schicken zu können. 


//==================================================================
//		for HLA ---rudi---16.08.01
//==================================================================

void HLAlesen () {
  if (hla) {

    //mydllHandle = LoadLibrary("hla.dll");

    char* fExecName = new char[ strlen("Sfx3D") + 1 ];
    strcpy( fExecName, "Sfx3D");
    if (IniFile::DefIniFile.findVar ("HLA", "Federationname")) {
      fExecName = new char[ strlen(IniFile::DefIniFile.readString ("HLA", "Federationname","Sfx3D")) + 1 ];
      strcpy( fExecName, IniFile::DefIniFile.readString ("HLA", "Federationname","Sfx3D") );
      dprintf("FederationName geholt: %s\n",fExecName);
    }
    	
    char* fedName = new char[ strlen(MySFXModel->ModelName ().str ()) + 1 ];
    strcpy( fedName, MySFXModel->ModelName ().str ());
    if (IniFile::DefIniFile.findVar ("HLA", "Federatename")) {
      fedName = new char[ strlen(IniFile::DefIniFile.readString ("HLA", "Federatename",MySFXModel->ModelName ().str ())) + 1 ];
      strcpy( fedName,IniFile::DefIniFile.readString ("HLA", "Federatename",MySFXModel->ModelName ().str ()) );
      dprintf("FederateName geholt: %s\n",fedName);
    }

	double lookAhead = 1.0;
	if (IniFile::DefIniFile.findVar ("HLA", "Lookahead")) {
      lookAhead = IniFile::DefIniFile.readDouble ("HLA", "Lookahead",1.0);
      dprintf("lookAhead geholt: %f\n",lookAhead);
    }
    
    double timeStep = 1.0;
    if (IniFile::DefIniFile.findVar ("HLA", "Timestep")) {
      timeStep = IniFile::DefIniFile.readDouble ("HLA", "Timestep",1.0);
      dprintf("timeStep geholt: %f\n",timeStep);
    }

    char* fedFileName = new char[ strlen("SfxHla.fed") + 1 ];
    strcpy( fedFileName, "SfxHla.fed");
    if (IniFile::DefIniFile.findVar ("HLA", "FEDFileName")) {
      fedFileName = new char[ strlen(IniFile::DefIniFile.readString ("HLA", "FEDFileName","SfxHla.fed")) + 1 ];
      strcpy( fedFileName, IniFile::DefIniFile.readString ("HLA", "FEDFileName","SfxHla.fed") );
      dprintf("FEDFileName geholt: %s\n",fedFileName);
    }
    
	double tickMinTime = 0.01;
	if (IniFile::DefIniFile.findVar ("HLA", "TickMinTime")) {
      tickMinTime = IniFile::DefIniFile.readDouble ("HLA", "TickMinTime",0.01);
      dprintf("TickMinTime geholt: %f\n", tickMinTime);
    }
    
    double tickMaxTime = 0.05;
    if (IniFile::DefIniFile.findVar ("HLA", "TickMinTime")) {
      tickMaxTime = IniFile::DefIniFile.readDouble ("HLA", "TickMaxTime",0.05);
      dprintf("TickMaxTime geholt: %f\n", tickMaxTime);
    }
   
    /*char* publishArbplan;
      publishArbplan = new char[ strlen(IniFile::DefIniFile.readString ("HLA", "PublishArbplan","00")) + 1 ];
      strcpy( publishArbplan,IniFile::DefIniFile.readString ("HLA", "PublishArbplan","00") );
      dprintf("publishArbplan geholt: %s\n",publishArbplan);

      char seps[] = ";";
      char *token;
    
      token = strtok (publishArbplan, seps);
      while( token != NULL )
      {
      int nint = atoi(token);
      //HlaPublishList.append (nint);
      typArbeitsplan* a = MySFXModel->findWorkSchedule (nint);
      if (a) {
      dprintf("Arbeitspan %i gefunden!\n",nint);
      a->setHla2Publish (true);
      }
      // Get next token: NULL is very important
      token = strtok ( NULL,seps);
      }
    */
    /*unsigned int* n (HlaPublishList.First ());
      dprintf("Inhalt von HlaPublishList 1st: %d\n",HlaPublishList.First ());
      for (; n; n = HlaPublishList.Next ()) {
      dprintf("Inhalt von HlaPublishList(%i): %i\n",HlaPublishList.Count (),n);
      }*/

    char seps[] = ";";
    char *token;
    char* pClass = new char[ strlen("Default") + 1 ];
    char* sClass = new char[ strlen("Default") + 1 ];

    DynArray<char> pParList;
    DynArray<char> sParList;

    if (IniFile::DefIniFile.findVar ("HLA", "PublishInteractionClassName")) {
      strcpy( pClass,IniFile::DefIniFile.readString ("HLA", "PublishInteractionClassName", "Default") );
    // wenn eine Klasse deklariert ist, koennen auch Parameter zugewiesen werden!!!
      if (pClass != "Default") {
	char* pPar;
	pPar = new char[ strlen(IniFile::DefIniFile.readString ("HLA", "PublishInteractionParName","Default")) + 1 ];
	strcpy( pPar,IniFile::DefIniFile.readString ("HLA", "PublishInteractionParName","Default") );
	dprintf("PublishInteractionParName geholt: %s\n",pPar);
	
	token = strtok (pPar, seps);
	while( token != NULL ) {
	  //char sPar2Char = new char[ strlen(token) + 1 ];
	  //HlaReceivedInteractionList.append(*(strcpy (new char [strlen ((const char*)imsg) + 1], imsg)));
	  //sPar2Char = new char[ strlen(token) + 1 ];
	  //strcpy( sPar2Char,token );
	  pParList.append(*(strcpy (new char [strlen ((const char*)token) + 1], token)));
	  dprintf("Publish: %s\n",pParList.Last());
	  // Get next token: NULL is very important
	  token = strtok ( NULL,seps);
	}
      }
    } else {
      cout << "pClass wird auf NULL gesetzt!" << endl;
      pClass = NULL;
      cout << "pClass wird auf NULL gesetzt!" << endl;
    }
    
    if (IniFile::DefIniFile.findVar ("HLA", "SubscribeInteractionClassName")) {
      strcpy( sClass,IniFile::DefIniFile.readString ("HLA", "SubscribeInteractionClassName", "Default") );
      
      cout << "pClass wird auf NULL gesetzt!" << endl;
      if (pClass != NULL) {  
	if (!strcmp (sClass, pClass)) {
	  cout << "Abbonement der Klasse: " << sClass << " wird wegen: " << pClass << " als veroeffentlichte Klasse unterbunden!" << endl;
	} else { 
	  if (sClass != "Default") {
	    char* sPar;
	    sPar = new char[ strlen(IniFile::DefIniFile.readString ("HLA", "SubscribeInteractionParName","Default")) + 1 ];
	    strcpy( sPar,IniFile::DefIniFile.readString ("HLA", "SubscribeInteractionParName","Default") );
	    dprintf("SubscribeInteractionParName geholt: %s\n",sPar);
	    
	    token = strtok (sPar, seps);
	    while( token != NULL ) {
	      sParList.append(*(strcpy (new char [strlen ((const char*)token) + 1], token)));;
	      dprintf("Subscribe: %s\n",sParList.Last());
	      // Get next token: NULL is very important
	      token = strtok ( NULL,seps);
	    }
	  } else {
	    sClass = NULL;
	  }
	}
      } else {
	if (sClass != "Default") {
	  char* sPar;
	  sPar = new char[ strlen(IniFile::DefIniFile.readString ("HLA", "SubscribeInteractionParName","Default")) + 1 ];
	  strcpy( sPar,IniFile::DefIniFile.readString ("HLA", "SubscribeInteractionParName","Default") );
	  dprintf("SubscribeInteractionParName geholt: %s\n",sPar);
	  
	  token = strtok (sPar, seps);
	  while( token != NULL ) {
	    sParList.append(*(strcpy (new char [strlen ((const char*)token) + 1], token)));;
	    dprintf("Subscribe: %s\n",sParList.Last());
	    // Get next token: NULL is very important
	    token = strtok ( NULL,seps);
	  }
	} else {
	  sClass = NULL;
	}
      }
    } else {
      sClass = NULL;
    }

    //HlaInit (SFXInterp,fedName,fExecName,lookAhead,pClass,pParList,sClass,sParList);
    dprintf ("Will HLA initialisieren...\n");

    HlaInit (SFXInterp,fedName,fExecName,lookAhead,tickMinTime,tickMaxTime,fedFileName,pClass,pParList,sClass,sParList);
    dprintf ("HLA initialisiert!\n");
  }
}


void RZSlesen (Tcl_Interp *interp) {

  char text  [255];
  int Schnittstelle, Baudr, Datenbits, Stopbits, Paritaet;
  int z = 0, von = 0, e = 0, p = 0;
  if (rzs) {
    if (hla)
      HLAlesen ();
    // Wenn hlaRzsEcho Programm vorhanden ist, wird die
    // serielle Schnittstelle nicht initialisiert. 
    if (!hlaRzsEcho && !(hla && hlaTimeConstrained)) {
    rzspar [1] = IniFile::DefIniFile.readInt ("RZS", "Steuerung", 0); 
    rzspar [2] = IniFile::DefIniFile.readInt ("RZS", "Protokoll", 0);
 
    Schnittstelle = IniFile::DefIniFile.readInt ("RZS", "COM", 1);
    Baudr         = IniFile::DefIniFile.readInt ("RZS", "Baud", 9600);
    Datenbits     = IniFile::DefIniFile.readInt ("RZS", "Datenbits", 2);
    Stopbits      = IniFile::DefIniFile.readInt ("RZS", "Stopbits", 2);
    Paritaet      = IniFile::DefIniFile.readInt ("RZS", "Paritaet", 2);
    
    if (SioInit ( interp, Schnittstelle, Baudr, Datenbits, Paritaet, Stopbits)) {
      dprintf ("Initialisierung der seriellen Schnittstelle COM%i: erfolgreich!\n", Schnittstelle);
      sprachausgabe = IniFile::DefIniFile.readInt ("RZS", "Sprachausgabe", 0);
      rzszeitschwelle = IniFile::DefIniFile.readInt ("RZS", "Zeitschwalle", 0);

      // Modelltechnik initialisieren
      dprintf ("Modelltechnik wird initialisiert, bitte warten!\n");
      RzsInit(); dprintf ("Modelltechnik initialisiert!\n");
      if (IniFile::DefIniFile.placeInSection ("MSPS")) {
        while (IniFile::DefIniFile.readSectLine (text))
          SioSchreiben(text, strlen(text));
      }
      for (z=1; z <= anzbst; z++) { //anzbst wird in msps.cpp ermittelt 
        if (baustein[z] != NULL) {
          RzsSenden( z, ETchtyp, baustein[z]->Basistyp());
          if (baustein[z]->Basistyp() == tMaschine) {
            sprintf (text, "\n%02i,00,71 1001\n",z);
            SioSchreiben (text, strlen (text)-1);
          }
          RzsSenden( z, ETainit, 0);
          e = 0;
          while (( von != z) || (e != ETeinit))
            RzsLesen (&von, &e, &p);
        }
      }
    
      // Alle zum Modell gehoerenden NC-Programme an die 
      // Maschinen uebertragen.
      IniFile::DefIniFile.placeInSection ("NCPROGRAMME"); 
      z=0;
      text[0] = '\0';
      while (IniFile::DefIniFile.readSectLine (text)) {
        sscanf (text, " %2i %2i", &z, &p);
        if (z>0) {
          NCInterp.Uebersetzen (z,p,MySFXModel->ModelPath () .str());
          dprintf ("Programm Nr. %3i an Maschine %3i uebertragen\n", p, z);
          sprintf (text, "\n\n%02i,00,62 -00", z);
          SioSchreiben (text, strlen(text));
          e = 0;
          while ((von != z) || (e != ETeinit))
            RzsLesen (&von, &e, &p);
          z=0;
          text[0] = '\0';
        }
      }
      dprintf ("Modelltechnik bereit.");
    }    // if (SioInit .........)
    else {
      dprintf ("Starte Modell ohne Modelltechnik!\n");
      rzs = 0;
    }
    }//if (!hlaRzsEcho && !(hla && hlaTimeConstrained)) 
  } // if rzs
  else
    // Dies muss mindestens geschehen, damit der tcl-Interpreter
    // bekannt gemacht wird 
  SioInit ( interp,0,0,0,0,0);
}

void TimerGoOn (ClientData /*cl*/) {
  timerToken = NULL;
  timer_sim_on = true;
}

void EreignisAbarbeitung () {
	// Rudi: 24-07-03: Wenn Modellende erreicht, dann nichts mehr verarbeiten!
  while (MySFXModel->isRunning () && timer_sim_on && (Modellzeit() < Modellende())) {
    if (waslos ()) {
      E_Steuerung ();
      if ((Modellzeit () - MyViewHandler->LastTimeUpdate ()) >= MyViewHandler->TimeUpdate ()) {
        MyViewHandler->flushViews ();
        Modellzeit ().strftime (DlgBuffer, 255, SimTime::OutputFormat ());
        Tcl_SetVar (SFXInterp, "simTime", DlgBuffer, TCL_GLOBAL_ONLY);
        MyViewHandler->markTimeUpdate ();
      }
    }
    else {
      // Hier wird die Uhr im Fenstertitel bei eingeschalteter Modelltechnik
      // oder Realzeitsimulation im Sekundentakt aktualisiert. Sieht einfach
      // schoener aus.   (20.09.1997 U. Cordes)
//      if ((MySFXModel->RealTime () || MySFXModel->PlantControl ())
//          && (AktSekundenAnzeige != (int) Modellzeit ().inSeconds ())) {
//        sprintf(ZeitString, "SIMFLEX/3: (%s) ", ExpName);
//        Modellzeit ().strftime (ZeitString + strlen (ZeitString), 240,
//                                SimTime::OutputFormat ());
//        if (SimFenster) SimFenster->setFenTitel(ZeitString);
//        AktSekundenAnzeige = (int) Modellzeit ().inSeconds ();
//      }
    } // else !waslos



// die Zeit aktualisiert werden(reale Systemzeit).
// Es macht wenig Sinn auch die Grafik mitlaufen zu lassen,
// da in die einzelnen Ereignisroutinen eingegriffen werden muss, 
// und der Anwender eher verwirrt wird. So hat der Anwender 
// den Zustand im Bilde, den er wiederherstellen soll,
// mit Hilfe der Handsteuerung. (miro 17.10.2001)
  
   if (rzsmanuell) {
   	
        Modellzeit ().strftime (DlgBuffer, 255, SimTime::OutputFormat ());
        Tcl_SetVar (SFXInterp, "simTime", DlgBuffer, TCL_GLOBAL_ONLY);
        MyViewHandler->markTimeUpdate ();
        while (Tcl_DoOneEvent (TK_ALL_EVENTS|TK_DONT_WAIT) != 0);
 }
    while (Tcl_DoOneEvent (TK_ALL_EVENTS|TK_DONT_WAIT) != 0);

    if (MyViewHandler->isPosed () && ZeitFaktor) {
      timer_sim_on = false;
      timerToken = Tk_CreateTimerHandler
                     ((int)((notiz::NextEventTime () - Modellzeit ()).inFracs () * ZeitFaktor),
                       TimerGoOn, NULL);
    }
  } // while (sim_on)
} // EreignisAbarbeitung

int MyMsgHandleFunc (int msgType, const char* txt) {
  if (msgType == MSG_WARNING)
    sprintf(DlgBuffer, "tk_messageBox -title Warning -icon warning "
                 "-type ok -message {%s}", txt);
  else {
    Sfx3D_on = 0;
    if (modelOpen) {
      modelOpen = false;
      if (timerToken) {
        Tk_DeleteTimerHandler (timerToken);
        TimerGoOn (NULL);
      }
      MySFXModel->stop ();
    }
    sprintf(DlgBuffer, "tk_messageBox -title Error -icon error "
                 "-type ok -message {%s}", txt);
  }
  Tcl_Eval (SFXInterp, DlgBuffer);
  return 1;
}

int MyMsgHandleFunc2 (int msgType, const char* txt) {
  if (msgType == MSG_STATUS)
    sprintf(DlgBuffer, "set menustatus {%s}",txt);
    
  else if (msgType == MSG_WARNING)
    sprintf(DlgBuffer, "tk_messageBox -title Warning -icon warning "
                 "-type ok -message {%s}", txt);
  else {
    Sfx3D_on = 0;
    if (modelOpen) {
      modelOpen = false;
      if (timerToken) {
        Tk_DeleteTimerHandler (timerToken);
        TimerGoOn (NULL);
      }
      MySFXModel->stop ();
    }
    sprintf(DlgBuffer, "tk_messageBox -title Error -icon error "
                 "-type ok -message {%s}", txt);
  }
  
  Tcl_Eval (SFXInterp, DlgBuffer);
  if (msgType == MSG_STATUS) {
    sprintf(DlgBuffer, "update idletasks");
    Tcl_Eval (SFXInterp, DlgBuffer);
  }
  return 1;
}

void CoutToTclWidget (char* txt) {
  sprintf (DlgBuffer, "put_win {%s};", txt);
  Tcl_Eval (SFXInterp, DlgBuffer);
}

void nixlog (char*) {
   
}

#ifdef WIN32

#include <shellapi.h>

void CoutToDebugWindow (char* txt) {
  static HWND DBWin32Window = 0;
  if (!DBWin32Window)
    DBWin32Window = (HWND) GetProp (GetDesktopWindow (), "DBWin32-Handle");
  SendMessage (DBWin32Window, WM_SETTEXT, 0, (unsigned) txt);
}
#endif

void ModellGenerierung (Tcl_Interp* interp) {
  if (rzs) {
    //---rudi---06.09.01
    // auch die rzs kann HLA einbinden
    if (hla)
      MySFXModel = new SFXModel (ExpName, ExtName, true, true,true);
  else 
      MySFXModel = new SFXModel (ExpName, ExtName, true, true,false);
  } else if (hla) {
    MySFXModel = new SFXModel (ExpName, ExtName, false, false,true);
  } else {
    MySFXModel = new SFXModel (ExpName, ExtName, false, false,false);
  }

/*
   if (!debugfenster) {
      coutController.setToCallback (CoutToTclWidget);
      Messager::setMsgHdlFunc (MyMsgHandleFunc);
   }
   else if (debugfenster == 1) {
    
#ifdef WIN32
    coutController.setToCallback (CoutToDebugWindow);
    ShellExecute (0, NULL, "DBWin.exe", NULL, NULL, SW_HIDE);
    ShellExecute (0, NULL, "DBWin32.exe", NULL, NULL, SW_HIDE);
#endif
    Messager::setMsgHdlFunc (MessagerToCout);
  }
  */
  /*else if (debugfenster == 2) {
    coutController.setToCallback (nixlog);
    Messager::setMsgHdlFunc (MyMsgHandleFunc);
  }
  
  if (logfile) {
    coutController.setToOstream (clog);
    Messager::setMsgHdlFunc (MessagerToCout);
  }
  */
  
  
  
    if (IniFile::DefIniFile.readInt ("IO", "dprintf_DEBUG", 0)) {
#ifdef WIN32
        coutController.setToCallback (CoutToDebugWindow);
        ShellExecute (0, NULL, "DBWin.exe", NULL, NULL, SW_HIDE);
        ShellExecute (0, NULL, "DBWin32.exe", NULL, NULL, SW_HIDE);
#endif
        Messager::setMsgHdlFunc (MessagerToCout);
    
    } else {
        coutController.setToCallback (CoutToTclWidget);
        Messager::setMsgHdlFunc (MyMsgHandleFunc);
    }

    if (IniFile::DefIniFile.readInt ("FFS", "Output_in_Datei", 0)) {
        coutController.setToOstream (clog);
        Messager::setMsgHdlFunc (MessagerToCout);
    }




    dprintf ("Modell wird geladen ...\n");

  /**< Bei Option -ausgabe, wird Pfad gesetzt. */
  const char *optausg = ProgArgs::OptionString ("-ausgabe");
  char ausgabe[255];
  if (optausg) {
    if (sscanf (optausg, "%s", &ausgabe) != NULL) {
      Ustring ausg (ausgabe);
      //dprintf("mit Option -ausgabe in Verzeichnis %s\n", ausgabe);
     // Msg.Warning ("ModellGenerierung (...)", "Ausgabeverzeichnis: %s, Modell: %s", ausgabe, ExpName);
      MySFXModel->setOutputPath (ausg);
    } else {
    	Msg.Error ("ModellGenerierung (...)", "Option -ausgabe gesetzt, aber kein Verzeichnis angegeben!!");
      //dprintf("Option -ausgabe gesetzt, aber keine Verzeichnis angegeben!!!\n");
    }
  }

  while (Tcl_DoOneEvent (TCL_ALL_EVENTS|TCL_DONT_WAIT) != 0);
  notiz::setup ();
  ExeContxt::setup ();
  char c;
  PrgModul = new typPrgModul ((MySFXModel->ModelPath () + MySFXModel->ModelName ()).str (), &c);
   //Msg.Warning ("ModellGenerierung (...)", "Ausgabeverzeichnis: %s", ausgabe);

 Messager::setMsgHdlFunc (MyMsgHandleFunc2);
  MySFXModel->load ();
  if (rzs){
    RZSlesen (interp);//miro,14.02.01 modeltechnik
  } else if (hla) { 
    // bei normaler und Realzeitsimulation
    HLAlesen ();    
    //dprintf ("Hla als FLAG gefunden!");
  }

  RZSlesen (interp);
  MyViewHandler = new SFXViewHandler (interp, *MySFXModel);
  MyViewHandler->createView (100, 100);

  while (modelOpen) {
    Tcl_DoOneEvent (0);
    EreignisAbarbeitung ();
  }
  if (rzs)
    /*
      if (hla)
      HlaExit();
    else
    */
      RzsExit ();//miro,14.02.01 modeltechnik
  /*
    else if (hla)
    HlaExit();
  */
  delete MyViewHandler;
  delete MySFXModel;
  delete PrgModul;
  if (hla)
  	HlaExit();
  PrgModul = NULL;
  ExeContxt::cleanup ();
  notiz::cleanup ();
}

int SSYCmdStructur ( ClientData /*clientData*/, Tcl_Interp *interp, int /*argc*/, const char *argv[] ) {
    sprintf(DlgBuffer, "%s", "");  //wichtige Rueckmeldung (11.04.98 rei]
    char text  [255];
    
    if (*argv[1] == 'S') {
        if (*(argv[1] + 1) == 't') {
            if (!strcmp("Step",  argv[1])) {
                
                if (MyViewHandler->isPosed () && waslos ()) {
                    if (timerToken) {
                        Tk_DeleteTimerHandler (timerToken);
                        TimerGoOn (NULL);
                    }
                    E_Steuerung ();
                    MyViewHandler->flushViews ();
                    Modellzeit ().strftime (DlgBuffer, 255, SimTime::OutputFormat ());
                    Tcl_SetVar (SFXInterp, "simTime", DlgBuffer, TCL_GLOBAL_ONLY);
                    MyViewHandler->markTimeUpdate ();
                }
                
            } else if (!strcmp ("Start", argv[1])) {
                
                MyViewHandler->flushViews ();
                if (!(MyViewHandler->isPosed ())) SFXViewHandler::poseViews (MyViewHandler);
                sprintf (DlgBuffer, "%d", MySFXModel->run ());
            	//if (hla && hlaTimeConstrained && hlaRemoteControl)
            	//HlaSendeRzsInteraction ("hla_Tcl_Cmd;SFXCmd;Start");
                //if (rzs) takten = 0;
                
            } else if (!strcmp ("Stop", argv[1])) {
                
                if (!(MyViewHandler->isPosed ())) SFXViewHandler::poseViews (MyViewHandler);
                if (timerToken) {
                    Tk_DeleteTimerHandler (timerToken);
                    TimerGoOn (NULL);
                }
                sprintf (DlgBuffer, "%d", MySFXModel->stop ());
                //if (rzs) takten = 0;
                
            }
            
        } else if (*(argv[1] + 1) == 'k') {
            
            if (!strcmp("SkipStart",  argv[1])) {
                if ((!MySFXModel->PlantControl ()) && (!MySFXModel->RealTime ())) {
                    if (!(MySFXModel->isRunning ())) MySFXModel->run ();
                    if (timerToken) {
                        Tk_DeleteTimerHandler (timerToken);
                        TimerGoOn (NULL);
                    }
                    SFXViewHandler::disposeViews (MyViewHandler, false, true);
                }
                
            } else if (!strcmp("SkipStop",  argv[1])) {
                
                if ((!MySFXModel->PlantControl ()) && (!MySFXModel->RealTime ())) {
                    bool wasRunning = atoi (argv[2]);
                    if (!wasRunning) {
                        MySFXModel->stop ();
                        Modellzeit ().strftime (DlgBuffer, 255, SimTime::OutputFormat ());
                        Tcl_SetVar (SFXInterp, "simTime", DlgBuffer, TCL_GLOBAL_ONLY);
                        MyViewHandler->markTimeUpdate ();
                    }
                    if (timerToken) {
                        Tk_DeleteTimerHandler (timerToken);
                        TimerGoOn (NULL);
                    }
                    SFXViewHandler::poseViews (MyViewHandler);
                }
                
            } else if (!strcmp("SkipTime",  argv[1])) {
                
                if ((!MySFXModel->PlantControl ()) && (!MySFXModel->RealTime ())) {
                    double zeit = atof (argv[2]);
                    bool absolut = atoi (argv[3]);
                    bool shouldMinimizeViews = atoi (argv[4]);
                    bool wasRunning = atoi (argv[5]);
                    if (timerToken) {
                        Tk_DeleteTimerHandler (timerToken);
                        TimerGoOn (NULL);
                    }
                    if (absolut) {
                        if (zeit > Modellzeit ().inMinutes ()) {
                          SFXViewHandler::disposeViews (MyViewHandler, shouldMinimizeViews, wasRunning);
                          planeein (zeit, ETinitGrafik, 0, 0);
                          sprintf (DlgBuffer, "Zeitsprung bis %10.2f\n", zeit);
                        }
                    } else {
                        SFXViewHandler::disposeViews (MyViewHandler, shouldMinimizeViews, wasRunning);
                        planedelta (zeit, ETinitGrafik, 0, 0);
                        sprintf (DlgBuffer, "Zeitsprung bis %10.2f\n", Modellzeit ().inMinutes () + zeit);
                    }
                } else {
                    sprintf (DlgBuffer, "Zeitsprung nicht mögllich!!!\n");
                }
            }
            
        } else if (!strcmp ("Speed", argv[1])) {
            
            if (timerToken) {
                Tk_DeleteTimerHandler (timerToken);
                TimerGoOn (NULL);
            }
            ZeitFaktor = atof (argv[2]);
            
        } else if (!strcmp ("SimTime", argv[1])) {
            
            sprintf (DlgBuffer, "%f", Modellzeit ().inMinutes ());
            
        } else if (!strcmp ("SysPro", argv[1])) {
            
            sys_protokoll (cout);
            
        } else if (!strcmp ("SprachAusgabe", argv[1])) {
            
            //sprintf(DlgBuffer, "%d", MySFXModel->setSpeech (!MySFXModel->Speech ()));
            
        }
        
    } else if (*argv[1] == 'T') {
        
        if (!strcmp ("Takten", argv[1])) {
            
            if (MySFXModel->PlantControl () || MySFXModel->RealTime ())
                sprintf (DlgBuffer, "Mit Modelltechnik kein Takten moeglich!\n");
            else
                MySFXModel->setCycle (atoi (argv [2]));
                
        } else if (!strcmp ("Trace", argv[1])) {
            
            sprintf (DlgBuffer, "%d", MySFXModel->setTrace (atoi (argv [2])));
            
        }
        
    } else if (!strcmp ("NewView", argv[1])) {
        
        if (MyViewHandler->isPosed ()) {
            MyViewHandler->createView (100, 100);
            while (Tcl_DoOneEvent (TK_ALL_EVENTS|TK_DONT_WAIT) != 0);
       }
       
    } else if (!strcmp ("InitBst", argv[1])) {
        
        modelOpen = true;
        ExpName = Ustring (argv[2]);
        ExtName = Ustring (argv[3]);
        //ExpName = Ustring (argv[argc - 1]);
        sprintf (DlgBuffer, "Modell wird geladen\n");
        
    } else  if (!strcmp ("ExitBst", argv[1])) {
        
        Sfx3D_on = 0;
        if (modelOpen) {
            modelOpen = false;
            if (timerToken) {
                Tk_DeleteTimerHandler (timerToken);
                TimerGoOn (NULL);
            }
            MySFXModel->stop ();
            sprintf (DlgBuffer, "Simulator beendet!\n");
        }
        
    } else if ( !strcmp ("CloseBst", argv[1])) {
        
        if (modelOpen) {
            modelOpen = false;
            ExpName = Ustring ();
            if (timerToken) {
                Tk_DeleteTimerHandler (timerToken);
                TimerGoOn (NULL);
            }
            MySFXModel->stop ();
            sprintf (DlgBuffer, "Modell geschlossen!\n");
        }
        
    } else if (!strcmp("RealzeitSim", argv[1])) {
        
        unsigned what = atoi (argv [2]);
        if (what == 1) ZeitFaktor = what;
        else {
            if (timerToken) {
                Tk_DeleteTimerHandler (timerToken);
                TimerGoOn (NULL);
            }
            ZeitFaktor = 0.0;
        }
        echtzeitsim = atoi (argv [2]);
        
    } else if (!strcmp ("ModTechnik", argv[1])) {
        
        rzs = atoi (argv[2]);
        //if (MySFXModel->PlantControl ()) MySFXModel->setCycle (false);
        
    } else if (!strcmp ("RzsManuell", argv[1])) {
        
        //**************** nur für die Handsteuerung (Anfang), miro 01.10.01********************* 
 	    rzsmanuell = atoi (argv[2]);        //Flag für die Handsteuerung, in realzeit.cpp behandelt
        //	rzsmantorzs ();//Die evtl. Rückmeldungen aus rzsman- nach rzskalender kopieren
        
    } else if ( !strcmp("sende",  argv[1]) ) { //RzsSenden -> Gsl.tcl
        
        sprintf(text, "%s", argv[2]);
		SioSchreiben (text, strlen(text));
        sprintf(text, "%s\n", argv[2]);
        
    } else if ( !strcmp("i_anzbst",  argv[1]) ) {//Anzahl der Bausteine im Modell,
        
        sprintf(DlgBuffer,"%i",anzbst);    // wird in MspsInit()[ueber '%01']  ermittelt
        
    } else if ( !strcmp("i_siodevnr",  argv[1]) ) { //Puffer der seriellen Schnittstelle
        
        sprintf(DlgBuffer,"%s",SioDevNr);
        
    } else  if ( !strcmp("rzsprint",  argv[1]) ) { //RZSKalender im Debugfenster ausdrücken
        
        rzsprint();
        
    } else  if ( !strcmp("ncprog",  argv[1]) ) { //Neues NC-Programm übertragen
        
        int p = atoi (argv[2]);
        int z = atoi (argv[3]);
        sprintf (text, "\n%02i,00,71 1001\n",z);
        SioSchreiben (text, strlen (text)-1);
        NCInterp.Uebersetzen (z,p,MySFXModel->ModelPath () .str());
        dprintf ("Programm Nr. %3i an Maschine %3i uebertragen\n", p, z);
        sprintf (text, "\n\n%02i,00,62 -00", z);
        SioSchreiben (text, strlen(text));
        
    } else  if ( !strcmp("ExitH",  argv[1]) ) { //Exit
        
        //   rzsmantorzs ();//Die eventuellen Rückmeldungen aus rzsmankalender nach rzskalender kopieren,
        rzsmanuell = 0; //********und rzsmankalender loeschen, sowie Flag zurücksetzen!***********************************
        
    } else if (!strcmp ("Hla4Sfx3D", argv[1])) {
        
        hla = atoi (argv[2]); // rudi
        hlaAsynchronousDelivery = atoi (argv[3]); // rudi
        hlaTimeRegulating = atoi (argv[4]); // rudi
        hlaTimeConstrained = atoi (argv[5]); // rudi
        hlaRzsEcho = atoi (argv[6]); // rudi
        hlaRemoteControl = atoi (argv[6]); // rudi
        //if (MySFXModel->PlantControl ()) MySFXModel->setCycle (false);
        
    } else  if ( !strcmp("DebugWindow",  argv[1]) ) { //Debugfenster unter Windows
        
        //miro, feb2003, inifile einstellungen im sfx3d-menu darstellen
        debugfenster = atoi (argv[2]);

        if (!debugfenster) {
            coutController.setToCallback (CoutToTclWidget);
            Messager::setMsgHdlFunc (MyMsgHandleFunc);
        } else if (debugfenster == 1) {
            #ifdef WIN32
                coutController.setToCallback (CoutToDebugWindow);
                ShellExecute (0, NULL, "DBWin.exe", NULL, NULL, SW_HIDE);
                ShellExecute (0, NULL, "DBWin32.exe", NULL, NULL, SW_HIDE);
            #endif
            Messager::setMsgHdlFunc (MessagerToCout);
        }

        if (logfile) {
            coutController.setToOstream (clog);
            Messager::setMsgHdlFunc (MessagerToCout);
        }
        
        
    } else  if ( !strcmp("InitProg",  argv[1]) ) {//Initialisierungsprotokoll
        
        initprog = atoi (argv[2]);
        MySFXModel->setInitDebug (initprog);
        
    } else  if ( !strcmp("TestProg",  argv[1]) ) { //Testausschriebe waehrend der Laufzeit
        
        testprog = atoi (argv[2]);
        MySFXModel->setDebug (testprog);
        
        
    } else  if ( !strcmp("PrgTest",  argv[1]) ) { //Testausschriebe aus der C++ Schnittstelle
        
        prgtest = atoi (argv[2]);
        MySFXModel->setPrgDebug (prgtest);
        
    } else  if ( !strcmp("Logfile",  argv[1]) ) { //Ausschriebe umlenken von stdout in die Datei 'logfile.out'
        
        logfile = atoi (argv[2]);
        
        if (logfile) {
            coutController.setToOstream (clog);
            Messager::setMsgHdlFunc (MessagerToCout);
        } else {
	        if (!debugfenster) {
                coutController.setToCallback (CoutToTclWidget);
                Messager::setMsgHdlFunc (MyMsgHandleFunc);
            } else if (debugfenster == 1) {
                #ifdef WIN32
                    coutController.setToCallback (CoutToDebugWindow);
                    ShellExecute (0, NULL, "DBWin.exe", NULL, NULL, SW_HIDE);
                    ShellExecute (0, NULL, "DBWin32.exe", NULL, NULL, SW_HIDE);
                #endif
                Messager::setMsgHdlFunc (MessagerToCout);
            }
        }
        
        
    } else  if ( !strcmp("NixLog",  argv[1]) ) { //Ausschriebe ins Nirvana umlenken, es gibt keine Ausschriebe mehr!
        
        int logaus = atoi (argv[2]);
	    if (logaus) {
	        coutController.setToCallback (nixlog);
            Messager::setMsgHdlFunc (MyMsgHandleFunc);
        } else {
            coutController.setToOstream (clog);
	        Messager::setMsgHdlFunc (MessagerToCout);
        }
        
        
    } else  if ( !strcmp ("AboutWindow", argv[1])) {
        
        
        //miro, feb2003, inifile einstellungen im sfx3d-menu darstellen
        char msg[255];
        char rev[] = "Release: 15";
        strtok (rev, ":");
        char *tok = strtok (NULL, "$");
        strcpy (msg, tok);
        float frev;
        sscanf (msg, " %f", &frev);
        sprintf (msg, "SIMFLEX/3D\n\n(c) 2010 rei/FPS/IPL/Uni Kassel\n\nRelease %1.2f (rei/rud 04)\n\nwww.fps.maschinenbau.uni-kassel.de", frev);
        sprintf(DlgBuffer, "tk_messageBox -parent . -title About -icon info -type ok \
        -message \"%s\"", msg);
        Tcl_GlobalEval (SFXInterp, DlgBuffer);
        
        
    } else  if ( !strcmp ("Hilfe", argv[1])) {
        
        //sprintf(DlgBuffer, "Hilfe: %5.3f\n", hilfe ());
        
    } else  {
        sprintf (DlgBuffer, "Unbekannte Methode \"%.32s\"\n " , argv[1]);
        Tcl_SetResult (interp, DlgBuffer, TCL_STATIC);
        return TCL_ERROR;
    }
    Tcl_SetResult (interp, DlgBuffer, TCL_STATIC);
    return TCL_OK;
} //  SSY_CmdStruktur

//==================================================================
//		Tcl/Tk-MainEventLoop
//==================================================================

//EXTERN void TkpDisplayWarning _ANSI_ARGS_((char *msg, char *title));
extern void TkpDisplayWarning _ANSI_ARGS_((char *msg, char *title));

void Tk_MyMain(int argc, char** argv, Tcl_AppInitProc */*appInitProc*/) {
    char *args;

    Tcl_FindExecutable(argv[0]);
    SFXInterp = Tcl_CreateInterp();

    args = Tcl_Merge (argc-1, argv+1);
    Tcl_SetVar (SFXInterp, "argv", args, TCL_GLOBAL_ONLY);
    ckfree (args);
    sprintf (DlgBuffer, "%d", argc-1);
    Tcl_SetVar (SFXInterp, "argc", DlgBuffer, TCL_GLOBAL_ONLY);
    Tcl_SetVar (SFXInterp, "argv0", argv[0], TCL_GLOBAL_ONLY);

    Tcl_SetVar (SFXInterp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);

    if (Tcl_Init(SFXInterp) == TCL_ERROR) {
      //TkpDisplayWarning (SFXInterp->result, "Application initialization failed");
    }
    if (Tk_Init(SFXInterp) == TCL_ERROR) {
//      TkpDisplayWarning (SFXInterp->result, "Application initialization failed");
    }

    Tcl_CreateCommand(SFXInterp, "SFXCmd", SSYCmdStructur,
            (ClientData) Tk_MainWindow (SFXInterp), (Tcl_CmdDeleteProc *) 0);

    sprintf (DlgBuffer, "%sGsl.tcl", FileSystem::ExePath ());

#if (TCL_MAJOR_VERSION * 100 + TCL_MINOR_VERSION) >= 705
    Tcl_SetVar (SFXInterp, "tcl_rcFileName", DlgBuffer, TCL_GLOBAL_ONLY);
#else
    tcl_RcFileName = "Gsl.tcl";
#endif

    Tcl_SourceRCFile (SFXInterp);
    Tcl_ResetResult (SFXInterp);

    while (Tcl_DoOneEvent (TK_ALL_EVENTS|TK_DONT_WAIT) != 0);

    sprintf (DlgBuffer, "wm title . \"SIMFLEX/3D\"");
    Tcl_Eval (SFXInterp, DlgBuffer);

    Sfx3D_on = 1;
    while (Sfx3D_on) {
      Tcl_DoOneEvent(0);
      if (ProgArgs::Argc() > 1){
	/*
	   sprintf (msgtest, "SIMFLEX/3D\n\n(c) 2001 FPS/ipl/GhK\n\nwww.fps.maschinenbau.uni-kassel.de" );
	   sprintf(DlgBuffer, "tk_messageBox -parent . -title About -icon info -type ok -message \"%s\"", msgtest);
	   Tcl_GlobalEval (SFXInterp, DlgBuffer);
         */
	sprintf (DlgBuffer, "DateiOeffnen {%s}", FileSystem::switchPathForOS((char*)ProgArgs::Argv(ProgArgs::Argc() - 1)));
	Tcl_Eval (SFXInterp, DlgBuffer);
      }
      if (modelOpen)
      	ModellGenerierung (SFXInterp);
    }
    Tcl_DeleteInterp (SFXInterp);
}

