/* --------------------------------------------------------------------  */
/*                          CALCULIX                                     */
/*                   - GRAPHICAL INTERFACE -                             */
/*                                                                       */
/*     A 3-dimensional pre- and post-processor for finite elements       */
/*              Copyright (C) 1996 Klaus Wittig                          */
/*                                                                       */
/*     This program is free software; you can redistribute it and/or     */
/*     modify it under the terms of the GNU General Public License as    */
/*     published by the Free Software Foundation; version 2 of           */
/*     the License.                                                      */
/*                                                                       */
/*     This program is distributed in the hope that it will be useful,   */
/*     but WITHOUT ANY WARRANTY; without even the implied warranty of    */ 
/*     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the      */
/*     GNU General Public License for more details.                      */
/*                                                                       */
/*     You should have received a copy of the GNU General Public License */
/*     along with this program; if not, write to the Free Software       */
/*     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.         */
/* --------------------------------------------------------------------  */


/*
TO DO:
- replace line_ with line_i in splitLine() and delete line_() in defineEntity and rename line_i to line_ in all functions.
- extend hitUndo()
*/


#define     TEST            0     /* debugging */

#include <cgx.h>

#define DPICK_BUFFER 10000
#define MAX_BUF      100

extern int   width_ini, height_ini;            /* Grafik-Fensterbreite/hoehe */
extern int   width_menu, height_menu;
extern int   w0, w1, activWindow;
extern int   width_w0, height_w0;
extern int   width_w1, height_w1;
extern int   MouseMode;                                   /* status maustasten */
extern double dtx, dty, drx, dry, drz, ds;                 /* Verschiebungen */
extern GLdouble R[4][4];                                   /* Rotationsmatrix */
extern unsigned char  surfFlag;                /* zeichne nur Oberflaechenelemente (1), sonst (0)*/
extern unsigned char  modelEdgeFlag;           /* zeichne mit Modell-Ecken (1), sonst (0)*/
extern unsigned char  drawMode;                /* protokoliert drawFunktion (drawLoad,Light,Animate,set)*/
extern unsigned char  cullFlag;                /* (1) enable Culling */
extern unsigned char  frameFlag;               /* mit (1) oder ohne Rahmen um das Grafikfenster */
extern unsigned char  pickFlag;
extern double dx ,dy;                  /* Mauskoordinaten */
extern double centerPnt[3];            /* Rotationszentrum */
extern int   centerNode;            /* Nr of center Node, 0:no centernode */
extern double     gtol;                                    /* geometry tolerance for merging */
extern int     ddiv;

extern Scale     scale[1];
extern double     *value_n;
extern Summen    anz[1];
extern Nodes     *node;
extern Elements  *e_enqire;

extern Datasets *lcase;
extern Faces     *face;

extern Alias     *alias;
extern Sets      *set;                
extern Psets     *pset;                
extern Points    *point;
extern Lines     *line;
extern Lcmb      *lcmb;
extern Gsur      *surf;
extern Gbod      *body;
extern Nurbl     *nurbl;
extern Nurbs     *nurbs;
extern SumGeo    anzGeo[1];
extern SumAsci   sumAsci[1];

extern int       num_olc;

extern int       offset;
extern int       lc;            /* active loadcase */

/* global variables for picking */
extern unsigned char pickfunc[MAX_LINE_LENGTH];  /* pickfunc either "qenq" "qadd" "qrem" ..  */
extern unsigned char mode[2];                    /* pickmode */
extern GLdouble dx_cur, dy_cur;         /* pick-cursor Area */
extern double backgrndcol_rgb[4];
extern unsigned char    buffer[MAX_LINE_LENGTH];        /* common string-buffer */
extern unsigned char  printFlag;                     /* printf 1:on 0:off */


static GLint hits;                             /* number of picked items, must be global because of glutKeyboardFunc(defineDiv) */
GLuint *selectBuf=NULL;                 /* buffer which holds the picked items, must be global because of glutKeyboardFunc(defineDiv) */
extern SpecialSet specialset[1];

int     pick_zmin;                      /* kleinster z-wert der gepickten items */
int     setNrbuf;                       /* setbuffer for pick() */
int    *pickdata;                       /* Zwischenspeicher fuer pickdaten */
int     pickbuf;                        /* kurzzeitbuffer */
int     pick_buffer;                    /* groesse von pickdata */
int     xbuf, ybuf;                     /* mauskoordinaten */
int     *selem=(int *)0;                /* buffer for qflp, points to surfs */
int     entitybuf=-1;                   /* saves the index of the last created entity for undo */
int     set_highl=-1;                   /* set which stores actual entity */
int     pntNr=-1;                       /* selected point */
int     lineNr=-1;                      /* selected line */
int     surfNr=-1;                      /* selected surf, surface as a target for the point-projection */
int     nurbsNr=-1;                     /* selected Nurbs, used for all touched surfs (s,g) */
int     bodyNr=-1;                      /* selected body */

#define MAX_LINES 100
int qspl_i, qspl_indx[MAX_LINES]; /* buffer for already splitted lines (qspl) */


int hitAction( GLuint *name, unsigned char *type, int x, int y )
{
  /* name[0]== picked type   */
  /* name[1]== picked name(Nr)  */
  /* type[0] == gkey in pick()  */

  unsigned char buf[MAX_LINE_LENGTH], printbuf[MAX_LINE_LENGTH];
  int i,j,k;
  int bias_fbd;
  static int qdisFlag=0;
  static double v_qdis[2][3], v0[3], v1[3],dax,day,daz;

  /* highlight the entity if its not qdel or qrem */
  if((compare(pickfunc, "qdel", 4) != 4)&&(compare(pickfunc, "qrem", 4) != 4))
  {
    /* buf[0]=tolower(type[0]); */
    buf[0]=type[0];
    buf[1]=(unsigned char)NULL;
    seta(set_highl, buf, name[1] );
  }

  if (name[0] == 'e')
  {
    printf ("%d n= ", name[1] );
    if(e_enqire[name[1]].type==1) k=8;
    else if(e_enqire[name[1]].type==4) k=20;
    else if(e_enqire[name[1]].type==6) k=10;
    else if(e_enqire[name[1]].type==7) k=3;
    else if(e_enqire[name[1]].type==8) k=6;
    else if(e_enqire[name[1]].type==9) k=4;
    else if(e_enqire[name[1]].type==10) k=8;
    else if(e_enqire[name[1]].type==11) k=2;
    else if(e_enqire[name[1]].type==12) k=3;
    else k=0;
    for (j=0; j<k; j++) printf("%d ",e_enqire[name[1]].nod[j]);
    printf("\n"); 
    if (compare(pickfunc, "qenq", 4) == 4)
    {
      sprintf(printbuf, "    in set=");
      for(i=1; i<anzGeo->sets; i++)
        if(!set[i].type)
          if( getIndex(&set[i].elem,set[i].anz_e,name[1]) >-1) if(set[i].name[0]!='-') sprintf(&printbuf[strlen(printbuf)],"%s,",set[i].name);  
      sprintf(&printbuf[strlen(printbuf)],"\n"); if(strlen(printbuf)>12) printf("%s", printbuf);
    }
    else if (compare(pickfunc, "qdel", 4) == 4) seta( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qadd", 4) == 4) seta( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qrem", 4) == 4) setr( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qflp", 4) == 4) flip( type, name[1]);
  }
  else if (name[0] == 'f')
  {
    printf ("%d n= ", name[1] );
      if(face[name[1]].type==7) k=3;
      else if(face[name[1]].type==8) k=6;
      else if(face[name[1]].type==9) k=4;
      else if(face[name[1]].type==10) k=8;
      else k=0;
      for (j=0; j<k; j++) printf("%d ",face[name[1]].nod[j]);
      printf("\n"); 
    if (compare(pickfunc, "qenq", 4) == 4)
    {
      sprintf(printbuf, "    in set=");
      for(i=1; i<anzGeo->sets; i++)
        if(!set[i].type)
          if( getIndex(&set[i].face,set[i].anz_f,name[1]) >-1) if(set[i].name[0]!='-') sprintf(&printbuf[strlen(printbuf)],"%s,",set[i].name);  
      sprintf(&printbuf[strlen(printbuf)],"\n"); if(strlen(printbuf)>12) printf("%s", printbuf);
    }
    else if (compare(pickfunc, "qdel", 4) == 4) seta( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qadd", 4) == 4) seta( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qrem", 4) == 4) setr( setNrbuf, type, name[1]);
  }
  else if ((name[0] == 'n')&& (node[name[1]].pflag!=1))
  {
    /* as a preliminary solution the nodal-values are suppressed if element-results are shown */ 
    if(lcase[lc].irtype == 3) printf ("%d xyz= %lf %lf %lf\n", name[1],
      (node[name[1]].nx* scale->w+scale->x),
      (node[name[1]].ny* scale->w+scale->y),
      (node[name[1]].nz* scale->w+scale->z) );
    else printf ("%d v= %e xyz= %lf %lf %lf ", name[1], value_n[name[1]],
      (node[name[1]].nx* scale->w+scale->x),
      (node[name[1]].ny* scale->w+scale->y),
      (node[name[1]].nz* scale->w+scale->z) );

      v0[0]=0.;
      v0[1]=node[name[1]].ny* scale->w+scale->y;
      v0[2]=node[name[1]].nz* scale->w+scale->z;
      v1[0]=0.; v1[1]=1.; v1[2]=0.;
      dax=v_angle(v0,v1);
      v0[0]=node[name[1]].nx* scale->w+scale->x;
      v0[1]=0.;
      v0[2]=node[name[1]].nz* scale->w+scale->z;
      v1[0]=0.; v1[1]=0.; v1[2]=1.;
      day=v_angle(v0,v1);
      v0[0]=node[name[1]].nx* scale->w+scale->x;
      v0[1]=node[name[1]].ny* scale->w+scale->y;
      v0[2]=0.;
      v1[0]=1.; v1[1]=0.; v1[2]=0.;
      daz=v_angle(v0,v1);
      v0[0]=node[name[1]].nx* scale->w+scale->x;
      v0[1]=node[name[1]].ny* scale->w+scale->y;
      v0[2]=node[name[1]].nz* scale->w+scale->z;
      printf("axyz= %lf %lf %lf rxyz= %lf %lf %lf\n",
        dax*180./pi,day*180./pi,daz*180./pi,
        sqrt(v0[1]*v0[1]+v0[2]*v0[2]),
        sqrt(v0[0]*v0[0]+v0[2]*v0[2]),
        sqrt(v0[0]*v0[0]+v0[1]*v0[1]) );
    if (compare(pickfunc, "qenq", 4) == 4)
    {
      sprintf(printbuf, "    in set=");
      for(i=1; i<anzGeo->sets; i++)
        if(!set[i].type)
          if( getIndex(&set[i].node,set[i].anz_n,name[1]) >-1) if(set[i].name[0]!='-') sprintf(&printbuf[strlen(printbuf)],"%s,",set[i].name);  
      sprintf(&printbuf[strlen(printbuf)],"\n"); if(strlen(printbuf)>12) printf("%s", printbuf);
    }
    else if (compare(pickfunc, "qdis", 4) == 4)
    {
      if(qdisFlag==1)
      {
        qdisFlag=0;
        v_qdis[1][0]=node[name[1]].nx* scale->w+scale->x;
        v_qdis[1][1]=node[name[1]].ny* scale->w+scale->y;
        v_qdis[1][2]=node[name[1]].nz* scale->w+scale->z;
        for(i=0; i<3; i++) { v0[i]=v_qdis[0][i]; v1[i]=v_qdis[1][i]; }
        v0[0]=v1[0]=0.; 
        dax=v_angle(v0,v1);
        for(i=0; i<3; i++) { v0[i]=v_qdis[0][i]; v1[i]=v_qdis[1][i]; }
        v0[1]=v1[1]=0.; 
        day=v_angle(v0,v1);
        for(i=0; i<3; i++) { v0[i]=v_qdis[0][i]; v1[i]=v_qdis[1][i]; }
        v0[2]=v1[2]=0.; 
        daz=v_angle(v0,v1);
        for(i=0; i<3; i++) { v0[i]=v_qdis[0][i]; v1[i]=v_qdis[1][i]; }
        printf("dist:%lf dx:%lf dy:%lf dz:%lf da:%lf dax:%lf day:%lf daz:%lf dr:%lf drx:%lf dry:%lf drz:%lf\n",
        sqrt((v_qdis[1][0]-v_qdis[0][0])*(v_qdis[1][0]-v_qdis[0][0])+
          (v_qdis[1][1]-v_qdis[0][1])*(v_qdis[1][1]-v_qdis[0][1])+
          (v_qdis[1][2]-v_qdis[0][2])*(v_qdis[1][2]-v_qdis[0][2])), 
               v_qdis[1][0]-v_qdis[0][0],v_qdis[1][1]-v_qdis[0][1],v_qdis[1][2]-v_qdis[0][2],
          v_angle(v_qdis[0],v_qdis[1])*180./pi,dax*180./pi,day*180./pi,daz*180./pi,
          sqrt(v1[0]*v1[0]+v1[1]*v1[1]+v1[2]*v1[2])-sqrt(v0[0]*v0[0]+v0[1]*v0[1]+v0[2]*v0[2]),
          sqrt(v1[1]*v1[1]+v1[2]*v1[2])-sqrt(v0[1]*v0[1]+v0[2]*v0[2]),
          sqrt(v1[0]*v1[0]+v1[2]*v1[2])-sqrt(v0[0]*v0[0]+v0[2]*v0[2]),
          sqrt(v1[0]*v1[0]+v1[1]*v1[1])-sqrt(v0[0]*v0[0]+v0[1]*v0[1]) );
      }
      else
      {
        qdisFlag=1;
        v_qdis[0][0]=node[name[1]].nx* scale->w+scale->x;
        v_qdis[0][1]=node[name[1]].ny* scale->w+scale->y;
        v_qdis[0][2]=node[name[1]].nz* scale->w+scale->z;
      }
    }
    else if (compare(pickfunc, "qcnt", 4) == 4)
    {
      centerNode=name[1];
      center( node[name[1]].nx, node[name[1]].ny, node[name[1]].nz);
      dx_cur=PICK_LENGTH; dy_cur=PICK_LENGTH;
      glutSetWindow( w1);
      /* Keyboardfunktion wiederherstellen (von pick())  */
      pickFlag=0;
      free(selectBuf); selectBuf=NULL;
      glutKeyboardFunc ( Keyboard );
      glutSetWindow( activWindow );
    }
    else if (compare(pickfunc, "qdel", 4) == 4) seta( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qadd", 4) == 4) seta( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qrem", 4) == 4) setr( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qele", 4) == 4) entitybuf=createElem(name[1]);
    else if (compare(pickfunc, "qnod", 4) == 4) moveNode(name[1], x, y);
    else if (compare(pickfunc, "qali", 4) == 4) pre_align( name[1], 0 );
    else if (compare(pickfunc, "qcut", 4) == 4) pre_cut( name[1], 0 );
  }
  else if (name[0] == 'p')
  {
    printf ("%s xyz= %lf %lf %lf ", point[name[1]].name,
      (point[name[1]].px* scale->w+scale->x),
      (point[name[1]].py* scale->w+scale->y),
      (point[name[1]].pz* scale->w+scale->z) );

      v0[0]=0.;
      v0[1]=point[name[1]].py* scale->w+scale->y;
      v0[2]=point[name[1]].pz* scale->w+scale->z;
      v1[0]=0.; v1[1]=1.; v1[2]=0.;
      dax=v_angle(v0,v1);
      v0[0]=point[name[1]].px* scale->w+scale->x;
      v0[1]=0.;
      v0[2]=point[name[1]].pz* scale->w+scale->z;
      v1[0]=0.; v1[1]=0.; v1[2]=1.;
      day=v_angle(v0,v1);
      v0[0]=point[name[1]].px* scale->w+scale->x;
      v0[1]=point[name[1]].py* scale->w+scale->y;
      v0[2]=0.;
      v1[0]=1.; v1[1]=0.; v1[2]=0.;
      daz=v_angle(v0,v1);
      v0[0]=point[name[1]].px* scale->w+scale->x;
      v0[1]=point[name[1]].py* scale->w+scale->y;
      v0[2]=point[name[1]].pz* scale->w+scale->z;
      printf("axyz= %lf %lf %lf rxyz= %lf %lf %lf\n",
        dax*180./pi,day*180./pi,daz*180./pi,
        sqrt(v0[1]*v0[1]+v0[2]*v0[2]),
        sqrt(v0[0]*v0[0]+v0[2]*v0[2]),
        sqrt(v0[0]*v0[0]+v0[1]*v0[1]) );
    if (compare(pickfunc, "qenq", 4) == 4)
    {
      sprintf(printbuf, "    in set=");
      for(i=1; i<anzGeo->sets; i++)
        if(!set[i].type)
          if( getIndex(&set[i].pnt,set[i].anz_p,name[1]) >-1) if(set[i].name[0]!='-') sprintf(&printbuf[strlen(printbuf)],"%s,", set[i].name); 
      sprintf(&printbuf[strlen(printbuf)],"\n"); if(strlen(printbuf)>12) printf("%s", printbuf);
    }
    else if (compare(pickfunc, "qdis", 4) == 4)
    {
      if(qdisFlag==1)
      {
        qdisFlag=0;
        v_qdis[1][0]=point[name[1]].px* scale->w+scale->x;
        v_qdis[1][1]=point[name[1]].py* scale->w+scale->y;
        v_qdis[1][2]=point[name[1]].pz* scale->w+scale->z;
        for(i=0; i<3; i++) { v0[i]=v_qdis[0][i]; v1[i]=v_qdis[1][i]; }
        v0[0]=v1[0]=0.; 
        dax=v_angle(v0,v1);
        for(i=0; i<3; i++) { v0[i]=v_qdis[0][i]; v1[i]=v_qdis[1][i]; }
        v0[1]=v1[1]=0.; 
        day=v_angle(v0,v1);
        for(i=0; i<3; i++) { v0[i]=v_qdis[0][i]; v1[i]=v_qdis[1][i]; }
        v0[2]=v1[2]=0.; 
        daz=v_angle(v0,v1);
        for(i=0; i<3; i++) { v0[i]=v_qdis[0][i]; v1[i]=v_qdis[1][i]; }
        printf("dist= %lf dx=%lf dy=%lf dz=%lf da=%lf dax=%lf day=%lf daz=%lf dr=%lf drx=%lf dry=%lf drz=%lf\n",
        sqrt((v_qdis[1][0]-v_qdis[0][0])*(v_qdis[1][0]-v_qdis[0][0])+
          (v_qdis[1][1]-v_qdis[0][1])*(v_qdis[1][1]-v_qdis[0][1])+
          (v_qdis[1][2]-v_qdis[0][2])*(v_qdis[1][2]-v_qdis[0][2])), 
          v_qdis[1][0]-v_qdis[0][0],v_qdis[1][1]-v_qdis[0][1],v_qdis[1][2]-v_qdis[0][2],
          v_angle(v_qdis[0],v_qdis[1])*180./pi,dax*180./pi,day*180./pi,daz*180./pi,
          sqrt(v1[0]*v1[0]+v1[1]*v1[1]+v1[2]*v1[2])-sqrt(v0[0]*v0[0]+v0[1]*v0[1]+v0[2]*v0[2]),
          sqrt(v1[1]*v1[1]+v1[2]*v1[2])-sqrt(v0[1]*v0[1]+v0[2]*v0[2]),
          sqrt(v1[0]*v1[0]+v1[2]*v1[2])-sqrt(v0[0]*v0[0]+v0[2]*v0[2]),
          sqrt(v1[0]*v1[0]+v1[1]*v1[1])-sqrt(v0[0]*v0[0]+v0[1]*v0[1]) );
      }
      else
      {
        qdisFlag=1;
        v_qdis[0][0]=point[name[1]].px* scale->w+scale->x;
        v_qdis[0][1]=point[name[1]].py* scale->w+scale->y;
        v_qdis[0][2]=point[name[1]].pz* scale->w+scale->z;
      }
    }
    else if (compare(pickfunc, "qlin", 4) == 4)
    {
      if( type[1] == 'b') entitybuf=createLine( point[name[1]].name, 0 ); /* start line */
      if( type[1] == 'c') entitybuf=createLine( point[name[1]].name, 2 ); /* add centerpnt */
      if( type[1] == 'm') entitybuf=createLine( point[name[1]].name, 3 ); /* midpnt, create centerpnt */
      if( type[1] == 't') entitybuf=createLine( point[name[1]].name, 4 ); /* seq, create set */
      if( type[1] == 'g') entitybuf=createLine( point[name[1]].name, 1 ); /* end  line */
    }
    else if (compare(pickfunc, "qcnt", 4) == 4)
    {
      center( point[name[1]].px, point[name[1]].py, point[name[1]].pz);
      dx_cur=PICK_LENGTH; dy_cur=PICK_LENGTH;
      glutSetWindow( w1);
      /* Keyboardfunktion wiederherstellen (von pick())  */
      pickFlag=0;
      free(selectBuf); selectBuf=NULL;
      glutKeyboardFunc ( Keyboard );
      glutSetWindow( activWindow );
    }
    else if (compare(pickfunc, "qdel", 4) == 4) seta( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qadd", 4) == 4) seta( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qrem", 4) == 4) setr( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qpnt", 4) == 4)
    {
      if(surfNr>-1) /* move points to a surface */
        seta( setNrbuf, type, name[1]);
      else movePoint(name[1], x, y);
    }
    else if (compare(pickfunc, "qali", 4) == 4) pre_align( name[1], 1 );
    else if (compare(pickfunc, "qcut", 4) == 4) pre_cut( name[1], 1 );
  }
  else if (name[0] == 'l')
  {
    if (line[name[1]].name[0]==(unsigned char)NULL) return(0);

    if ((compare(pickfunc, "qbia", 4) == 4)&&(line[name[1]].div>1)) 
    {
      if(type[3]=='c')
        line[name[1]].bias=1./line[name[1]].bias;
      else
      {
        if(line[name[1]].bias<1.)
          line[name[1]].bias = 1./pow((double)pickbuf, (1./((double)line[name[1]].div-1.)));
        else
          line[name[1]].bias = pow((double)pickbuf, (1./((double)line[name[1]].div-1.)));
      }
    }
    else if (compare(pickfunc, "qdiv", 4) == 4)
    {
      if((line[name[1]].bias!=1.)&&(pickbuf>1))
      {
        if(line[name[1]].bias<1.)
        {
          /* bias must be recalculated */
          bias_fbd= pow(1./line[name[1]].bias,(line[name[1]].div-1.)) +0.5;
          line[name[1]].bias= 1./(1./line[name[1]].bias * pow(bias_fbd,(1./((double)pickbuf-1.)))/pow(bias_fbd,(1./((double)line[name[1]].div-1.))));
        }
        else
        {
          /* bias must be recalculated */
          bias_fbd= pow(line[name[1]].bias,(line[name[1]].div-1.)) +0.5;
          line[name[1]].bias*= pow(bias_fbd,(1./((double)pickbuf-1.)))/pow(bias_fbd,(1./((double)line[name[1]].div-1.)));
        }
      }
      else if(pickbuf==1) line[name[1]].bias=1.;
      line[name[1]].div=pickbuf;
      rep(name[1]);
    }

    bias_fbd=getBias_fbd(name[1], line);

    if (line[name[1]].typ=='a')
      printf ("%s p1:%s p2:%s pc:%s div:%d bias:%d bias_el:%lf\n"
      , line[name[1]].name, point[line[name[1]].p1].name, point[line[name[1]].p2].name
      , point[line[name[1]].trk].name, line[name[1]].div, bias_fbd, line[name[1]].bias  );
    else if (line[name[1]].typ=='s')
      printf ("%s p1:%s p2:%s set:%s div:%d bias:%d bias_el:%lf\n"
      , line[name[1]].name, point[line[name[1]].p1].name, point[line[name[1]].p2].name
      , set[line[name[1]].trk].name, line[name[1]].div, bias_fbd, line[name[1]].bias  );
    else if (line[name[1]].typ==' ')
      printf ("%s p1:%s p2:%s div:%d bias:%d bias_el:%lf\n"
      , line[name[1]].name, point[line[name[1]].p1].name, point[line[name[1]].p2].name
      , line[name[1]].div, bias_fbd, line[name[1]].bias );

    if (compare(pickfunc, "qenq", 4) == 4)
    {
      sprintf(printbuf, "    in set=");
      for(i=1; i<anzGeo->sets; i++)
        if(!set[i].type)
          if( getIndex(&set[i].line,set[i].anz_l,name[1]) >-1) if(set[i].name[0]!='-') sprintf(&printbuf[strlen(printbuf)],"%s,",set[i].name);  
      sprintf(&printbuf[strlen(printbuf)],"\n"); if(strlen(printbuf)>12) printf("%s", printbuf);
    }
    else if (compare(pickfunc, "qdel", 4) == 4) seta( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qadd", 4) == 4) seta( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qrem", 4) == 4) setr( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qseq", 4) == 4) convertLine( name[1], pickbuf );
    else if ((compare(pickfunc, "qspl", 4) == 4)||((compare(pickfunc, "qlin", 4) == 4)&&(type[1]=='s') ))
    {
      for(j=0; j<qspl_i; j++) if(qspl_indx[j]==name[1]) return(0);
      if (qspl_i<MAX_LINES) qspl_indx[qspl_i]=name[1];
      else { printf(" ERROR in hitAction(), to much lines picked. Increase MAX_LINES\n"); return(0); }
      qspl_i++;
      k= splitLine( name[1], x, y );
      if(k>-1) seta( setNrbuf, "p", k);
      if(set[setNrbuf].anz_p>1)
      {
        sprintf( buffer,"p %s %lf", set[setNrbuf].name, gtol);
        pre_merge( buffer);
      }
    }
    else if (compare(pickfunc, "qsur", 4) == 4) strcpy(type, line[name[1]].name);
    else if (compare(pickfunc, "qlin", 4) == 4) lineNr=name[1];
  }
  else if (name[0] == 's')
  {
    if (surf[name[1]].sh<0) printf ("%s %1c BLEND ", surf[name[1]].name, surf[name[1]].ori );
    else printf ("%s %1c %s ", surf[name[1]].name, surf[name[1]].ori, nurbs[surf[name[1]].sh].name );
    for (j=0; j<surf[name[1]].nl; j++)
    {
      if (surf[name[1]].typ[j]=='l')
      {
        printf (" %1c %s", surf[name[1]].o[j], line[surf[name[1]].l[j]].name );
      }
      else
      {
        printf (" %1c %s", surf[name[1]].o[j], lcmb[surf[name[1]].l[j]].name );
        for (k=0; k<lcmb[surf[name[1]].l[j]].nl; k++ )
        {
          printf (" (%c) (%s)", lcmb[surf[name[1]].l[j]].o[k], line[lcmb[surf[name[1]].l[j]].l[k]].name );
        }
      }
    }
    printf (" \n");
    if (compare(pickfunc, "qenq", 4) == 4)
    {
      sprintf(printbuf, "    in set=");
      for(i=1; i<anzGeo->sets; i++)
        if(!set[i].type)
          if( getIndex(&set[i].surf,set[i].anz_s,name[1]) >-1) if(set[i].name[0]!='-') sprintf(&printbuf[strlen(printbuf)],"%s,",set[i].name);  
      sprintf(&printbuf[strlen(printbuf)],"\n"); if(strlen(printbuf)>12) printf("%s", printbuf);
    }
    else if (compare(pickfunc, "qdel", 4) == 4) seta( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qadd", 4) == 4) seta( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qrem", 4) == 4) setr( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qsur", 4) == 4)
    {
      /* change the interior def to BLEND */ 
      if(type[1]=='b')
      {
        if(surf[name[1]].pgn!=NULL)
	{
          surf[name[1]].sh=-1; free(surf[name[1]].pgn); surf[name[1]].pgn=NULL; surf[name[1]].npgn=0;
          repSurf(name[1]);
	}
        else
        {
          surf[name[1]].sh=-1; free(surf[name[1]].pgn); surf[name[1]].pgn=NULL; surf[name[1]].npgn=0;
	}
        printf (" interior changed to BLEND\n");
      }
      else if(type[1]=='s')
      {
	/* if a Nurbs was chosen change the interior def of the selected surf */
        if(nurbsNr>-1)
	{
          surf[name[1]].sh=nurbsNr;
          if(surf[name[1]].pgn!=NULL)
	  {
            free(surf[name[1]].pgn); surf[name[1]].pgn=NULL; surf[name[1]].npgn=0;

            /* create the interior */
            repSurf(name[1]);
	  }
          printf (" interior changed to Nurbs: %s\n", nurbs[surf[name[1]].sh].name );
	}
	/* define this surf-name as the default name */
        else
	{  
          printf(" Active surf:%s\n", surf[name[1]].name);
          surfNr=name[1];
	}
      }  
    }
    else if (compare(pickfunc, "qbod", 4) == 4) pickstack(name[1]);
    else if (compare(pickfunc, "qflp", 4) == 4) flip( type, name[1]);
    else if (compare(pickfunc, "qpnt", 4) == 4) 
    {
      /* mark a surface as a target for the point-projection */
      if(surf[name[1]].sh>-1)
      {
        surfNr=name[1];
      }
      else
      {
        printf("WARNING: surf:%s is not related to a nurbs, surf can not be used for projection\a\n", surf[name[1]].name);
      }
    }
  }
  else if (name[0] == 'b')
  {
    printf ("%s %1c", body[name[1]].name, body[name[1]].ori );
    for (j=0; j<body[name[1]].ns; j++)
      printf (" %1c %s", body[name[1]].o[j], surf[body[name[1]].s[j]].name );
    printf (" \n");
    if (compare(pickfunc, "qenq", 4) == 4)
    {
      sprintf(printbuf, "    in set=");
      for(i=1; i<anzGeo->sets; i++)
        if(!set[i].type)
          if( getIndex(&set[i].body,set[i].anz_b,name[1]) >-1) if(set[i].name[0]!='-') sprintf(&printbuf[strlen(printbuf)],"%s,",set[i].name);  
      sprintf(&printbuf[strlen(printbuf)],"\n"); if(strlen(printbuf)>12) printf("%s", printbuf);
    }
    else if (compare(pickfunc, "qdel", 4) == 4) seta( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qadd", 4) == 4) seta( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qrem", 4) == 4) setr( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qbod", 4) == 4) bodyNr=name[1];
  }
  else if (name[0] == 'L')
  {
    printf ("%s \n", nurbl[name[1]].name);
    if (compare(pickfunc, "qenq", 4) == 4)
    {
      sprintf(printbuf, "    in set=");
      for(i=1; i<anzGeo->sets; i++)
        if(!set[i].type)
          if( getIndex(&set[i].nurl,set[i].anz_nurl,name[1]) >-1) if(set[i].name[0]!='-') sprintf(&printbuf[strlen(printbuf)],"%s,",set[i].name);  
      sprintf(&printbuf[strlen(printbuf)],"\n"); if(strlen(printbuf)>12) printf("%s", printbuf);
    }
    else if (compare(pickfunc, "qdel", 4) == 4) seta( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qadd", 4) == 4) seta( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qrem", 4) == 4) setr( setNrbuf, type, name[1]);
  }
  else if (name[0] == 'S')
  {
    printf ("%s \n", nurbs[name[1]].name);
    if (compare(pickfunc, "qenq", 4) == 4)
    {
      sprintf(printbuf, "    in set=");
      for(i=1; i<anzGeo->sets; i++)
        if(!set[i].type)
          if( getIndex(&set[i].nurs,set[i].anz_nurs,name[1]) >-1) if(set[i].name[0]!='-') sprintf(&printbuf[strlen(printbuf)],"%s,",set[i].name);  
      sprintf(&printbuf[strlen(printbuf)],"\n"); if(strlen(printbuf)>12) printf("%s", printbuf);
    }
    else if (compare(pickfunc, "qdel", 4) == 4) seta( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qadd", 4) == 4) seta( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qrem", 4) == 4) setr( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qsur", 4) == 4)
    {
      /* if a a default surf is known apply the nurbs */
      if(surfNr>-1)
      {
        surf[surfNr].sh=name[1];

	/* if it was prepared for illumination, change the interior def of the selected surf */
        if(surf[surfNr].pgn!=NULL)
	{
          free(surf[surfNr].pgn); surf[surfNr].pgn=NULL; surf[surfNr].npgn=0;

          /* create the interior */
          repSurf(surfNr);
	}
        /* reset the active nurbs */
        nurbsNr=-1;
      }
      else
      {
	printf(" Active Nurbs:%s\n", nurbs[name[1]].name);
        nurbsNr=name[1];
      }
    }
  }
  else printf ("\n");
  return(1);
}


int hitUndo( GLuint *name, unsigned char *type, int x, int y )
{
  /* name[0]== picked type   */
  /* name[1]== picked name(Nr)  */
  /* type[0] == gkey in pick()  */
  if (name[0] == 'e')
  {
    printf (" element: %d \n", name[1]);
    /* if (compare(pickfunc, "qdel", 4) == 4) */
    if (compare(pickfunc, "qadd", 4) == 4) setr( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qrem", 4) == 4) seta( setNrbuf, type, name[1]);
  }
  else if (name[0] == 'f')
  {
    printf (" face: %d \n", name[1]);
    /* if (compare(pickfunc, "qdel", 4) == 4) */
    if (compare(pickfunc, "qadd", 4) == 4) setr( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qrem", 4) == 4) seta( setNrbuf, type, name[1]);
  }
  else if (name[0] == 'n')
  {
    /* if (compare(pickfunc, "qdel", 4) == 4) */
    if (compare(pickfunc, "qadd", 4) == 4) setr( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qrem", 4) == 4) seta( setNrbuf, type, name[1]);
  }
  else if (name[0] == 'p')
  {
    /*
    if (compare(pickfunc, "qdel", 4) == 4)
    */
    if (compare(pickfunc, "qadd", 4) == 4) setr( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qrem", 4) == 4) seta( setNrbuf, type, name[1]);
  }
  else if (name[0] == 'l')
  {
    /*
    if (compare(pickfunc, "qdiv", 4) == 4) { line[name[1]].div=pickbuf; rep(name[1]); }
    if (compare(pickfunc, "qspl", 4) == 4) splitLine( name[1], x, y, type[1]);
    if (compare(pickfunc, "qdel", 4) == 4) setr( setNrbuf, type, name[1]);
    */
    if (compare(pickfunc, "qadd", 4) == 4) setr( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qrem", 4) == 4) seta( setNrbuf, type, name[1]);
  }
  else if (name[0] == 's')
  {
    if (compare(pickfunc, "qadd", 4) == 4) setr( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qrem", 4) == 4) seta( setNrbuf, type, name[1]);
    /*
    if (compare(pickfunc, "qdel", 4) == 4) 
    */
  }
  else if (name[0] == 'b')
  {
    /* if (compare(pickfunc, "qdel", 4) == 4) */
    if (compare(pickfunc, "qadd", 4) == 4) setr( setNrbuf, type, name[1]);
    else if (compare(pickfunc, "qrem", 4) == 4) seta( setNrbuf, type, name[1]);
  }
  else printf ("\n");
  return(1);
}

int pickstack( GLuint name )
{
  printf (" pickstack: name:%d added\n", name );
  pickdata[0]++;
  if (pick_buffer<=pickdata[0])
  {
    pick_buffer=DPICK_BUFFER+pickdata[0]; 
    if((pickdata=(int *)realloc((int *)pickdata,(pick_buffer)*sizeof(int)))==NULL)
    { printf("\n\nERROR: realloc failure in pickstack\a\n");
    return(-1); }
  }    
  pickdata[pickdata[0]]=name;
  return(pickdata[0]);
}

int processHits( GLint hits, GLuint *buffer, unsigned char *type, unsigned char *mode, int x, int y )
{
  int i;
  GLuint   *ptr, key, name[2];


  pick_zmin=(unsigned int)(pow(2,32)-1);
  name[0]=-1;
  name[1]=-1;

  /* key=tolower(type[0]); */
  key=type[0];
  ptr=buffer;
  /* ptr pro hit: anz_names, pick_zmin, max_z, name_1, name_n, ... */
  if (hits)
  {
    /*
    printf (" hits= %d type %c\n", hits, type[0]);
    */
    if ( mode[0] == 'i')
    {
      for (i=0; i<hits; i++) /* suche hit mit pick_zmin */
      {
        /*
        printf ("hitrecord: %u %u %u %c %c %c key:%c\n", *(ptr), *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), (unsigned char)tolower(type[0]), key);
	*/
        ptr+=2;
        if(((unsigned int)ptr[0] <= (unsigned int)pick_zmin) &&(ptr[1] == key) )
        {
          pick_zmin=*ptr; name[0]=type[0]; name[1]=*(ptr+2);
	  /*
          printf ("pick_zmin:%u typ:%c name:%u key:%c\n",
            pick_zmin, name[0], name[1], (unsigned int)type[0] );
          */
        }
        ptr+=1+*(ptr-2);
      }
      if (name[0]!=(GLuint)-1)
      {
        if (type[3]=='u')  hitUndo( name, type, x, y );
        else               hitAction( name, type, x, y);
      }
    }
    if ( mode[0] == 'a')
    {
      for (i=0; i<hits; i++) /* collect all hits */
      {
      /*
      printf ("hitrecord: %u %u %u %c %u\n", *(ptr), *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4) );
      */
        ptr+=2;
        if ((unsigned int)ptr[1] == (unsigned int)key)
        {
          pick_zmin=*ptr; name[0]=type[0]; name[1]=*(ptr+2);
          /*  
          printf ("pick_zmin:%u typ:%1c name:%u key:%1c\n",
            pick_zmin, name[0], name[1], type[0] );
          */
          if (type[3]=='u')  hitUndo( name, type, x, y );
          else               hitAction( name, type, x, y );
        }
        ptr+=1+*(ptr-2);
      }
    }
  }
  else printf ("\a\n");
  return(1);
}



void defineDiv( unsigned char gkey, int x, int y )
{
  static int i=0;
  static unsigned char type[MAX_NAME_LENGTH];
  if (i)
  {
    printf("%c\n",gkey);
    i=0;
    type[1]=gkey;
    pickbuf=atoi(type);
    glutKeyboardFunc ( pick );
    type[0]='l';
    type[1]=' ';
    type[2]=(unsigned char)NULL;
    goPicking(xbuf,ybuf,type);
  }
  else{ printf("%c",gkey); type[0]=gkey; i=1;}
}

/* fragt Keyboard ab, was im pick-mode zu tun ist  */
/* wenn "q" dann exit  */
void pick( unsigned char gkey, int x, int y )
{
  int  i,j,n,k;
  unsigned char flag;
  static int ii={0}, xcur[2], ycur[2], wtogle={0};
  static double yw[2], xw[2], dist;
  static int anz_lpc[EDGES_PER_SURF], clines[EDGES_PER_SURF][LINES_PER_EDGE], edge[EDGES_PER_SURF];
  unsigned char ctyp[EDGES_PER_SURF];
  static unsigned char type[MAX_NAME_LENGTH];
  int  icor, nr;
  static int anz_c=0;
  static unsigned char name[MAX_LINE_LENGTH], ori[2], blend[MAX_LINE_LENGTH], cori[EDGES_PER_SURF][2];
  static unsigned char *lori=NULL;
  static unsigned char face[SURFS_PER_BODY][MAX_LINE_LENGTH];
  static unsigned char *alreadyChecked=NULL;
  GLuint size_selectBuf;


  /* Achtung! Entities koennen mehrfach dargestellt sein! */
  if (anz->nmax>anzGeo->p) size_selectBuf=(GLuint)(MAX_BUF*anz->nmax)+100;
  else size_selectBuf=(GLuint)(MAX_BUF*anzGeo->p)+100;
  do{
    if( ( selectBuf= (GLuint *)realloc((GLuint *)selectBuf, size_selectBuf * sizeof(GLuint))) == NULL )
    {
      printf ("WARNING: in Pick() is size_selectBuf: %d to large and is reduced\n", size_selectBuf);
      size_selectBuf/=2;
    }
    if(size_selectBuf<100)
    {
      printf("\n\n ERROR: realloc Failure in pick()\a\n\n") ;
      return;
    }
  }while(!selectBuf);
  glSelectBuffer (size_selectBuf, selectBuf);


  /* trigger the appropriate action based on the gkey */
  if ( gkey == 'u') /* undo last picking-action */
  {
    if (compare(pickfunc, "qnod", 4) == 4)
    { 
      moveNode(-2, x, y);
    }
    if (compare(pickfunc, "qele", 4) == 4)
    { 
      if(entitybuf>=0) { delElem( 1, &entitybuf); entitybuf=-1; }
    }
    else if (compare(pickfunc, "qpnt", 4) == 4)
    { 
      if(entitybuf>=0) { delPnt( 1, &entitybuf); entitybuf=-1; }
      else
      {
        movePoint(-2, x, y);
      }
    }
    else if (compare(pickfunc, "qlin", 4) == 4)
    {
      if(entitybuf>=0) { delLine( 1, &entitybuf); entitybuf=-1; }
    }
    else if (compare(pickfunc, "qsur", 4) == 4)
    {
      if(entitybuf>=0) { delSurf( 1, &entitybuf); entitybuf=-1; }
      /* reset counters */
      anz_c=0;
      for (i=0; i<EDGES_PER_SURF; i++) anz_lpc[i]=0;
    }
    else if (compare(pickfunc, "qbod", 4) == 4)
    {
      if(entitybuf>=0) { delBody( 1, &entitybuf); entitybuf=-1; }
    }
    else if ((compare(pickfunc, "qadd", 4) == 4)||(compare(pickfunc, "qrem", 4) == 4))
    {
      type[3]='u';
      processHits( hits, selectBuf, type, mode, x, y );
      if (type[0]=='e') updateDispLists();
    }
    return;
  }

  type[0]=gkey;
  type[2]=(unsigned char)NULL;
  type[3]=(unsigned char)NULL;

  /* delete and reopen the temporary set which stores highlited entities, or quit */
  delSet(specialset->highl);
  if (( type[0] == 'q')||( type[0] == 'Q')) /* Exit Pick() */
  {
    pickfunc[0]=(char)NULL;
    dx_cur=PICK_LENGTH; dy_cur=PICK_LENGTH;
    glutSetWindow( w1);
    /* glutPassiveMotionFunc ( NULL ); */   /* schaltet mitgehenden Fangrahmen aus */
    free(selectBuf); selectBuf=NULL;
    glutKeyboardFunc ( Keyboard );    /* Keyboardfunkt wiederherstellen (von pick())  */
    glutSetWindow( activWindow );
    pickFlag=0;
    anz_c=0;
    entitybuf=-1;
    pntNr=-1;  
    lineNr=-1;   
    surfNr=-1;
    nurbsNr=-1;
    bodyNr=-1;  
    if (compare(pickfunc, "qsur", 4) == 4) 
    {
      anz_c=0;
      for (i=0; i<EDGES_PER_SURF; i++) anz_lpc[i]=0;
    }
    else if (compare(pickfunc, "qflp", 4) == 4) free(selem);

    if(getSetNr(specialset->tmp)>-1) delSet(specialset->tmp);
    printf (" done\n");
    return;
  }
  if ((pset = (Psets *)realloc( (Psets *)pset, (anzGeo->psets+1)*sizeof(Psets)) ) == NULL )
  {
    printf(" ERROR: realloc failure in plot, pset not installed\n\n");
    return;
  }
  set_highl= pre_seta( specialset->highl, "i", 0 );
  pset[anzGeo->psets].nr= set_highl;
  if (compare(pickfunc, "qsur", 4) == 4) { if(type[0]=='s') pset[anzGeo->psets].type[0]='s'; else pset[anzGeo->psets].type[0]= 'l'; }
  else if (compare(pickfunc, "qlin", 4) == 4) pset[anzGeo->psets].type[0]= 'p';
  else pset[anzGeo->psets].type[0]= tolower(gkey);
  if (pset[anzGeo->psets].type[0]=='p'||pset[anzGeo->psets].type[0]=='l'||pset[anzGeo->psets].type[0]=='s'||pset[anzGeo->psets].type[0]=='b') pset[anzGeo->psets].type[1]= 'a';
  else pset[anzGeo->psets].type[1]=(char)NULL;
  pset[anzGeo->psets].col=7;
  anzGeo->psets++;
  glutPostRedisplay();



  if ( type[0] == 'r') /*  new pick-area, print x,y */
  {
    xcur[ii]=x; ycur[ii]=y;
    if (ii)
    {
      ii=0;
      dx_cur= xcur[1]-xcur[0];
      dx_cur= sqrt( dx_cur*dx_cur );
      dy_cur= ycur[1]-ycur[0];
      dy_cur= sqrt( dy_cur*dy_cur );
      printf (" cursorArea set to dx_cur=%lf dy_cur=%lf\n", dx_cur, dy_cur);
    }
    else
      ii=1;
    return;
  }
  else if ( type[0] == 'w') /* show window koordinates */
  {
    xw[wtogle]=(double)x/width_w1*scale->w*2.*ds;
    yw[wtogle]=(double)y/width_w1*scale->w*2.*ds;
    if (wtogle)
    {
      dist=sqrt( (xw[1]-xw[0])*(xw[1]-xw[0]) + (yw[1]-yw[0])*(yw[1]-yw[0]) );
      printf (" P2 xw:%lf yw:%lf \n", xw[wtogle], yw[wtogle] );
      printf (" distance: %lf \n", dist);
      wtogle=0;
    }
    else
    {
      printf (" P1 xw:%lf yw:%lf \n", xw[wtogle], yw[wtogle]);
      wtogle=1;
    }
    return;
  }
  else if ((compare(pickfunc, "qenq", 4) == 4)||(compare(pickfunc, "qadd", 4) == 4)||
           (compare(pickfunc, "qdis", 4) == 4)||
           (compare(pickfunc, "qrem", 4) == 4)||(compare(pickfunc, "qdel", 4) == 4))
  {
    if ( type[0] == 'a') /*  pick all in range mode */
    {
      mode[0]='a';
      printf ("mode:%s\n", mode);
      return;
    }
    if ( type[0] == 'i') /* individual pick mode */
    {
      mode[0]='i';
      dx_cur=PICK_LENGTH; dy_cur=PICK_LENGTH;
      printf ("mode:%s\n", mode);
      return;
    }
    if (compare(pickfunc, "qdel", 4) == 4) 
      if((type[0]=='n')||(type[0]=='e')||(type[0]=='p')||(type[0]=='l')||(type[0]=='s')||(type[0]=='b')
        ||(type[0]=='L')||(type[0]=='S'))
      {
        setNrbuf=pre_seta(specialset->zap, "i", 0 );
        if(setNrbuf<0) { printf(" ERROR: could not create set for qdel\a\n"); return; } 
      }

    goPicking(x,y,type);

    if (compare(pickfunc, "qdel", 4) == 4) zap(set[setNrbuf].name);
    if ((compare(pickfunc, "qadd", 4) == 4)||(compare(pickfunc, "qrem", 4) == 4)||(compare(pickfunc, "qdel", 4) == 4))
      if (type[0]=='e') updateDispLists();
  }

  else if ((compare(pickfunc, "qdiv", 4) == 4)||(compare(pickfunc, "qbia", 4) == 4)||(compare(pickfunc, "qseq", 4) == 4))
  {
    if ( type[0] == 'a') /*  pick all in range mode */
    {
      mode[0]='a';
      printf ("mode:%s\n", mode);
      return;
    }
    if ( type[0] == 'i') /* individual pick mode */
    {
      mode[0]='i';
      dx_cur=PICK_LENGTH; dy_cur=PICK_LENGTH;
      printf ("mode:%s\n", mode);
      return;
    }

    if(( type[0] == 'c')&&(compare(pickfunc, "qbia", 4) == 4)) /* change the bias-direction */
    {
      type[3]='c';
    }
    else if( type[0] == ' ')
    {
        xbuf=x; ybuf=y;
        printf(" define Div: \n");
        glutKeyboardFunc(defineDiv);
        return;
    }
    else
    {
      /* look if we have a valid integer > 0, then pick a line */
      type[1] = ' ';
      icor=atoi(type);
      if (( icor <1 )||( icor >9 ))
      {
        printf(" Key not known\n");
        return;
      }
      pickbuf=icor;
    }
    type[0]='l';
    goPicking(x,y,type);
  }

  else if (compare(pickfunc, "qcnt", 4) == 4)
  {
    if((type[0]=='n')||(type[0]=='p'))
      goPicking(x,y,type);
  }

  else if (compare(pickfunc, "qsur", 4) == 4)
  {
    /* create a gsur */
    if ( type[0] == 'a') /*  pick all in range mode */
    {
      mode[0]='a';
      printf ("mode:%s\n", mode);
      return;
    }
    if ( type[0] == 'i') /* individual pick mode */
    {
      mode[0]='i';
      dx_cur=PICK_LENGTH; dy_cur=PICK_LENGTH;
      printf ("mode:%s\n", mode);
      return;
    }

    if(type[0]=='b')
    {
      /* reset the active Nurbs */
      nurbsNr=-1;

      type[0]='s'; type[1]='b';
      goPicking(x,y,type);
    }
    else if(type[0]=='s') { type[0]='s'; type[1]='s'; goPicking(x,y,type); }
    else if(type[0]=='S') { type[0]='S'; type[1]='s'; goPicking(x,y,type); }
    else if(type[0]=='g')
    {
      /* look if we have the right amount of edges */
      if( anz_c>=EDGES_PER_SURF-1)
      {
        printf("ERROR: more(%d) than %d edges defined, start again\n\a", anz_c, EDGES_PER_SURF-1);
        anz_c=0;
        for (i=0; i<EDGES_PER_SURF; i++)
          anz_lpc[i]=0;
        return;
      }
      /* look if all edges are propperly defined */
      for (i=0; i<anz_c; i++)
      {
        if (anz_lpc[i]<1)
	{
          printf("ERROR: define edge Nr:%d\n", i+1);
          return;
        }
      }
      printf ("generate surf ");
      strcpy(ori, "+");
      for (i=0; i<anz_c; i++)
      {
        strcpy( cori[i], "+");
        if (anz_lpc[i]==1)                 /* we have a single line */
	{
          nr=clines[i][0];
          edge[i]=nr;
          ctyp[i]='l';
        }
        else                               /* we need a lcmb, puuh  */
	{
          /* do we already have a suitable lcmb? */
          flag=0;
          for (j=0; j<anzGeo->c; j++ )
	  {
            if (lcmb[j].nl==anz_lpc[i])   /* same amount of lines */
	    {
              printf ("check lcmb:%s \n", lcmb[j].name);
	     
              if((alreadyChecked=(unsigned char *)realloc((unsigned char *)alreadyChecked,(anz_lpc[i])*sizeof(unsigned char)))==NULL)
              { printf(" ERROR: realloc failure in pick()\n\n"); return; }
	      for (k=0; k<anz_lpc[i]; k++) alreadyChecked[k]=0; /* reset */
              for (n=0; n<lcmb[j].nl; n++)
	      {
                flag=0;
                for (k=0; k<anz_lpc[i]; k++)
		{
		  /*
                  printf ("c:%s == l:%s\n", line[lcmb[j].l[n]].name, line[clines[i][k]].name);
		  */
                  if ((lcmb[j].l[n]==clines[i][k])&&(alreadyChecked[k]==0))
                  {
                    flag=1;               /* share that line */
                    alreadyChecked[k]=1;
                  }
		}
                if (!flag) goto not_equal_lcmb;
	      }
	     
              printf ("equal\n");
	     
              break;
	    }
            else flag=0;
            not_equal_lcmb:;
	  }

          if (!flag)  /* no lcmb was found, so create one */
	  {
            if((lori=(unsigned char *)realloc((unsigned char *)lori, (anz_lpc[i])*sizeof(unsigned char)) ) == NULL )
            { printf(" ERROR: realloc failure in pick()\n\n"); return; }
            for (j=0; j<anz_lpc[i]; j++) lori[j]='+';
            getNewName( name, "c" );
            n=lcmb_i( name, 0, anz_lpc[i], lori, clines[i] );
            if(n <0 )
            {
              printf ("ERROR: lcmb in error, start again\n\a");
              anz_c=0;
              for (j=0; j<EDGES_PER_SURF; j++) anz_lpc[j]=0;
              return;
            }
            edge[i]=n;
            ctyp[i]='c';
	  }
          else
	  {
            printf ("use existing lcmb:%s \n", lcmb[j].name );
            edge[i]=j;
            ctyp[i]='c';
          }
        }
      }
      if(surfNr==-1) getNewName( name, "s" );
      else
      /* surfNr will be used as a name for the next generated surface and the original surface will be destroyed. The buffer is then reseted */
      { strcpy(name,surf[surfNr].name); ori[0]=surf[surfNr].ori; nurbsNr=surf[surfNr].sh; surfNr=-1; }
      printf (" name: %s\n", name );
      entitybuf= surface_i( name, ori[0], nurbsNr, anz_c, &cori[0][0], edge, ctyp );
      /* reset counters */
      anz_c=0;
      for (i=0; i<EDGES_PER_SURF; i++) anz_lpc[i]=0;
    }

    /* look if we have a valid integer < 0, then pick a line */
    type[1]=(unsigned char)NULL;
    icor=atoi(type)-1;
    if (icor>=EDGES_PER_SURF-1)
    {
      printf ("ERROR: Only %d edges per surface possible (not:%s!)\a\n", EDGES_PER_SURF-1, type);
      return;
    }
    if ( icor>=0 )
    {
      if( icor>=anz_c) anz_c=icor+1;
      type[0]='l';
      goPicking(x,y,type);
      nr=getLineNr(type);
      if ( nr>-1)          /* picking was successfull */
      {
        clines[icor][anz_lpc[icor]]=getLineNr(type);
        printf ("%d edge:%d lines:%d Name:%s index:%d\n",
               anz_c, icor, anz_lpc[icor], type, clines[icor][anz_lpc[icor]]);
        anz_lpc[icor]++;
      }
      else
        printf ("WARNING: No line picked, please try again! \a\n");
    }
  }
  else if (compare(pickfunc, "qbod", 4) == 4)
  {
    /* create a gbod */

    if ( type[0] == 'a') /*  pick all in range mode */
    {
      mode[0]='a';
      printf ("mode:%s\n", mode);
    }
    else if ( type[0] == 'i') /* individual pick mode */
    {
      mode[0]='i';
      dx_cur=PICK_LENGTH; dy_cur=PICK_LENGTH;
      printf (" mode:%s\n", mode);
    }

    else if ( type[0] == 'b') /* get a body to replace */
    {
      goPicking(x,y,type);
    }
    else if(type[0]=='g')
    {
      if(bodyNr==-1) getNewName( name, "b" );
      else { strcpy(name,body[bodyNr].name); bodyNr=-1; }
      printf (" generate body:%s\n", name);

      /* look if we have the right amount of faces */
      if( anz_c==2)
      {
        /* try to create the missing surfs */
        entitybuf=body_( name, &face[0][0] );
      }
      else
      {
        strcpy( blend, "NORM");
        for (i=0; i<anz_c; i++) strcpy( cori[i], "+");
        entitybuf=gbod( name, blend, anz_c, &cori[0][0], &face[0][0] );
      }

      /* reset counters */
      anz_c=0;
      pickdata[0]=0;
      pick_buffer=0;
    }

    else if((type[0]=='s')||(type[0]=='S'))
    {
      goPicking(x,y,type);
      for (i=0; i<pickdata[0]; i++)
      {
        nr=getSurfNr(surf[pickdata[i+1]].name);
        if (nr>-1)
        {
          strcpy( face[i+anz_c], surf[pickdata[i+1]].name );
          printf (" sum:%d face:%d surf:%s \n", i+1+anz_c, pickdata[i+1], face[i+anz_c]);
        }
        else
          printf("pick failed, surf not known\n");
      }
      anz_c+=i;
      pickdata[0]=0;
    }
  }

  else if (compare(pickfunc, "qlin", 4) == 4)
  {
    /*  type[0] l:end a line b:start a line c:add centerpoint */
    if(type[0]=='l')
    {
      type[1]=type[0];
      goPicking(x,y,type);
    }
    else if((type[0]=='g')||(type[0]=='b')||(type[0]=='c')||(type[0]=='m')||(type[0]=='t'))
    {
      type[1]=type[0];
      type[0]='p';
      goPicking(x,y,type);
    }
    else if(type[0]=='s')
    {
      qspl_i=0;           /* forget the splitted lines */
      type[1]=type[0];
      type[0]='l';
      goPicking(x,y,type);
    }
  }

  else if ((compare(pickfunc, "qali", 4) == 4)||(compare(pickfunc, "qcut", 4) == 4))
  {
    if((type[0]=='n')||(type[0]=='p'))
      goPicking(x,y,type);
  }

  else if (compare(pickfunc, "qele", 4) == 4)
  {
    if ( type[0] == 's') /* generate shell element */
    {
      createElem(-1);
      /* pickFlag=1; */
    }
    if ( type[0] == 'v') /* generate volume element */
    {
      createElem(-2);
      /* pickFlag=1; */
    }
    else if (type[0]=='n')
    {
      goPicking(x,y,type);
    }
  }

  else if (compare(pickfunc, "qnod", 4) == 4)
  {
    if ( type[0] == 'm') /*  move item */
    {
       moveNode(-1, x, y);
       /* pickFlag=1; */
       entitybuf=-1;      /* if not, undo would delete the last created entity */
    }
    else if (type[0]=='p')
    {
      type[0]='n';
      goPicking(x,y,type);
    }
  }

  else if (compare(pickfunc, "qpnt", 4) == 4)
  {
    if ( type[0] == 'a') /*  pick all in range mode */
    {
      mode[0]='a';
      printf ("mode:%s\n", mode);
      return;
    }
    if ( type[0] == 'i') /* individual pick mode */
    {
      mode[0]='i';
      dx_cur=PICK_LENGTH; dy_cur=PICK_LENGTH;
      printf ("mode:%s\n", mode);
      return;
    }
    if ( type[0] == 'm') /*  move item */
    {
      surfNr=-1;
      movePoint(-1, x, y);
      /* pickFlag=1; */
      entitybuf=-1;      /* if not, undo would delete the last created entity */
    }
    else if ( type[0] == 'g') /* create a new point */
    {
      surfNr=-1;
      entitybuf=createPoint( x, y );
    }
    else if (type[0]=='p')  /* choose a point */
    {
      goPicking(x,y,type);
      if(surfNr>-1) /* move points to a surface */
      {
        movePoint(0, x, y);
      }
    }
    else if (type[0]=='s')  /* choose a surface for projection */
    {
      if(getSetNr(specialset->tmp)>-1) delSet(specialset->tmp);
      setNrbuf=pre_seta(specialset->tmp, "i", 0 );
      if(setNrbuf<0) { printf(" ERROR: could not create set for qpnt\a\n"); return; } 
      goPicking(x,y,type);
    }
  }

  else if (compare(pickfunc, "qspl", 4) == 4)
  {
    if ( type[0] == 'a') /*  pick all in range mode */
    {
      mode[0]='a';
      printf ("mode:%s\n", mode);
      return;
    }
    if ( type[0] == 'i') /* individual pick mode */
    {
      mode[0]='i';
      dx_cur=PICK_LENGTH; dy_cur=PICK_LENGTH;
      printf ("mode:%s\n", mode);
      return;
    }
    if( type[0] == 's') /*  split lines */
    {
      qspl_i=0;           /* forget the splitted lines */
      setNrbuf=pre_seta(specialset->tmp, "i", 0 );
      if(setNrbuf<0) { printf(" ERROR: could not create set for qdel\a\n"); return; } 
      type[1]=type[0];
      type[0]='l';
      goPicking(x,y,type);
    }
    else printf(" command not known\a\n");
  }

  else if (compare(pickfunc, "qflp", 4) == 4)
  {
    if ( type[0] == 'a') /* orient all connected surfs */
    {
      mode[0]='a';
      printf ("mode:%s\n", mode);
      return;
    }
    if ( type[0] == 'i') /* individual pick mode */
    {
      mode[0]='i';
      type[1]='i';
      dx_cur=PICK_LENGTH; dy_cur=PICK_LENGTH;
      printf ("mode:%s\n", mode);
      return;
    }
    if (( type[0] == 's')||( type[0] == 'e')) /* flip surf and elems  or only elem */
    {
      if(mode[0]=='a')
      {
	mode[0]='i'; /* change back to indiv because the surf-connection will identify the others */
        type[1]='a';
      }
      goPicking(x,y,type);
    }
  }
}

/* look whats drawn in the picking-rectangle  */
void goPicking( int x, int y, unsigned char *type )
{
  int j;
  GLint  viewport[4];

  glGetIntegerv (GL_VIEWPORT, viewport);
  /*    glClearColor ( backgrndcol_rgb[0], backgrndcol_rgb[1], backgrndcol_rgb[2], backgrndcol_rgb[3] );  */
  /*    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);   */

  /*    glRenderMode (GL_SELECT);   */
  /*    glInitNames();   */
  /*    glPushName (-1);   */
  glRenderMode (GL_SELECT);   
  glInitNames();   
  glPushName (-1);   


  glLoadIdentity ();
  gluPickMatrix( (GLdouble) x, (GLdouble) (viewport[3]-y), dx_cur,dy_cur, viewport);
  moveModel();

  if (drawMode==4)
  {
    drawSets( PICK );
  }
  else
  {
    if(surfFlag==1) 
    {
      if(type[0]=='e')
      {
        for (j=0; j<anzGeo->psets; j++ )
        {
          if(pset[j].type[0]=='f') drawFaces_plot( set[pset[j].nr].anz_f, set[pset[j].nr].face, node, face, 2, 'e',0 );
        }
      }
      else if(type[0]=='f')
      {
        for (j=0; j<anzGeo->psets; j++ )
        {
          if(pset[j].type[0]=='f') drawFaces_plot( set[pset[j].nr].anz_f, set[pset[j].nr].face, node, face, 2, 0,PICK );
        }
      }
      else if(type[0]=='n')
      {
        for (j=0; j<anzGeo->psets; j++ )
        {
          if(pset[j].type[0]=='f') drawFaceNodes_plot( set[pset[j].nr].anz_f, set[pset[j].nr].face, node, face, 2, 0 );
        }
      }
    }
    else 
    {
      if(type[0]=='e')
      {
        for (j=0; j<anzGeo->psets; j++ )
        {
          if(pset[j].type[0]=='e') drawElements_plot( set[pset[j].nr].anz_e, set[pset[j].nr].elem, node, e_enqire, 2, 0,PICK );
        }
      }
      else if(type[0]=='f')
      {
        for (j=0; j<anzGeo->psets; j++ )
        {
          if(pset[j].type[0]=='f') drawFaces_plot( set[pset[j].nr].anz_f, set[pset[j].nr].face, node, face, 2, 0,PICK );
        }
      }
      else if(type[0]=='n')
      {
        for (j=0; j<anzGeo->psets; j++ )
        {
          if(pset[j].type[0]=='e') drawElemNodes_plot( set[pset[j].nr].anz_e, set[pset[j].nr].elem, node, e_enqire, 2, 0 );
        }
      }
    }
  }
  /*     glutSwapBuffers();  */
  /*     glFlush(); */
  glFlush();

  hits = glRenderMode (GL_RENDER);
  if (hits<0)
  {
    printf("\nWARNING: Overflow occured, select a smaler region and try again!\a\n");
  }
  else
  {
    processHits( hits, selectBuf, type, mode, x, y );
  }
}



void qali()
{
  pickFlag=1;
  mode[0]='i';
  strcpy( pickfunc, "qali");
  glutSetWindow( w1);
  glutKeyboardFunc ( pick );
  glutSetWindow( activWindow );
}
void qcut()
{
  pickFlag=1;
  mode[0]='i';
  strcpy( pickfunc, "qcut");
  glutSetWindow( w1);
  glutKeyboardFunc ( pick );
  glutSetWindow( activWindow );
}
void qele()
{
  pickFlag=1;
  mode[0]='i';
  strcpy( pickfunc, "qele");
  glutSetWindow( w1);
  glutKeyboardFunc ( pick );
  glutSetWindow( activWindow );
}
void qnod()
{
  pickFlag=1;
  mode[0]='i';
  strcpy( pickfunc, "qnod");
  glutSetWindow( w1);
  glutKeyboardFunc ( pick );
  glutSetWindow( activWindow );
}
void qcnt()
{
  pickFlag=1;
  mode[0]='i';
  strcpy( pickfunc, "qcnt");
  glutSetWindow( w1);
  glutKeyboardFunc ( pick );
  glutSetWindow( activWindow );
}
void qdis()
{
  pickFlag=1;
  mode[0]='i';
  strcpy( pickfunc, "qdis");
  glutSetWindow( w1);
  glutKeyboardFunc ( pick );
  glutSetWindow( activWindow );
}
void qenq()
{
  pickFlag=1;
  mode[0]='i';
  strcpy( pickfunc, "qenq");
  glutSetWindow( w1);
  glutKeyboardFunc ( pick );
  glutSetWindow( activWindow );
}
void qflp()
{
  int i,j;

  pickFlag=1;
  mode[0]='i';
  strcpy( pickfunc, "qflp");
  glutSetWindow( w1);
  glutKeyboardFunc ( pick );
  glutSetWindow( activWindow );
  if ((selem = (int *)malloc( (anz->emax+1)*sizeof(int)) ) == NULL )
  { printf("\n\nERROR: malloc failure in qflp\n"); return; }
  /* generate selem[elem]= index of surface */
  for (i=0; i<=anz->emax; i++) selem[i]=0;
  for (i=0; i<anzGeo->s; i++)
  {
    for (j=0; j<surf[i].ne; j++)
    {
      if((surf[i].elem[j]<=anz->emax)&&(surf[i].elem[j]>=anz->emin))
        selem[surf[i].elem[j]]=i;
    }
  }
}
void qbia()
{
  pickFlag=1;
  mode[0]='i';
  strcpy( pickfunc, "qbia");
  glutSetWindow( w1);
  glutKeyboardFunc ( pick );
  glutSetWindow( activWindow );
}
void qdiv()
{
  pickFlag=1;
  mode[0]='i';
  strcpy( pickfunc, "qdiv");
  glutSetWindow( w1);
  glutKeyboardFunc ( pick );
  glutSetWindow( activWindow );
}
void qseq()
{
  pickFlag=1;
  mode[0]='i';
  strcpy( pickfunc, "qseq");
  glutSetWindow( w1);
  glutKeyboardFunc ( pick );
  glutSetWindow( activWindow );
}
void qadd( unsigned char *record)
{
  setNrbuf=pre_seta( record, "i", 0);
  if(setNrbuf<0) { printf(" ERROR: could not create set for qadd\a\n"); return; } 
  pickFlag=1;
  mode[0]='i';
  strcpy( pickfunc, "qadd");
  glutSetWindow( w1);
  glutKeyboardFunc ( pick );
  glutSetWindow( activWindow );
}
void qdel( void )
{
  pickFlag=1;
  mode[0]='i';
  strcpy( pickfunc, "qdel");
  glutSetWindow( w1);
  glutKeyboardFunc ( pick );
  glutSetWindow( activWindow );
}
void qrem( unsigned char *record)
{
  setNrbuf=pre_seta( record, "i", 0);
  if(setNrbuf<0) { printf(" ERROR: could not create set for qrem\a\n"); return; } 
  pickFlag=1;
  mode[0]='i';
  strcpy( pickfunc, "qrem");
  glutSetWindow( w1);
  glutKeyboardFunc ( pick );
  glutSetWindow( activWindow );
}
void qpnt( unsigned char *record)
{
  if(strlen(record)) pntNr=getPntNr(record);
  pickFlag=1;
  mode[0]='i';
  strcpy( pickfunc, "qpnt");
  glutSetWindow( w1);
  glutKeyboardFunc ( pick );
  glutSetWindow( activWindow );
}
void qlin( unsigned char *record)
{
  if(strlen(record)) lineNr=getLineNr(record);
  pickFlag=1;
  mode[0]='i';
  strcpy( pickfunc, "qlin");
  glutSetWindow( w1);
  glutKeyboardFunc ( pick );
  glutSetWindow( activWindow );
}
void qsur( unsigned char *record)
{
  if(strlen(record)) surfNr=getSurfNr(record);
  pickFlag=1;
  mode[0]='i';
  strcpy( pickfunc, "qsur");
  glutSetWindow( w1);
  glutKeyboardFunc ( pick );
  glutSetWindow( activWindow );
}
void qbod( unsigned char *record)
{
  if(strlen(record)) bodyNr=getBodyNr(record);
  pickFlag=1;
  mode[0]='i';
  strcpy( pickfunc, "qbod");
  glutSetWindow( w1);
  glutKeyboardFunc ( pick );
  glutSetWindow( activWindow );
  if(pickdata==NULL) /* first time call */
  {
    pick_buffer=DPICK_BUFFER;
    if((pickdata=(int *)realloc((int *)pickdata,(pick_buffer)*sizeof(int)))==NULL)
    { printf("\n\nERROR: realloc failure in pickstack\a\n");
    return; }
    pickdata[0]=0;
  } 
}
void qspl()
{
  pickFlag=1;
  mode[0]='a';
  strcpy( pickfunc, "qspl");
  glutSetWindow( w1);
  glutKeyboardFunc ( pick );
  glutSetWindow( activWindow );
}



void moveNode(int n, int x, int y)
{
  GLint    viewport[4];
  GLdouble mvmatrix[16], projmatrix[16];

  static GLdouble wx, wy, wz;  /*  returned world x, y, z coords  */
  static GLdouble nx, ny, nz;  /*  new world x, y, z coords  */
  static double    nbuf[3];     /*  coordinate-buffer for undo */
  static int flag, nodnr=-1, nod_undo=-1, moveFlag=0;

  unsigned char buffer[MAX_LINE_LENGTH];

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
  moveModel();
  glGetIntegerv (GL_VIEWPORT, viewport);
  glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix);
  glGetDoublev (GL_PROJECTION_MATRIX, projmatrix);

  if (((n>-1)&&(nodnr==-1))||((n>-1)&&(moveFlag==1)))
  {
    /* mark node as one to be moved later and determine screen coordinates */
    nodnr=n;
    moveFlag=0;

    if(moveFlag==0)
    {
      nod_undo=n;
      nbuf[0]=node[n].nx;
      nbuf[1]=node[n].ny;
      nbuf[2]=node[n].nz;
    }
    flag=gluProject( node[n].nx, node[n].ny, node[n].nz, mvmatrix, projmatrix,
       viewport,  &wx, &wy, &wz);
    if (flag==GL_FALSE)
      printf("WARNING: Malfunction in moveNode(), please reselect\n");
    /* printf (" node:%d x=%lf y=%lf z=%lf \n", n, node[n].nx,node[n].ny,node[n].nz );
    printf (" Win coords are %d (%lf, %lf, %lf)\n",  flag,  wx   ,  wy   , wz     ); */
  }
  else if ((n==-1)&&(nodnr>-1))
  {
    /* move node to new location */

    /* remember that the point was moved, a new stroke of "p" will choose a new point to move */
    moveFlag=1;
    wx=(GLdouble)x; wy=(GLdouble)(viewport[3]-y);
    flag=gluUnProject ( wx, wy, wz, mvmatrix, projmatrix, viewport, &nx, &ny, &nz);
    /* printf ("World coords are %d (%lf, %lf, %lf)\n", flag, nx, ny, nz); */
    if (flag==GL_TRUE)
    {
      node[nodnr].nx=nx;
      node[nodnr].ny=ny;
      node[nodnr].nz=nz;
      updateDispLists();
    }
    else
      printf("WARNING: Malfunction in moveNode(), please reselect\n");
  }
  else if ((n>-1)&&(nodnr>-1))
  {
    /* replace the node nodnr by the actual node n */
    sprintf(buffer,"%d",nodnr);
    pre_seta( specialset->tmp, "n", buffer);
    sprintf(buffer,"%d",n);
    pre_seta( specialset->tmp, "n", buffer);
    sprintf(buffer,"n %s %lf nolock",specialset->tmp,MAX_FLOAT);
    pre_merge(buffer);
    nodnr=-1;
  }
  else if ((n<-1)&&(nod_undo>-1))
  {
    /* undo */
    node[nod_undo].nx=nbuf[0];
    node[nod_undo].ny=nbuf[1];
    node[nod_undo].nz=nbuf[2];
    updateDispLists();
    nodnr=nod_undo=-1;
  }
}



void movePoint(int p, int x, int y)
{
  int i,j;
  GLint    viewport[4];
  GLdouble mvmatrix[16], projmatrix[16];
  
  static GLdouble wx, wy, wz;  /*  returned world x, y, z coords  */
  static GLdouble nx, ny, nz;  /*  new world x, y, z coords  */
  static double    pbuf[3];     /*  coordinate-buffer for undo */
  static int flag, pntnr=-1, pnt_undo=-1, moveFlag=0;
  
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
  moveModel();
  glGetIntegerv (GL_VIEWPORT, viewport);
  glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix);
  glGetDoublev (GL_PROJECTION_MATRIX, projmatrix);

  /* undo */
  if ((p==-2)&&(pnt_undo>-1))
  {
    pntnr=pnt_undo;
    /* pnt_undo=-1; */
    point[pntnr].px=pbuf[0];
    point[pntnr].py=pbuf[1];
    point[pntnr].pz=pbuf[2];
    /* correct the affected lines */
    for (i=0; i<anzGeo->l; i++)
    {
      if(line[i].typ=='a')
      {
        if((line[i].p1==pntnr)||(line[i].p2==pntnr)||(line[i].trk==pntnr)) rep(i);
      }
      else if(line[i].typ=='s')
      {
        for (j=0; j<set[line[i].trk].anz_p; j++)
        {
          if(set[line[i].trk].pnt[j]==pntnr) rep(i);
        }
      }
      else
      {
        if((line[i].p1==pntnr)||(line[i].p2==pntnr)) rep(i);
      }
    }
    pntnr=pnt_undo=-1;
  }
  else if (surfNr>-1)
  {
    /* project p to surf */
    projPntsToNurbs(nurbs,surf[surfNr].sh,set,setNrbuf,point);
    
    /* correct the shape of the lines */
    for (i=0; i<anzGeo->l; i++)
    {
      rep(i); 
    }
  }
  else if (((p>-1)&&(pntnr==-1))||((p>-1)&&(moveFlag==1)))
  {
    /* mark this point as one to be moved later and determine screen coordinates */  
    pntnr=pnt_undo=p;
    moveFlag=0;

    pbuf[0]=point[p].px;
    pbuf[1]=point[p].py;
    pbuf[2]=point[p].pz;
    
    /* necessary for plotting the moved point */
    flag=gluProject( point[p].px, point[p].py, point[p].pz, mvmatrix, projmatrix,
       viewport,  &wx, &wy, &wz);
    if (flag==GL_FALSE)
      printf("WARNING: Malfunction in movePoint(), please reselect\n");
    
    /* printf (" pnt:%d x=%lf y=%lf z=%lf \n", n, point[p].px, point[p].py, point[p].pz );
    printf (" Win coords are %d (%lf, %lf, %lf)\n",  flag,  wx   ,  wy   , wz     ); */
  }
  else if ((p==-1)&&(pntnr>-1))
  {
    /* move the point to the window-coordinates */

    /* remember that the point was moved, a new stroke of "p" will choose a new point to move */
    moveFlag=1;
    wx=(GLdouble)x; wy=(GLdouble)(viewport[3]-y);
    flag=gluUnProject ( wx, wy, wz, mvmatrix, projmatrix, viewport, &nx, &ny, &nz);
    /* printf ("new World coords are %d (%lf, %lf, %lf)\n", flag, nx, ny, nz); */
    if (flag==GL_TRUE)
    {
      point[pntnr].px=nx;
      point[pntnr].py=ny;
      point[pntnr].pz=nz;
      /* correct the shape of the connected lines */
      for (i=0; i<anzGeo->l; i++)
      {
        if(line[i].typ=='a')
        {
          if((line[i].p1==pntnr)||(line[i].p2==pntnr)||(line[i].trk==pntnr)) rep(i);
        }
        else if(line[i].typ=='s')
        {
          for (j=0; j<set[line[i].trk].anz_p; j++)
          {
            if(set[line[i].trk].pnt[j]==pntnr)
            {
              rep(i);
              break;
            }
          }
        }
        else
        {
          if((line[i].p1==pntnr)||(line[i].p2==pntnr)) rep(i);
        }
      }
    }
    else
      printf("WARNING: Malfunction in movePoint(), please reselect\n");
  }
  else if ((p>-1)&&(pntnr>-1))
  {
    /* move the point pntnr to the actual point p */

    point[pntnr].px=point[p].px;
    point[pntnr].py=point[p].py;
    point[pntnr].pz=point[p].pz;
    /* correct the shape of the connected lines */
    for (i=0; i<anzGeo->l; i++)
    {
      if(line[i].typ=='a')
      {
        if((line[i].p1==pntnr)||(line[i].p2==pntnr)||(line[i].trk==pntnr)) rep(i);
      }
      else if(line[i].typ=='s')
      {
        for (j=0; j<set[line[i].trk].anz_p; j++)
        {
          if(set[line[i].trk].pnt[j]==pntnr)
          {
            rep(i);
            break;
          }
        }
      }
      else
      {
        if((line[i].p1==pntnr)||(line[i].p2==pntnr)) rep(i);
      } 
    }
    pntnr=-1;
  }
}



int createElem(int n)
{
  static int nodes[26];
  static int nr;

  if(n>-1)
  {
    nodes[nr++]=n;
  }
  else if(n==-1)
  {
    printf(" create shell element:%d\n",anz->emax+1 );
    if     (nr==3) elem_define( anz->emax+1, 7, nodes, 1, 0 );
    else if(nr==4) elem_define( anz->emax+1, 9, nodes, 1, 0 );
    else if(nr==6) elem_define( anz->emax+1, 8, nodes, 1, 0 );
    else if(nr==8) elem_define( anz->emax+1, 10, nodes, 1, 0 );
    else
    {
      printf(" Warning, wrong number of nodes:%d, no element created, start again\n",nr);
      nr=0;
      return(-1);
    }
    nr=0;
    return(anz->emax);
  }
  else if(n==-2)
  {
    printf(" create volume element:%d\n",anz->emax+1);
    if     (nr==8)  elem_define( anz->emax+1, 1, nodes, 1, 0 );
    else if(nr==20) elem_define( anz->emax+1, 4, nodes, 1, 0 );
    else
    {
      printf(" Warning, wrong number of nodes:%d, no element created, start again\n",nr);
      nr=0;
      return(-1);
    }
    nr=0;
    return(anz->emax);
  }
  return(-1);
     
}



int createPoint( int x, int y )
{
  /* new point is located in an area parallel to the screen and running through centerPnt */
  unsigned char     name[MAX_LINE_LENGTH];
  int      nr=-1;
  GLint    viewport[4];
  GLdouble mvmatrix[16], projmatrix[16];
  
  static GLdouble wx, wy, wz;  /*  returned world x, y, z coords  */
  static GLdouble nx, ny, nz;  /*  new world x, y, z coords  */
  static int flag;

  printf("createPoint\n");

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
  moveModel();
  glGetIntegerv (GL_VIEWPORT, viewport);
  glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix);
  glGetDoublev (GL_PROJECTION_MATRIX, projmatrix);
  
  flag=gluProject( centerPnt[0], centerPnt[1], centerPnt[2], mvmatrix, projmatrix,
     viewport,  &wx, &wy, &wz);
  if (flag==GL_FALSE)
    printf("WARNING: Malfunction in createPoint(), please reselect\n");
  /* printf (" pnt:%d x=%lf y=%lf z=%lf \n", n, point[p].px, point[p].py, point[p].pz );
  printf (" Win coords are %d (%lf, %lf, %lf)\n",  flag,  wx   ,  wy   , wz     ); */
  
  
  wx=(GLdouble)x; wy=(GLdouble)(viewport[3]-y);
  flag=gluUnProject ( wx, wy, wz, mvmatrix, projmatrix, viewport, &nx, &ny, &nz);
  /* printf ("new World coords are %d (%lf, %lf, %lf)\n", flag, nx, ny, nz); */
  if (flag==GL_TRUE)
  {
    if(pntNr==-1) getNewName( name, "p" );
    else { strcpy(name,point[pntNr].name); pntNr=-1; }
    printf(" create point:%s %lf %lf %lf\n", name, nx, ny, nz );
    nr  = pnt( name, nx, ny, nz, 0);
  }
  else
    printf("WARNING: Malfunction in createPoint(), please reselect\n");
  
  updateDispLists();
  return(nr);
}


int createLine( unsigned char *apnt, int flag )
{
  int i,j=0, nr=-1;
  static int p1, p2, pc=-1, pm=-1, ps[1000], seq=1;
  double P1[3], P2[3], Pc[3], Pm[3], pbuf[3], u;
  unsigned char name[MAX_LINE_LENGTH], setname[MAX_LINE_LENGTH];
  double pmp1[3], pmp2[3], pmp1_2[3], pmp2_2[3], nm12[3];
  double eva[3], evb[3], va[3], vb[3], p0p1_2[3], p0p2_2[3], vr[3];

  if (flag==0) p1  = getPntNr( apnt );
  else if (flag==1)
  {
    p2  = getPntNr( apnt );
    if (p1!=p2)
    {
      if (pc>-1)
      {
        P1[0]=point[p1].px;
        P1[1]=point[p1].py;
        P1[2]=point[p1].pz;
        Pc[0]=point[pc].px;
        Pc[1]=point[pc].py;
        Pc[2]=point[pc].pz;
        /* radius berechnen */
        v_result(Pc, P1, vr);        
        printf(" R:%lf\n", v_betrag(vr)*scale->w);

        if(lineNr==-1) getNewName( name, "l" );
        else { strcpy(name,line[lineNr].name); lineNr=-1; }
        printf(" create line:%s %s %s %s %d\n", name, point[p1].name, point[p2].name, point[pc].name, ddiv );
        nr= line_i( name, p1, p2, pc, ddiv, 1, 'a' );
        pc=-1;
      }
      else if (pm>-1)
      {
        P1[0]=point[p1].px;
        P1[1]=point[p1].py;
        P1[2]=point[p1].pz;
        P2[0]=point[p2].px;
        P2[1]=point[p2].py;
        P2[2]=point[p2].pz;
        Pm[0]=point[pm].px;
        Pm[1]=point[pm].py;
        Pm[2]=point[pm].pz;
    
        /* vprod nm12 = pmp1 x pmp2 */
        v_result( Pm, P1, pmp1 );
        v_result( Pm, P2, pmp2 );
        v_prod( pmp1, pmp2, nm12 );
    
        /* Vector halfway between pm and p1 or p2 */
        u=0.5;
        v_scal( &u, pmp1, pmp1_2);
        v_scal( &u, pmp2, pmp2_2);
        v_add( Pm, pmp1_2, p0p1_2); 
        v_add( Pm, pmp2_2, p0p2_2); 


        /* Vector in direction to PC, vprod va = nm12 x pmp1 and vb =  pmp2 x nm12 */
        v_prod( nm12, pmp1, va );
        v_prod( pmp2, nm12, vb );
        v_norm( va, eva );
        v_norm( vb, evb );
    
        /* determine abs-max-component of nm12 */
        u=0.;
        for (i=0; i<3; i++) if (nm12[i]*nm12[i]>u) { u=nm12[i]*nm12[i]; j=i; }

        /* calculation of the intersection between eva and evb */
        if (j==0)
	{
          u=(p0p2_2[1]-p0p1_2[1]-eva[1]*(p0p2_2[2]-p0p1_2[2])/eva[2])
           /(eva[1]*evb[2]/eva[2] - evb[1]);
        }
        else if (j==1)
	{
          u=(p0p2_2[0]-p0p1_2[0]-eva[0]*(p0p2_2[2]-p0p1_2[2])/eva[2])
           /(eva[0]*evb[2]/eva[2] - evb[0]);
        }
        else if (j==2)
	{
          u=(p0p2_2[0]-p0p1_2[0]-eva[0]*(p0p2_2[1]-p0p1_2[1])/eva[1])
           /(eva[0]*evb[1]/eva[1] - evb[0]);
        }
        else 
	{
          printf(" ERROR: in createLine, nm12 in error:%d\n", j);
          return(-1);
        }

        /*  centerpoint Pc = p0p2_2+ evb*u */
        v_scal( &u, evb, pbuf );
        v_add( pbuf, p0p2_2, Pc );

        /* radius berechnen */
        v_result(Pc, P1, vr);        
        printf(" R:%lf\n", v_betrag(vr)*scale->w);

	/*
        printf( "Pc:%lf %lf %lf\n", Pc[0], Pc[1], Pc[2] ); 
        printf(" P1:%s P2:%s PM:%s\n", point[p1].name, point[p2].name,  point[pm].name);
        printf(" u:%lf v:%lf\n", u*scale->w, v*scale->w);
        printf("nm12: %lf %lf %lf\n", nm12[0], nm12[1], nm12[2]);    
        printf("eva: %lf %lf %lf\n", eva[0], eva[1], eva[2]);    
        printf("evb: %lf %lf %lf\n", evb[0], evb[1], evb[2]);    
	*/


        /* centerpoint anlegen pc */
        getNewName( name, "p" );
        printf(" create point:%s %lf %lf %lf\n", name, Pc[0], Pc[1], Pc[2] );
        pc= pnt( name, Pc[0], Pc[1], Pc[2], 0 );

        /* kreisbogen definieren */
        if(lineNr==-1) getNewName( name, "l" );
        else { strcpy(name,line[lineNr].name); lineNr=-1; }
        printf(" create line:%s %s %s %s %d\n" , name, point[p1].name, point[p2].name, point[pc].name, ddiv  );
        nr= line_i( name, p1, p2, pc, ddiv, 1, 'a' );

        pc=-1;
        pm=-1;
      }
      else if (seq>1)
      {
        getNewName( setname, "se" );
        ps[0]=p1;
        ps[seq]=p2;
        for (i=0; i<=seq; i++)
	{
          pre_seta( setname, "ps", point[ps[i]].name);
        }
        nr=getSetNr( setname); 
        /* set[nr].type=1; */
        if(lineNr==-1) getNewName( name, "l" );
        else { strcpy(name,line[lineNr].name); lineNr=-1; }
        printf(" create line:%s %s %s %s %d\n"
        , name, point[p1].name, point[p2].name, setname, ddiv );
        nr= line_i( name, p1, p2, nr, ddiv, 1, 's' );
	seq=1;
      }
      else
      {
        if(lineNr==-1) getNewName( name, "l" );
        else { strcpy(name,line[lineNr].name); lineNr=-1; }
        printf(" create line:%s %s %s %d\n", name, point[p1].name, point[p2].name, ddiv );
        nr= line_i( name, p1, p2, 0, ddiv, 1, 0 );
      }
      p1=p2;
      }
    else printf(" p1==p2, try again\a\n");
    }
  else if (flag==2) /* center point defined */
    {
    pc  = getPntNr( apnt );
    }
  else if (flag==3) /* mit-point defined, create a centerpoint */
    {
    pm  = getPntNr( apnt );
    }
  else if (flag==4) /* seq-point defined, create a set */
    {
    ps[seq]  = getPntNr( apnt );
    if (seq<1000) seq++;
    }
  return (nr);
}

/* makes a seqence-line from an arc or straight line */
void convertLine( int l, int div )
{
  int k, p, setNr;
  double pn[3];
  unsigned char name[MAX_LINE_LENGTH];

  /* define a sequence */
  if( getNewName( name, "se" ) == -1 ) 
  {
    printf("ERROR: point could not be created\n");
    return;
  }
  if( (setNr=pre_seta( name, "i", 0)) <0 ) return;
  set[setNr].type=1;
  seta( setNr, "p", line[l].p1 ); 

  /* create spline points */
  /* and define a sequence */
  for (k=0; k<div; k++)
  {
    if (line[l].typ=='a') arcNodes( l, k, div+1, pn );
    else if (line[l].typ=='n') nurlNodes( l, k, div+1, pn );
    else if (line[l].typ=='s') splineNodes( l, k, div+1, pn );
    else straightNodes( l, k, div+1, pn );
    if( getNewName( name, "p" ) == -1 ) 
    {
      printf("ERROR: point could not be created\n");
      return;
    }
    if(printFlag) printf (" pnt=%s x=%lf y=%lf z=%lf\n",  name, pn[0], pn[1], pn[2]);
    p=pnt( name, pn[0], pn[1], pn[2], 0 );
    if( p<0) printf("ERROR: point could not be created\n");
    seta( setNr, "p", p ); 
  }
  seta( setNr, "p", line[l].p2 );
  line_i( line[l].name, line[l].p1, line[l].p2, setNr, line[l].div, 1, 's' );
  return;
}

#include <math.h>



double AsplitL_l( double *b, double *eu, double *ev, double *eg )
/******************************************************************/
/*   Grade (eg) schneidet Ebene (eu,ev) return g                  */
/*   determinante dritter Ordnung                                 */
/*   b= Abstand zwischen den Aufpunkten der Linie und Ebene       */
/*   b=eu*u + ev*v + eg *g  (e: Einheitsvektoren )                */
/******************************************************************/
{
  double g, D, Dg, a, c;

  a = eu[0]*ev[1]*eg[2]+ ev[0]*eg[1]*eu[2]+ eg[0]*eu[1]*ev[2];
  c = eg[0]*ev[1]*eu[2]+ eu[0]*eg[1]*ev[2]+ ev[0]*eu[1]*eg[2];
  D = a-c;

  a = eu[0]*ev[1]* b[2]+ ev[0]* b[1]*eu[2]+  b[0]*eu[1]*ev[2];
  c =  b[0]*ev[1]*eu[2]+ eu[0]* b[1]*ev[2]+ ev[0]*eu[1]* b[2];
  Dg= a-c;
  g = Dg / D;
  return (g);
}




#define DS 10000
#define MIN_SPROD 1.e30
int splitLine( int l, int x, int y )
{
  int i,j,k,n;
  double p0[3], p1[3], p01[3], pm0[3], pm1[3], pm01[3], pm02[3], p0pm0[3], ps[3], p0ps[3];
  double eu[3], ev[3], en[3], eg[3], g;
  int   p1_nr, p2_nr, ps_nr, l_nr[2], setNr, setNr0, setNr1, line_bias;
  unsigned char name[MAX_LINE_LENGTH], trk[2][MAX_LINE_LENGTH];
  unsigned char linbuf[MAX_LINE_LENGTH];
  double sprod_pk[DS], ek[2][3], pm00[3], pm0k[3];
  double pk[2][3], lbez, ps_lbez=0, div;
  double min_sprod, sprod_euek;

  double pbuf[3];
  static double *pset_dl=NULL;

  GLint    viewport[4];
  GLdouble mvmatrix[16], projmatrix[16];

  static GLdouble wx, wy, wz;  /*  returned world x, y, z coords  */
  static GLdouble nx, ny, nz;  /*  new world x, y, z coords  */
  static int flag;


  /* erzeugen von zwei Raumpunkten auf dem Mauspeilstrahl (MausPos.-Z-Richtung) */

  /* first create a temporary point in window-z direction at cursor-x,y pos.  */
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
  moveModel();
  glGetIntegerv (GL_VIEWPORT, viewport);
  glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix);
  glGetDoublev (GL_PROJECTION_MATRIX, projmatrix);

  flag=gluProject( centerPnt[0], centerPnt[1], centerPnt[2], mvmatrix, projmatrix,
     viewport,  &wx, &wy, &wz);
  if (flag==GL_FALSE)
  {
    printf(" ERROR: Malfunction in splitLine(), please reselect\n");
    return(-1);
  }
  /* printf (" Win coords are %d (%lf, %lf, %lf)\n",  flag,  wx   ,  wy   , wz     ); */
  
  wx=(GLdouble)x; wy=(GLdouble)(viewport[3]-y);
  flag=gluUnProject ( wx, wy, wz, mvmatrix, projmatrix, viewport, &nx, &ny, &nz);
  /* printf ("new World coords are %d (%lf, %lf, %lf)\n", flag, nx, ny, nz); */
  if (flag==GL_TRUE)
  {
    pm0[0]=nx;
    pm0[1]=ny;
    pm0[2]=nz;
  }
  else
  {
    printf(" ERROR: Malfunction in splitLine(), please reselect\n");
    return(-1);
  }
  
  wz++;
  flag=gluUnProject ( wx, wy, wz, mvmatrix, projmatrix, viewport, &nx, &ny, &nz);
  /* printf ("new World coords are %d (%lf, %lf, %lf)\n", flag, nx, ny, nz); */
  if (flag==GL_TRUE)
  {
    pm1[0]=nx;
    pm1[1]=ny;
    pm1[2]=nz;
  }
  else
  {
    printf(" ERROR: Malfunction in splitLine(), please reselect\n");
    return(-1);
  }

  /* split the first line (l) */ 

  /* berechne den ersten Einheitsvektor der Schnittebene, eu==Peilstrahlrichtung */
  v_result( pm0, pm1, pm01 );
  v_norm( pm01, eu );

  /* bestimme die Koordinaten der Linienendpunkte */
  p1_nr= line[l].p1;
  p0[0] = point[p1_nr].px;
  p0[1] = point[p1_nr].py;
  p0[2] = point[p1_nr].pz;
  p2_nr= line[l].p2;
  p1[0] = point[p2_nr].px;
  p1[1] = point[p2_nr].py;
  p1[2] = point[p2_nr].pz;
  /*
  printf("endpnt P1:%s %lf %lf %lf\n", point[line[l].p1].name, p0[0],p0[1],p0[2]);
  printf("endpnt P2:%s %lf %lf %lf\n", point[line[l].p2].name, p1[0],p1[1],p1[2]);
  */

  /* berechne den schnittpunkt der zu splittenden linie mit der ebene a(eu,ev) */
  if( line[l].typ==' ')
  {
    /* berechne den zweiten Einheitsvektor der Schnittebene, ev==Peilstrahl x Linie */
    v_result( p0, p1, p01 );
    v_prod( pm01, p01, pm02 );
    v_norm( pm02, ev );

    /* berechne den Normalenvektor der Schnittebene */
    v_prod( eu, ev, en );

    /* berechne den Einheitsvektor der zu splitenden Linie */
    v_norm( p01, eg );

    /* bestimme den Abstand zwischen den Aufpunkten der Linie und Ebene  */
    v_result( p0, pm0, p0pm0 );

    /* berechne die Konstante g zur berechnung von ps (Schnittpunkt) ps=p0+eg*g  */
    g = AsplitL_l( p0pm0, eu, ev, eg );

    v_scal( &g, eg, p0ps );
    v_add( p0, p0ps, ps );
    strcpy(trk[0], " ");
    strcpy(trk[1], " ");

    /* erzeuge den Punkt */
    n= getNewName( name, "p" );
    printf(" create point:%s %lf %lf %lf\n", name, ps[0], ps[1], ps[2] );
    ps_nr  = pnt( name, ps[0], ps[1], ps[2], 0 );
  }
  else
  {
    /* Zerlege die linie in DS Teile und bestimme die durchtritte durch die Ebene */
    /* ein Durchtritt erfolgt, wenn das vorzeichen des skalarproduckts sich aendert */
    /* speichere den linienpunkt vor und hinter dem durchtritt fuer die spaetere */
    /* interpolation. Bestimme das dem peilstrahl am naechsten liegende punktepaar */
    /* das naechstliegende punktepaar ist das mit dem kleinsten skalarprodukt */

    /* berechne den Einheitsvektor zum 1. kontrollpunkt */
    pk[0][0]= p0[0];
    pk[0][1]= p0[1];
    pk[0][2]= p0[2];
    v_result( pm1, pk[0], pm00 );
    v_norm( pm00, ek[0] );

    flag=0;
    min_sprod=MIN_SPROD;

    /* set the line-bias to 1 for the search of the split-point */
    /* reset it after this operation to the original one */
    line_bias=line[l].bias;
    line[l].bias=1;
    for (k=0; k<DS; k++)
    {
      if (line[l].typ=='a')
      {
        if(arcNodes( l, k,(int) DS, pbuf )==-1)      { printf("ERROR in spliting\n"); }
      }
      else if (line[l].typ=='s')
      {
        if(splineNodes( l, k,(int) DS, pbuf )==-1)   { printf("ERROR in spliting\n"); }
      }
      pk[1][0]= pbuf[0];
      pk[1][1]= pbuf[1];
      pk[1][2]= pbuf[2];
      

      /* die richtung der schnittebene wird fuer jeden kontrollpunkt neu berechnet */
      /* berechne den zweiten Einheitsvektor der Schnittebene */
      v_result( pk[0], pk[1], p01 );
      v_prod( pm01, p01, pm02 );
      v_norm( pm02, ev );

      /* berechne den Normalenvektor der Schnittebene */
      v_prod( eu, ev, en );

      /* winkel zum ersten kontrollpunkt */
      sprod_pk[0]=v_sprod( en, ek[0]);

      /* berechne den Einheitsvektor zu diesem kontrollpunkt */
      v_result( pm1, pk[1], pm0k );
      v_norm( pm0k, ek[1] );
      sprod_pk[1]=v_sprod( en, ek[1]);

      /* haben wir einen durchstosspunkt? (vorzeichenwechsel von sprod)  */
      if( (sprod_pk[0]*sprod_pk[1]) <=0. )
      {
        flag=1;
        /* durchstoss gefunden, ist er der bisher naechstliegende? */
        sprod_euek=v_sprod( eu, ek[0])+v_sprod( eu, ek[1]);
	/*
        printf("sprod_euek:%lf min_sprod:%lf k:%d DS:%d\n", sprod_euek, min_sprod,k,DS); 
        printf(" pnt0:%lf %lf %lf sprod_pn:%lf\n", pk[0][0], pk[0][1], pk[0][2], sprod_pk[0]);
        printf(" pnt1:%lf %lf %lf sprod_pn:%lf\n", pk[1][0], pk[1][1], pk[1][2], sprod_pk[1]);
	*/
	
        if( sprod_euek<min_sprod )
        {
          min_sprod=sprod_euek;
          p0[0] =pk[0][0] ;
          p0[1] =pk[0][1] ;
          p0[2] =pk[0][2] ;
          p1[0] =pk[1][0] ;
          p1[1] =pk[1][1] ;
          p1[2] =pk[1][2] ;
          ps_lbez=(double)k/(double)DS;           /* position, bezogene linienlaenge */
          /*
          printf(" min_sprod:%lf ps_lbez:%lf \n", min_sprod, ps_lbez );
          */
	}
      }
      pk[0][0]=pk[1][0] ;
      pk[0][1]=pk[1][1] ;
      pk[0][2]=pk[1][2] ;
      ek[0][0]=ek[1][0] ;
      ek[0][1]=ek[1][1] ;
      ek[0][2]=ek[1][2] ;
      
      
    }
    /* reset the line-bias */
    line[l].bias=line_bias;
    
    /* uebernehme einen der durchstoss-punkte als splitpunkt */
    if(flag)
    {  
      ps[0]=p0[0];
      ps[1]=p0[1];
      ps[2]=p0[2];
    }
    else
    {
      printf(" ERROR: Malfunction in splitLine(), please reselect\a\n");
      return(-1);
    }

    /* erzeuge den splitpunkt */
    getNewName( name, "p" );
    printf(" create point:%s %lf %lf %lf\n", name, ps[0], ps[1], ps[2] );
    ps_nr  = pnt( name, (double)ps[0], (double)ps[1], (double)ps[2], 0 );

    /* erzeuge den trk der neuen linien */
    if (line[l].typ=='a')
    {
      strcpy( trk[0], point[line[l].trk].name );
      strcpy( trk[1], point[line[l].trk].name );
    }
    else if (line[l].typ=='s')
    {
      /* suche alle punkte des trk die vor dem schnittpunkt liegen und ordne sie einem */
      /* neuen set zu und loesche sie aus dem bestehenden trk */

      /* erzeuge zwei neue sets fuer die stuetzpunkte der zwei neuen linien */
      getNewName( trk[0], "se" );
      setNr0=pre_seta( trk[0], "is", 0);

      getNewName( trk[1], "se" );
      setNr1=pre_seta( trk[1], "is", 0);

      /* determine the length of the spline, accumulate all dists between points */
      /* look if the sequence is ordered in the same way as the line */
      setNr=line[l].trk;
      lbez=0.;
     
      if ( ( pset_dl= (double *)realloc( (double *)pset_dl, (set[setNr].anz_p+1) * sizeof(double))) == NULL )
        printf("ERROR: realloc failed: splitLine\n\n" ); 
      pset_dl[0]=pset_dl[set[setNr].anz_p-1]=0.;
      if( line[l].p1==set[setNr].pnt[0] )
      {
        p0[0]=point[set[setNr].pnt[0]].px;
        p0[1]=point[set[setNr].pnt[0]].py;
        p0[2]=point[set[setNr].pnt[0]].pz;   
        for (i=1; i<set[setNr].anz_p; i++)
        {
          p1[0]=point[set[setNr].pnt[i]].px;
          p1[1]=point[set[setNr].pnt[i]].py;
          p1[2]=point[set[setNr].pnt[i]].pz;
          v_result( p0, p1, p01  );
          p0[0]=p1[0];
          p0[1]=p1[1];
          p0[2]=p1[2];
          lbez+=v_betrag( p01  );
          pset_dl[i]=lbez;
        }
      }
      else
      {
        p0[0]=point[set[setNr].pnt[set[setNr].anz_p-1]].px;
        p0[1]=point[set[setNr].pnt[set[setNr].anz_p-1]].py;
        p0[2]=point[set[setNr].pnt[set[setNr].anz_p-1]].pz;   
        for (i=1; i<set[setNr].anz_p; i++)
        {
          p1[0]=point[set[setNr].pnt[set[setNr].anz_p-1-i]].px;
          p1[1]=point[set[setNr].pnt[set[setNr].anz_p-1-i]].py;
          p1[2]=point[set[setNr].pnt[set[setNr].anz_p-1-i]].pz;
          v_result( p0, p1, p01  );
          p0[0]=p1[0];
          p0[1]=p1[1];
          p0[2]=p1[2];
          lbez+=v_betrag( p01  );
          pset_dl[set[setNr].anz_p-1-i]=lbez;
        }
      }
      ps_lbez*=lbez;

      k=0;
      if( line[l].p1==set[setNr].pnt[0] )
      {
        for (i=0; i<set[setNr].anz_p; i++)
        { 
          /* printf("+ dl:%lf ls:%lf p:%s\n", pset_dl[i], ps_lbez, point[set[setNr].pnt[i]].name);*/
          if(pset_dl[i]<ps_lbez) seta( setNr0, "ps", set[setNr].pnt[i] );
          else
          {
            if(!k){
              seta( setNr0, "ps", ps_nr ); 
              seta( setNr1, "ps", ps_nr ); k++; } 
            seta( setNr1, "ps", set[setNr].pnt[i] );
          }
        }
      }
      else
      {
        for (i=set[setNr].anz_p-1; i>=0; i--)
        { 
          /* printf("- dl:%lf ls:%lf p:%s\n", pset_dl[i], ps_lbez, point[set[setNr].pnt[i]].name);*/
          if(pset_dl[i]<ps_lbez) seta( setNr0, "ps", set[setNr].pnt[i] );
          else
          {
            if(!k){
              seta( setNr0, "ps", ps_nr ); 
              seta( setNr1, "ps", ps_nr ); k++; } 
            seta( setNr1, "ps", set[setNr].pnt[i] );
          }
        }
      }
    }
    else
    {
      strcpy(trk[0], " ");
      strcpy(trk[1], " ");
    }
  }

  /* sichere den liniennamen bevor der pointer durch realloc in line_ geaendert wird  */
  strcpy( linbuf, line[l].name);

  /* erzeuge zwei neue linien  */
  if (line[l].div>1) div=line[l].div/2; else div=1;
  n= getNewName( name, "l" );
  if ( n == -1 )
   { printf(" createLine: Type %s not known\n", "l"); exit(-1); }
  else printf(" create line:%s %s %s %s %lf\n", name, point[p1_nr].name, point[ps_nr].name, trk[0], div );
  line_( name, point[p1_nr].name, point[ps_nr].name, trk[0], div, 1 );
  l_nr[0]=getLineNr(name);

  if (line[l].div>1) div=line[l].div-div; else div=1;
  n= getNewName( name, "l" );
  if ( n == -1 )
   { printf("createLine: Type %s not known\n", "l"); exit(-1); }
  else printf(" create line:%s %s %s %s %lf\n", name, point[ps_nr].name, point[p2_nr].name, trk[1], div );
  line_( name, point[ps_nr].name, point[p2_nr].name, trk[1], div, 1 );
  l_nr[1]=getLineNr(name);

  /* untersuche alle lcmbs ob linbuf ein Mitglied ist */
  for (i=0; i<anzGeo->c; i++)
  {
    for (j=0; j<lcmb[i].nl; j++)
    {
      if( l == lcmb[i].l[j] )
      {
         printf (" realloc lcmb:%s and replace line:%s with %s and %s \n",
           lcmb[i].name, line[l].name,line[l_nr[0]].name, line[l_nr[1]].name );
        if ((lcmb[i].o = (unsigned char *)realloc( (unsigned char *)lcmb[i].o, (lcmb[i].nl+1)*sizeof(unsigned char)) ) == NULL )
        { printf("\n\n ERROR: realloc failure in qspl, lcmb.o:%s not changed\n\n",lcmb[i].name ); return(-1); }
        if ((lcmb[i].l = (int *)realloc( (int *)lcmb[i].l, (lcmb[i].nl+1)*sizeof(int)) ) == NULL )
        { printf("\n\n ERROR: realloc failure in qspl, lcmb.l:%s not changed\n\n", lcmb[i].name); return(-1); }
	/* umspeichern der linien beginnend bei der letzten bis einschlieslich j */
        for (n=lcmb[i].nl; n>j; n--)
	{
          lcmb[i].o[n]=lcmb[i].o[n-1];
          lcmb[i].l[n]=lcmb[i].l[n-1];
        }
        /* Auffuellen der j, j+1 pos. mit l1, l2 mit der Orientierung der gesplitteten linie */
        lcmb[i].o[j]=lcmb[i].o[j+1];
        lcmb[i].l[j]=l_nr[0];
        lcmb[i].o[j+1]=lcmb[i].o[j];
        lcmb[i].l[j+1]=l_nr[1];
        lcmb[i].nl++;
      }
    }
  }

  /* untersuche alle surfs ob linbuf ein Mitglied ist und ersetze sie durch eine lcmb */
  /* kontrolliere ob nicht schon eine geeignete lcmb existiert */
  for (i=0; i<anzGeo->s; i++)
  {
    for (j=0; j<surf[i].nl; j++)
    {
      if(( l == surf[i].l[j] )&&( surf[i].typ[j]=='l' ))
      {

        /* do we already have a suitable lcmb? */
        for (n=0; n<anzGeo->c; n++ )
	{
          if (lcmb[n].nl==2)   /* same amount of lines */
	  {
	    /*
            printf ("checke lcmb:%s \n", lcmb[n].name);
	    */
            if (((lcmb[n].l[0]==l_nr[0])||(lcmb[n].l[0]==l_nr[1])) && ((lcmb[n].l[1]==l_nr[0])||(lcmb[n].l[1]==l_nr[1])))
	    {
	      /*
              printf ("equal:%s\n",lcmb[n].name);
	      */
              break;
	    }
	  }
        }
        if (n>=anzGeo->c)  /* no lcmb was found, so create one */
        {
          /* create lcmb */
          if ( getNewName( name, "c" ) == -1 )
          { printf("Type c not known, lcmb can not be created\n"); exit(-1); }
          lcmb_i( name, (int)0, (int)2, "++", l_nr );
          n=getLcmbNr( name );
        }
        printf ("realloc surf:%s and replace line:%s with lcmb:%s made of %s and %s \n",
          surf[i].name, line[l].name, name, line[l_nr[0]].name, line[l_nr[1]].name );
        if (n>-1) { surf[i].l[j]=n; surf[i].o[j]='+'; surf[i].typ[j]='c'; }
        else { printf("lcmb not known, surface could not be changed \a\n"); return(-1); }
      }
    }
  }
  /* loesche basislinie */
  delLine( 1, &l );

  orientSet( "all" );
  updateDispLists();
  return(ps_nr);
}



void pre_align( int nr, int flag )
{
  static int count=0;
  static double p[3][3], p02[3], p01[3], p03[3], p03xz[3];
  double  ay, axz;
  double  p03_b, p03xz_b, scalar, sig;

  GLint    viewport[4];
  GLdouble mvmatrix[16], projmatrix[16];

  static GLdouble wx, wy, wz;  /*  returned world x, y, z coords  */
  static int flag2;

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity ();
  moveModel();
  glGetIntegerv (GL_VIEWPORT, viewport);
  glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix);
  glGetDoublev (GL_PROJECTION_MATRIX, projmatrix);

  if (flag)
  {
    flag2=gluProject( point[nr].px, point[nr].py, point[nr].pz, mvmatrix, projmatrix,
      viewport,  &wx, &wy, &wz);
    if (flag2==GL_FALSE)
      printf("WARNING: Malfunction in movePoint(), please reselect\n");
  }
  else
  {
    flag2=gluProject( node[nr].nx, node[nr].ny, node[nr].nz, mvmatrix, projmatrix,
      viewport,  &wx, &wy, &wz);
    if (flag2==GL_FALSE)
      printf("WARNING: Malfunction in movePoint(), please reselect\n");
  }

  p[count][0] = wx;
  p[count][1] = wy;
  p[count][2] = -wz*width_w1/ds*2.;     /* warum *2.? */
  count++;

  if (count == 1)
  {
    /* 1. Punkt gewaehlt == neuer Drehpunkt und neue Arbeitsebene */
  if (flag==0)
        center( node[nr].nx, node[nr].ny, node[nr].nz);
  if (flag==1)
        center( point[nr].px, point[nr].py, point[nr].pz);
  }
  if (count == 3)
  {
    count=0;
    /* 3 Punkte gewaehlt, berechne die Normale auf der Ebene */
    v_result( &p[0][0], &p[1][0],  p01);
    v_result( &p[0][0], &p[2][0],  p02);
    v_prod( p01, p02, p03 );

    /* Richtungsumkehr wenn die z-Komponente der Normalen nach hinten zeigt (-) */
    if (p03[2]<0)
    {
       p03[0]*=-1;
       p03[1]*=-1;
       p03[2]*=-1;
    }
    /* return wenn die ebene bereits zu der bildschirmebene paralel ist */
    if ((!p03[0])||(!p03[1])) return;

    /* drehe den Ort des Betrachters  */
    ay=atan(p03[0]/p03[2]);

    p03xz[0]=p03[0];
    p03xz[1]=0.;
    p03xz[2]=p03[2];
    scalar = v_sprod( p03xz, p03 );
    p03xz_b= v_betrag( p03xz );
    p03_b  = v_betrag( p03 );
    axz =acos( scalar/p03xz_b/p03_b ) * 180./pi;

    /* vorzeichen von der y-Komponente der Normalen wird zum vorzeichen von axz */
    scalar= sqrt(p03[1]*p03[1]);
    sig = p03[1]/scalar;
    axz = axz*sig;

    ay=ay*180./pi;

    rot_r( ay );
    rot_u( axz );
  }
}


double *createSplitPoint_( double *n1, double *n2, double *pn, double *eu, double *ev )
{
  static double ns[4];
  double eg[3], n1n2[3], n1pn[3], n1ns[3];
  double g;

  v_result( n1, n2, n1n2 );
  printf(" n1: %lf %lf %lf\n", n1[0], n1[1], n1[2] );
  printf(" n2: %lf %lf %lf\n", n2[0], n2[1], n2[2] );
  printf(" n1n2: %lf %lf %lf\n", n1n2[0], n1n2[1], n1n2[2] );

  /* berechne den Einheitsvektor der zu splitenden Linie */
  v_norm( n1n2, eg );
  printf(" eg: %lf %lf %lf\n", eg[0], eg[1], eg[2] );

  /* bestimme den Abstand zwischen den Aufpunkten der Linie und Ebene  */
  v_result( n1, pn, n1pn );
  printf(" n1pn: %lf %lf %lf\n", n1pn[0], n1pn[1], n1pn[2] );

  /* berechne die Konstante g zur berechnung von ps (Schnittpunkt) ps=p0+eg*g  */
  printf(" eu: %lf %lf %lf\n", eu[0], eu[1], eu[2] );
  printf(" ev: %lf %lf %lf\n", ev[0], ev[1], ev[2] );
  g = AsplitL_l( n1pn, eu, ev, eg );

  /* pos von ns bezogen auf |n1n2| */
  ns[3] = g/v_betrag(n1n2);

  v_scal( &g, eg, n1ns );
  v_add( n1, n1ns, ns );
  printf("  n1ns: %lf %lf %lf S:%lf l:%lf g:%lf dist:%lf\n", n1ns[0], n1ns[1], n1ns[2], v_sprod(n1ns,n1n2),v_betrag(n1n2),g, ns[3]);

  /* winkel zw n1ns und n1n2 bestimmen. wenn >0 dann ist ns zwischen n1 und n2 */
  if((double)((int)(g*1000)) < (g-1.)) return(NULL); 
  else if((v_sprod(n1ns,n1n2)>=0)&&((int)(g*1000)<=(int)(v_betrag(n1n2)*1000))) return(ns);
  else return(NULL);
}


double *createSplitPoint( double *n1, double *n2, double *pn, double *eu, double *ev )
{
  static double ns[4];
  double eg[3], n1n2[3], n1pn[3], n1ns[3];
  double g;

  v_result( n1, n2, n1n2 );

  /* berechne den Einheitsvektor der zu splitenden Linie */
  v_norm( n1n2, eg );

  /* bestimme den Abstand zwischen den Aufpunkten der Linie und Ebene  */
  v_result( n1, pn, n1pn );

  /* berechne die Konstante g zur berechnung von ps (Schnittpunkt) ps=p0+eg*g  */
  g = AsplitL_l( n1pn, eu, ev, eg );

  /* pos von ns bezogen auf |n1n2| */
  ns[3] = g/v_betrag(n1n2);

  v_scal( &g, eg, n1ns );
  v_add( n1, n1ns, ns );

  /* winkel zw n1ns und n1n2 bestimmen. wenn >0 dann ist ns zwischen n1 und n2 */
  if((double)((int)(g*1000)) < (g-1.)) return(NULL); 
  else if((v_sprod(n1ns,n1n2)>=0)&&((int)(g*1000)<=(int)(v_betrag(n1n2)*1000))) return(ns);
  else return(NULL);
}


void updLcase( int ns, int n1, int n2, double val )
{
  int i,l;

  for(l=0; l<anz->l; l++)
  {
    for(i=0; i<lcase[l].ncomps; i++)
    {
      if ( (lcase[l].dat[i] = (float *)realloc(lcase[l].dat[i], (ns+1) * sizeof(float))) == NULL )
        printf("\n\n ERROR: realloc failure\n\n" );	               
      lcase[l].dat[i][ns] = lcase[l].dat[i][n1]*(1.-val) + lcase[l].dat[i][n2]*val;
      /* printf("val:%lf n0:%lf n1:%lf n2:%lf\n", val, lcase[l].dat[i][ns], lcase[l].dat[i][n1],lcase[l].dat[i][n2]);   */
    }
  }
}


void pre_cut( int nr, int flag )
{
  static int count=0;
  int i,j,k,n1,n2,nn1,nn2, nset, nbuf;
  static double p[3][3];
  double v02[3], v01[3], vn[3], eu[3], ev[3], en[3], *ns, pn[3], cg[3], npre[1000][6];
  int  anz_n, nvalid[1000];
  Rsort *rsort=NULL;

  double local_gtol=1.e-9; /* dist to merge new nodes (might be set to gtol) */

  /* mapping of nodeindexes from frd to pre_cut */
  int nhe20[]  = {0,8,1,9,2,10,3,11,12,-1,13,-1,14,-1,15,-1,4,16,5,17,6,18,7,19};
  int ntet10[] = {0,4,1,5,2,6,7,-1,8,-1,9,-1,3};


  /* neuer Drehpunkt */
  if (flag==0)
  {
    center( node[nr].nx, node[nr].ny, node[nr].nz);
    p[count][0] = node[nr].nx;
    p[count][1] = node[nr].ny; 
    p[count][2] = node[nr].nz;
  }
  if (flag==1)
  {
    center( point[nr].px, point[nr].py, point[nr].pz);
    p[count][0] = point[nr].px;
    p[count][1] = point[nr].py; 
    p[count][2] = point[nr].pz;
  }
  count++;

  if (count == 3)
  {
    count=0;

    /* 3 Punkte gewaehlt, berechne die Normale auf der Ebene */
    v_result( &p[0][0], &p[1][0],  v01);
    v_result( &p[0][0], &p[2][0],  v02);
    v_prod( v01,v02, vn );
    v_norm( vn, en );

    /* punkt auf der ebene der nicht mit nodes identisch ist */
    for(i=0; i<3; i++) pn[i]=0.;
    for(i=0; i<3; i++)
    {
      pn[0]+= p[i][0];
      pn[1]+= p[i][1];
      pn[2]+= p[i][2];
    }
    for(i=0; i<3; i++) pn[i]/=3.;
    center( pn[0], pn[1], pn[2]);

    /* eu ev der ebene ausgehend von pn */
    v_result( pn, &p[1][0],  v01);
    v_prod( v01, vn, v02 );
    v_norm( v01, eu );
    v_norm( v02, ev );

    /* oeffne einen temp set */
    zap("-qcut");
    if( (nset=pre_seta( "-qcut", "i", 0)) <0 ) return;
    nbuf=0;

    /* schneide alle elemente mit der ebene */
    for(i=0; i<anz->e; i++)
    {
      anz_n=0;
      if (e_enqire[e_enqire[i].nr].type == 1)  /* HEXA8 */
      {
        for(n1=0; n1<4; n1++)
        {
          if(n1==3) n2=0;
          else n2=n1+1;
          ns=createSplitPoint( &node[e_enqire[e_enqire[i].nr].nod[n1]].nx, &node[e_enqire[e_enqire[i].nr].nod[n2]].nx, pn, eu, ev );
          if(ns>(double *)NULL)
          {
            npre[anz_n][0]=ns[0];
            npre[anz_n][1]=ns[1];
            npre[anz_n][2]=ns[2];
            npre[anz_n][3]=ns[3];
            npre[anz_n][4]=e_enqire[e_enqire[i].nr].nod[n1];
            npre[anz_n][5]=e_enqire[e_enqire[i].nr].nod[n2];
            nvalid[anz_n]=1;
            anz_n++;
          }
        }
        for(n1=0; n1<4; n1++)
        {
          n2=n1+4;
          ns=createSplitPoint( &node[e_enqire[e_enqire[i].nr].nod[n1]].nx, &node[e_enqire[e_enqire[i].nr].nod[n2]].nx, pn, eu, ev );
          if(ns>(double *)NULL)
          {
            npre[anz_n][0]=ns[0];
            npre[anz_n][1]=ns[1];
            npre[anz_n][2]=ns[2];
            npre[anz_n][3]=ns[3];
            npre[anz_n][4]=e_enqire[e_enqire[i].nr].nod[n1];
            npre[anz_n][5]=e_enqire[e_enqire[i].nr].nod[n2];
            nvalid[anz_n]=1;
            anz_n++;
          }
        }
        for(n1=4; n1<8; n1++)
        {
          if(n1==7) n2=4;
          else n2=n1+1;
          ns=createSplitPoint( &node[e_enqire[e_enqire[i].nr].nod[n1]].nx, &node[e_enqire[e_enqire[i].nr].nod[n2]].nx, pn, eu, ev );
          if(ns>(double *)NULL)
          {
            npre[anz_n][0]=ns[0];
            npre[anz_n][1]=ns[1];
            npre[anz_n][2]=ns[2];
            npre[anz_n][3]=ns[3];
            npre[anz_n][4]=e_enqire[e_enqire[i].nr].nod[n1];
            npre[anz_n][5]=e_enqire[e_enqire[i].nr].nod[n2];
            nvalid[anz_n]=1;
            anz_n++;
          }
        }
        if(anz_n>0)
        {
          /* aussortieren der doppelten nodes */
          for(j=0; j<anz_n; j++)
          {
            if(nvalid[j])
            {
              /* gehe ueber alle nodes und deaktiviere nahe nodes */
              for(k=j; k<anz_n; k++)
              {
               if(nvalid[k])
               {
                if(dabs(npre[j][0]-npre[k][0])>local_gtol) goto nexti; 
                if(dabs(npre[j][1]-npre[k][1])>local_gtol) goto nexti;
                if(dabs(npre[j][2]-npre[k][2])>local_gtol) goto nexti;
                nvalid[k]=0;
                nexti:;
               }
              }
              nod( anz, &node, 0, anz->nmax+1, npre[j][0], npre[j][1], npre[j][2], 0 );
              seta(0, "n", anz->nmax);
              seta(nset, "n", anz->nmax);
              updLcase( anz->nmax, npre[j][4], npre[j][5], npre[j][3] );
            }
          }
  
          /* sortiere die nodes nach winkel zum ersten node, masterrichtung ist en, center ist cg */
          anz_n=set[nset].anz_n-nbuf;
  
          cg[0]=0.;
          cg[1]=0.;
          cg[2]=0.;
          for(j=nbuf; j<set[nset].anz_n; j++)
          {
            cg[0]+=node[set[nset].node[j]].nx;
            cg[1]+=node[set[nset].node[j]].ny;
            cg[2]+=node[set[nset].node[j]].nz;
          }
          cg[0]/=anz_n;
          cg[1]/=anz_n;
          cg[2]/=anz_n;
  
          if ( (rsort = (Rsort *)malloc( (anz_n+1) * sizeof(Rsort))) == NULL )
            printf("ERROR: realloc failed: rsort\n\n" ); 
          v_result( cg, &node[set[nset].node[nbuf]].nx,  v01);
          rsort[0].r=0.;
          rsort[0].i=set[nset].node[nbuf];
          k=1;
          for(j=nbuf+1; j<set[nset].anz_n; j++)
          {
            v_result( cg, &node[set[nset].node[j]].nx,  v02);
            rsort[k].r=v_angle_ref(v01,v02,en);
            rsort[k].i=set[nset].node[j];
            k++;
          }
          qsort( rsort, anz_n, sizeof(Rsort), (void *)compareRsort );
          k=0;
          for(j=nbuf; j<set[nset].anz_n; j++)
          {
            set[nset].node[j]=rsort[k].i;
            k++;
          }
          free(rsort);
          
  
          /* generiere neue elemente */
          for(j=nbuf+1; j<set[nset].anz_n-1; j++)
          {
            nvalid[0]=set[nset].node[nbuf];
            nvalid[1]=set[nset].node[j];
            nvalid[2]=set[nset].node[j+1];
            elem_define( anz->emax+1, 7, nvalid, 0, 0 );
            seta(0, "e", anz->emax);
            seta(nset, "e", anz->emax);
          }
          nbuf=set[nset].anz_n;
        }
      } /* end he8 */

      if (e_enqire[e_enqire[i].nr].type == 3)  /* TET4 */
      {
        for(n1=0; n1<3; n1++)
        {
          if(n1==2) n2=0;
          else n2=n1+1;
          /* printf(" 1n: %d %d\n",e_enqire[e_enqire[i].nr].nod[n1],e_enqire[e_enqire[i].nr].nod[n2]); */
          ns=createSplitPoint( &node[e_enqire[e_enqire[i].nr].nod[n1]].nx, &node[e_enqire[e_enqire[i].nr].nod[n2]].nx, pn, eu, ev );
          if(ns>(double *)NULL)
          {
            npre[anz_n][0]=ns[0];
            npre[anz_n][1]=ns[1];
            npre[anz_n][2]=ns[2];
            npre[anz_n][3]=ns[3];
            npre[anz_n][4]=e_enqire[e_enqire[i].nr].nod[n1];
            npre[anz_n][5]=e_enqire[e_enqire[i].nr].nod[n2];
            nvalid[anz_n]=1;
            anz_n++;

            /* getNewName( name, "p" );
            pnt( name, ns[0], ns[1], ns[2], 0 );
            printf(" create point:%s %lf %lf %lf\n\n", name, ns[0], ns[1], ns[2] ); */
          }
        }
        for(n1=0; n1<3; n1++)
        {
          n2=3;
          /* printf(" 2n: %d %d\n",e_enqire[e_enqire[i].nr].nod[n1],e_enqire[e_enqire[i].nr].nod[n2]); */
          ns=createSplitPoint( &node[e_enqire[e_enqire[i].nr].nod[n1]].nx, &node[e_enqire[e_enqire[i].nr].nod[n2]].nx, pn, eu, ev );
          if(ns>(double *)NULL)
          {
            npre[anz_n][0]=ns[0];
            npre[anz_n][1]=ns[1];
            npre[anz_n][2]=ns[2];
            npre[anz_n][3]=ns[3];
            npre[anz_n][4]=e_enqire[e_enqire[i].nr].nod[n1];
            npre[anz_n][5]=e_enqire[e_enqire[i].nr].nod[n2];
            nvalid[anz_n]=1;
            anz_n++;
          }
        }
        if(anz_n>0)
        {
          /* aussortieren der doppelten nodes */
          for(j=0; j<anz_n; j++)
          {
            if(nvalid[j])
            {
              /* gehe ueber alle nodes und deaktiviere nahe nodes */
              for(k=j; k<anz_n; k++)
              {
               if(nvalid[k])
               {
                /* printf("check node:%d %d gtol:%le\n", j, k, local_gtol );
                   printf("d:%le %le %le\n",(npre[j][0]-npre[k][0]),(npre[j][1]-npre[k][1]),(npre[j][2]-npre[k][2]) ); */
                if(dabs(npre[j][0]-npre[k][0])>local_gtol) goto nexti0; 
                if(dabs(npre[j][1]-npre[k][1])>local_gtol) goto nexti0;
                if(dabs(npre[j][2]-npre[k][2])>local_gtol) goto nexti0;
                nvalid[k]=0;
                /* printf("node:%d is close to %d\n", j, k); */
                nexti0:;
               }
              }
              nod( anz, &node, 0, anz->nmax+1, npre[j][0], npre[j][1], npre[j][2], 0 );
              /* printf("make node:%d from node %d\n", anz->nmax, j); */
              seta(0, "n", anz->nmax);
              seta(nset, "n", anz->nmax);
              updLcase( anz->nmax, npre[j][4], npre[j][5], npre[j][3] );
            }
            /* else printf("skip node:%d\n", j); */
          }
  
          /* sortiere die nodes nach winkel zum ersten node, masterrichtung ist en, center ist cg */
          anz_n=set[nset].anz_n-nbuf;
  
          cg[0]=0.;
          cg[1]=0.;
          cg[2]=0.;
          for(j=nbuf; j<set[nset].anz_n; j++)
          {
            cg[0]+=node[set[nset].node[j]].nx;
            cg[1]+=node[set[nset].node[j]].ny;
            cg[2]+=node[set[nset].node[j]].nz;
          }
          cg[0]/=anz_n;
          cg[1]/=anz_n;
          cg[2]/=anz_n;
  
          if ( (rsort = (Rsort *)malloc( (anz_n+1) * sizeof(Rsort))) == NULL )
            printf("ERROR: realloc failed: rsort\n\n" ); 
          v_result( cg, &node[set[nset].node[nbuf]].nx,  v01);
          rsort[0].r=0.;
          rsort[0].i=set[nset].node[nbuf];
          k=1;
          for(j=nbuf+1; j<set[nset].anz_n; j++)
          {
            v_result( cg, &node[set[nset].node[j]].nx,  v02);
            rsort[k].r=v_angle_ref(v01,v02,en);
            rsort[k].i=set[nset].node[j];
            k++;
          }
          qsort( rsort, anz_n, sizeof(Rsort), (void *)compareRsort );
          k=0;
          for(j=nbuf; j<set[nset].anz_n; j++)
          {
            /* printf("%d n:%d alpha:%lf\n", k, rsort[k].i, rsort[k].r*180./pi); */
            set[nset].node[j]=rsort[k].i;
            k++;
          }
          free(rsort);
          
  
          /* generiere neue elemente */
          for(j=nbuf+1; j<set[nset].anz_n-1; j++)
          {
            nvalid[0]=set[nset].node[nbuf];
            nvalid[1]=set[nset].node[j];
            nvalid[2]=set[nset].node[j+1];
            elem_define( anz->emax+1, 7, nvalid, 0, 0 );
            seta(0, "e", anz->emax);
            seta(nset, "e", anz->emax);
          }
          nbuf=set[nset].anz_n;
        }
      } /* end tet4 */

      else if (e_enqire[e_enqire[i].nr].type == 4)  /* HEXA20 */
      {
        for(nn1=0; nn1<8; nn1++)
        {
          if(nn1==7) nn2=0;
          else nn2=nn1+1;
          n1=nhe20[nn1];
          n2=nhe20[nn2];
          /* printf(" 1n: %d %d\n",e_enqire[e_enqire[i].nr].nod[n1],e_enqire[e_enqire[i].nr].nod[n2]); */
          ns=createSplitPoint( &node[e_enqire[e_enqire[i].nr].nod[n1]].nx, &node[e_enqire[e_enqire[i].nr].nod[n2]].nx, pn, eu, ev );
          if(ns>(double *)NULL)
          {
            npre[anz_n][0]=ns[0];
            npre[anz_n][1]=ns[1];
            npre[anz_n][2]=ns[2];
            npre[anz_n][3]=ns[3];
            npre[anz_n][4]=e_enqire[e_enqire[i].nr].nod[n1];
            npre[anz_n][5]=e_enqire[e_enqire[i].nr].nod[n2];
            nvalid[anz_n]=1;
            anz_n++;

            /* getNewName( name, "p" );
            pnt( name, ns[0], ns[1], ns[2], 0 );
            printf(" create point:%s %lf %lf %lf\n\n", name, ns[0], ns[1], ns[2] ); */
          }
        }
        for(nn1=0; nn1<8; nn1+=2)
        {
          nn2=nn1+8;
          n1=nhe20[nn1];
          n2=nhe20[nn2];
          ns=createSplitPoint( &node[e_enqire[e_enqire[i].nr].nod[n1]].nx, &node[e_enqire[e_enqire[i].nr].nod[n2]].nx, pn, eu, ev );
          if(ns>(double *)NULL)
          {
            npre[anz_n][0]=ns[0];
            npre[anz_n][1]=ns[1];
            npre[anz_n][2]=ns[2];
            npre[anz_n][3]=ns[3];
            npre[anz_n][4]=e_enqire[e_enqire[i].nr].nod[n1];
            npre[anz_n][5]=e_enqire[e_enqire[i].nr].nod[n2];
            nvalid[anz_n]=1;
            anz_n++;
          }
        }
        for(nn1=16; nn1<24; nn1++)
        {
          if(nn1==23) nn2=16;
          else nn2=nn1+1;
          n1=nhe20[nn1];
          n2=nhe20[nn2];
          ns=createSplitPoint( &node[e_enqire[e_enqire[i].nr].nod[n1]].nx, &node[e_enqire[e_enqire[i].nr].nod[n2]].nx, pn, eu, ev );
          if(ns>(double *)NULL)
          {
            npre[anz_n][0]=ns[0];
            npre[anz_n][1]=ns[1];
            npre[anz_n][2]=ns[2];
            npre[anz_n][3]=ns[3];
            npre[anz_n][4]=e_enqire[e_enqire[i].nr].nod[n1];
            npre[anz_n][5]=e_enqire[e_enqire[i].nr].nod[n2];
            nvalid[anz_n]=1;
            anz_n++;
          }
        }
        for(nn1=16; nn1<24; nn1+=2)
        {
          nn2=nn1-8;
          n1=nhe20[nn1];
          n2=nhe20[nn2];
          ns=createSplitPoint( &node[e_enqire[e_enqire[i].nr].nod[n1]].nx, &node[e_enqire[e_enqire[i].nr].nod[n2]].nx, pn, eu, ev );
          if(ns>(double *)NULL)
          {
            npre[anz_n][0]=ns[0];
            npre[anz_n][1]=ns[1];
            npre[anz_n][2]=ns[2];
            npre[anz_n][3]=ns[3];
            npre[anz_n][4]=e_enqire[e_enqire[i].nr].nod[n1];
            npre[anz_n][5]=e_enqire[e_enqire[i].nr].nod[n2];
            nvalid[anz_n]=1;
            anz_n++;
          }
        }
        if(anz_n>0)
        {
          /* aussortieren der doppelten nodes */
          for(j=0; j<anz_n; j++)
          {
            if(nvalid[j])
            {
              /* gehe ueber alle nodes und deaktiviere nahe nodes */
              for(k=j; k<anz_n; k++)
              {
               if(nvalid[k])
               {
                /* printf("check node:%d %d gtol:%le\n", j, k, local_gtol );
                   printf("d:%le %le %le\n",(npre[j][0]-npre[k][0]),(npre[j][1]-npre[k][1]),(npre[j][2]-npre[k][2]) ); */
                if(dabs(npre[j][0]-npre[k][0])>local_gtol) goto nexti1; 
                if(dabs(npre[j][1]-npre[k][1])>local_gtol) goto nexti1;
                if(dabs(npre[j][2]-npre[k][2])>local_gtol) goto nexti1;
                nvalid[k]=0;
                /* printf("node:%d is close to %d\n", j, k); */
                nexti1:;
               }
              }
              nod( anz, &node, 0, anz->nmax+1, npre[j][0], npre[j][1], npre[j][2], 0 );
              /* printf("make node:%d from node %d\n", anz->nmax, j); */
              seta(0, "n", anz->nmax);
              seta(nset, "n", anz->nmax);
              updLcase( anz->nmax, npre[j][4], npre[j][5], npre[j][3] );
            }
            /* else printf("skip node:%d\n", j); */
          }
  
          /* sortiere die nodes nach winkel zum ersten node, masterrichtung ist en, center ist cg */
          anz_n=set[nset].anz_n-nbuf;
  
          cg[0]=0.;
          cg[1]=0.;
          cg[2]=0.;
          for(j=nbuf; j<set[nset].anz_n; j++)
          {
            cg[0]+=node[set[nset].node[j]].nx;
            cg[1]+=node[set[nset].node[j]].ny;
            cg[2]+=node[set[nset].node[j]].nz;
          }
          cg[0]/=anz_n;
          cg[1]/=anz_n;
          cg[2]/=anz_n;
  
          if ( (rsort = (Rsort *)malloc( (anz_n+1) * sizeof(Rsort))) == NULL )
            printf("ERROR: realloc failed: rsort\n\n" ); 
          v_result( cg, &node[set[nset].node[nbuf]].nx,  v01);
          rsort[0].r=0.;
          rsort[0].i=set[nset].node[nbuf];
          k=1;
          for(j=nbuf+1; j<set[nset].anz_n; j++)
          {
            v_result( cg, &node[set[nset].node[j]].nx,  v02);
            rsort[k].r=v_angle_ref(v01,v02,en);
            rsort[k].i=set[nset].node[j];
            k++;
          }
          qsort( rsort, anz_n, sizeof(Rsort), (void *)compareRsort );
          k=0;
          for(j=nbuf; j<set[nset].anz_n; j++)
          {
            /* printf("%d n:%d alpha:%lf\n", k, rsort[k].i, rsort[k].r*180./pi); */
            set[nset].node[j]=rsort[k].i;
            k++;
          }
          free(rsort);
          
  
          /* generiere neue elemente */
          for(j=nbuf+1; j<set[nset].anz_n-1; j++)
          {
            nvalid[0]=set[nset].node[nbuf];
            nvalid[1]=set[nset].node[j];
            nvalid[2]=set[nset].node[j+1];
            elem_define( anz->emax+1, 7, nvalid, 0, 0 );
            seta(0, "e", anz->emax);
            seta(nset, "e", anz->emax);
          }
          nbuf=set[nset].anz_n;
        }
      } /* end he20 */

      else if (e_enqire[e_enqire[i].nr].type == 6)  /* TET10 */
      {
        for(nn1=0; nn1<6; nn1++)
        {
          if(nn1==5) nn2=0;
          else nn2=nn1+1;
          n1=ntet10[nn1];
          n2=ntet10[nn2];
          /* printf(" 1n: %d %d\n",e_enqire[e_enqire[i].nr].nod[n1],e_enqire[e_enqire[i].nr].nod[n2]); */
          ns=createSplitPoint( &node[e_enqire[e_enqire[i].nr].nod[n1]].nx, &node[e_enqire[e_enqire[i].nr].nod[n2]].nx, pn, eu, ev );
          if(ns>(double *)NULL)
          {
            npre[anz_n][0]=ns[0];
            npre[anz_n][1]=ns[1];
            npre[anz_n][2]=ns[2];
            npre[anz_n][3]=ns[3];
            npre[anz_n][4]=e_enqire[e_enqire[i].nr].nod[n1];
            npre[anz_n][5]=e_enqire[e_enqire[i].nr].nod[n2];
            nvalid[anz_n]=1;
            anz_n++;

            /* getNewName( name, "p" );
            pnt( name, ns[0], ns[1], ns[2], 0 );
            printf(" create point:%s %lf %lf %lf\n\n", name, ns[0], ns[1], ns[2] ); */
          }
        }
        for(nn1=0; nn1<6; nn1+=2)
        {
          nn2=nn1+6;
          n1=ntet10[nn1];
          n2=ntet10[nn2];
          ns=createSplitPoint( &node[e_enqire[e_enqire[i].nr].nod[n1]].nx, &node[e_enqire[e_enqire[i].nr].nod[n2]].nx, pn, eu, ev );
          if(ns>(double *)NULL)
          {
            npre[anz_n][0]=ns[0];
            npre[anz_n][1]=ns[1];
            npre[anz_n][2]=ns[2];
            npre[anz_n][3]=ns[3];
            npre[anz_n][4]=e_enqire[e_enqire[i].nr].nod[n1];
            npre[anz_n][5]=e_enqire[e_enqire[i].nr].nod[n2];
            nvalid[anz_n]=1;
            anz_n++;
          }
        }
        for(nn1=6; nn1<12; nn1+=2)
        {
          nn2=12;
          n1=ntet10[nn1];
          n2=ntet10[nn2];
          ns=createSplitPoint( &node[e_enqire[e_enqire[i].nr].nod[n1]].nx, &node[e_enqire[e_enqire[i].nr].nod[n2]].nx, pn, eu, ev );
          if(ns>(double *)NULL)
          {
            npre[anz_n][0]=ns[0];
            npre[anz_n][1]=ns[1];
            npre[anz_n][2]=ns[2];
            npre[anz_n][3]=ns[3];
            npre[anz_n][4]=e_enqire[e_enqire[i].nr].nod[n1];
            npre[anz_n][5]=e_enqire[e_enqire[i].nr].nod[n2];
            nvalid[anz_n]=1;
            anz_n++;
          }
        }
        if(anz_n>0)
        {
          /* aussortieren der doppelten nodes */
          for(j=0; j<anz_n; j++)
          {
            if(nvalid[j])
            {
              /* gehe ueber alle nodes und deaktiviere nahe nodes */
              for(k=j; k<anz_n; k++)
              {
               if(nvalid[k])
               {
                /* printf("check node:%d %d gtol:%le\n", j, k, local_gtol );
                   printf("d:%le %le %le\n",(npre[j][0]-npre[k][0]),(npre[j][1]-npre[k][1]),(npre[j][2]-npre[k][2]) ); */
                if(dabs(npre[j][0]-npre[k][0])>local_gtol) goto nexti2; 
                if(dabs(npre[j][1]-npre[k][1])>local_gtol) goto nexti2;
                if(dabs(npre[j][2]-npre[k][2])>local_gtol) goto nexti2;
                nvalid[k]=0;
                /* printf("node:%d is close to %d\n", j, k); */
                nexti2:;
               }
              }
              nod( anz, &node, 0, anz->nmax+1, npre[j][0], npre[j][1], npre[j][2], 0 );
              /* printf("make node:%d from node %d\n", anz->nmax, j); */
              seta(0, "n", anz->nmax);
              seta(nset, "n", anz->nmax);
              updLcase( anz->nmax, npre[j][4], npre[j][5], npre[j][3] );
            }
            /* else printf("skip node:%d\n", j); */
          }
  
          /* sortiere die nodes nach winkel zum ersten node, masterrichtung ist en, center ist cg */
          anz_n=set[nset].anz_n-nbuf;
  
          cg[0]=0.;
          cg[1]=0.;
          cg[2]=0.;
          for(j=nbuf; j<set[nset].anz_n; j++)
          {
            cg[0]+=node[set[nset].node[j]].nx;
            cg[1]+=node[set[nset].node[j]].ny;
            cg[2]+=node[set[nset].node[j]].nz;
          }
          cg[0]/=anz_n;
          cg[1]/=anz_n;
          cg[2]/=anz_n;
  
          if ( (rsort = (Rsort *)malloc( (anz_n+1) * sizeof(Rsort))) == NULL )
            printf("ERROR: realloc failed: rsort\n\n" ); 
          v_result( cg, &node[set[nset].node[nbuf]].nx,  v01);
          rsort[0].r=0.;
          rsort[0].i=set[nset].node[nbuf];
          k=1;
          for(j=nbuf+1; j<set[nset].anz_n; j++)
          {
            v_result( cg, &node[set[nset].node[j]].nx,  v02);
            rsort[k].r=v_angle_ref(v01,v02,en);
            rsort[k].i=set[nset].node[j];
            k++;
          }
          qsort( rsort, anz_n, sizeof(Rsort), (void *)compareRsort );
          k=0;
          for(j=nbuf; j<set[nset].anz_n; j++)
          {
            /* printf("%d n:%d alpha:%lf\n", k, rsort[k].i, rsort[k].r*180./pi); */
            set[nset].node[j]=rsort[k].i;
            k++;
          }
          free(rsort);
          
  
          /* generiere neue elemente */
          for(j=nbuf+1; j<set[nset].anz_n-1; j++)
          {
            nvalid[0]=set[nset].node[nbuf];
            nvalid[1]=set[nset].node[j];
            nvalid[2]=set[nset].node[j+1];
            elem_define( anz->emax+1, 7, nvalid, 0, 0 );
            seta(0, "e", anz->emax);
            seta(nset, "e", anz->emax);
          }
          nbuf=set[nset].anz_n;
        }
      } /* end tet10 */
    }


    /* zeige neue elemente */
    makeSurfaces();
    allocUtilityData();        
    updateDispLists(); 
    if(anz->l) plot( "ev -qcut" );
    else plot( "ei -qcut" );
  }
}



void flipSurfori(int s)
{
  int i,j,k,n;
  int nbuf[26];
  double *buf;

    /* switch signum of surf */
    if (surf[s].ori=='-') surf[s].ori='+';
    else                  surf[s].ori='-';
    n=0;
    while((surf[s].npgn-n)>0)
    {
      n++; /* jump over the polygon token (ie.GL_POLYGON_TOKEN) */
      j=surf[s].pgn[n++];
      surf[s].pgn[n]*=-1;
      surf[s].pgn[n+1]*=-1;
      surf[s].pgn[n+2]*=-1;
      n+=3;
      if ((buf = (double *)malloc((j*3)*sizeof(double)) ) == NULL )
      { printf("\n\nERROR: realloc failure in flip\n\n"); return; }
      for(k=0; k<j; k++)
      {
        buf[j*3-k*3-3]=surf[s].pgn[n];
        buf[j*3-k*3-2]=surf[s].pgn[n+1];
        buf[j*3-k*3-1]=surf[s].pgn[n+2];
        n+=3;
      }
      n-=3*j;
      for(k=0; k<j; k++)
      {
        surf[s].pgn[n]  =buf[k*3] ; 
        surf[s].pgn[n+1]=buf[k*3+1];
        surf[s].pgn[n+2]=buf[k*3+2];
        n+=3;
      }
      free(buf);
    }

    /* switch orient of all embedded elements */
    for (i=0; i<surf[s].ne; i++)
    {
      if (e_enqire[surf[s].elem[i]].type == 7)
      {
        nbuf[1]=e_enqire[surf[s].elem[i]].nod[1];
        nbuf[2]=e_enqire[surf[s].elem[i]].nod[2];
        e_enqire[surf[s].elem[i]].nod[2]=nbuf[1];
        e_enqire[surf[s].elem[i]].nod[1]=nbuf[2];
      }  
      else if (e_enqire[surf[s].elem[i]].type == 8)
      {
        nbuf[0]=e_enqire[surf[s].elem[i]].nod[0];
        nbuf[1]=e_enqire[surf[s].elem[i]].nod[1];
        nbuf[4]=e_enqire[surf[s].elem[i]].nod[4];
        nbuf[5]=e_enqire[surf[s].elem[i]].nod[5];
        e_enqire[surf[s].elem[i]].nod[0]=nbuf[1];
        e_enqire[surf[s].elem[i]].nod[1]=nbuf[0];
        e_enqire[surf[s].elem[i]].nod[4]=nbuf[5];
        e_enqire[surf[s].elem[i]].nod[5]=nbuf[4];
      }  
      else if (e_enqire[surf[s].elem[i]].type == 9)
      {
        nbuf[1]=e_enqire[surf[s].elem[i]].nod[1];
        nbuf[3]=e_enqire[surf[s].elem[i]].nod[3];
        e_enqire[surf[s].elem[i]].nod[3]=nbuf[1];
        e_enqire[surf[s].elem[i]].nod[1]=nbuf[3];
      }  
      else if (e_enqire[surf[s].elem[i]].type == 10)
      {
        nbuf[1]=e_enqire[surf[s].elem[i]].nod[1];
        nbuf[3]=e_enqire[surf[s].elem[i]].nod[3];
        nbuf[4]=e_enqire[surf[s].elem[i]].nod[4];
        nbuf[5]=e_enqire[surf[s].elem[i]].nod[5];
        nbuf[6]=e_enqire[surf[s].elem[i]].nod[6];
        nbuf[7]=e_enqire[surf[s].elem[i]].nod[7];
        e_enqire[surf[s].elem[i]].nod[3]=nbuf[1];
        e_enqire[surf[s].elem[i]].nod[1]=nbuf[3];
        e_enqire[surf[s].elem[i]].nod[7]=nbuf[4];
        e_enqire[surf[s].elem[i]].nod[6]=nbuf[5];
        e_enqire[surf[s].elem[i]].nod[5]=nbuf[6];
        e_enqire[surf[s].elem[i]].nod[4]=nbuf[7];
      }
      else  
      {
        printf(" ERROR: element type %d not known\n", e_enqire[surf[s].elem[i]].type);
      }
    }
}


void oriAllSurfs(int sur)
{
  int i,j,n,l,ll,lll,cl,s, prod1, prod2,oriflag,counter=0,surl;
  int **ltos, *stos;

  /* go over all surfs.*/
  /* check if one neighbour surf is oriented */
  /* then orient the surf */

  /* first go over all lines and determine all related surfs (should be 2) */
  /* store the surfs in an array which points then to the surf */
  /*  this will be set to -1 if the surf is oriented */
  /*  if all surfs are oriented this array contains only -1 */
  /* relate all surfs to its lines */
  if( (ltos=(int **)malloc((anzGeo->l+1)*sizeof(int *) ) )==NULL)
  printf("ERROR malloc failed in oriAllSurfs()\n");
  for(i=0; i<anzGeo->l; i++)
  {
    if( (ltos[i]=(int *)malloc((3)*sizeof(int) ) )==NULL)
    printf("ERROR malloc failed in oriAllSurfs()\n");
     ltos[i][0]=0; for(j=1;j<3;j++) ltos[i][j]=-1;
  }

  for(s=0; s<anzGeo->s; s++)
  {
    if(surf[s].name!=NULL) for(j=0; j<surf[s].nl; j++)
    {
      if(surf[s].typ[j]=='l')
      {
        n=++ltos[surf[s].l[j]][0];
        if(n>2)
        {
          printf("ERROR: to many related surfs(%d) for line:%s\n", n, line[surf[s].l[j]].name);
          printf("No inner surfaces are permitted. Command could not be executed\n");
          return;
        }
        ltos[surf[s].l[j]][n]=s;
      }
      else
      {
        cl=surf[s].l[j];
        for(l=0; l<lcmb[cl].nl; l++)
	{
          n=++ltos[lcmb[cl].l[l]][0];
          if(n>2)
          {
            printf("ERROR: to many related surfs(%d) for line:%s\n", n, line[lcmb[cl].l[l]].name);
            printf("No inner surfaces are permitted. Command could not be executed\n");
            return;
          }
          ltos[lcmb[cl].l[l]][n]=s;
	}
      }
    }
  }


  for(i=0; i<anzGeo->l; i++)
  {
    printf("l:%s ", line[i].name);
    if(ltos[i][1]>-1) printf("surf:%s ", surf[ltos[i][1]].name);
    if(ltos[i][2]>-1) printf("surf:%s ", surf[ltos[i][2]].name);
    printf("\n ");
  }

  /* create a link between surfindex and surface */
  /* the surfindex is - as long a surf is not oriented */
  if( (stos=(int *)malloc((anzGeo->s+1)*sizeof(int) ) )==NULL)
    printf("ERROR malloc failed in oriAllSurfs()\n");
  for(i=0; i<anzGeo->s; i++) stos[i]=-(i+1);
  
  /* the start-surface is already oriented */
  stos[sur]=sur+1; 
 
  /* go over all surfs and look if one has an oriented neighbour */
 more:;
  oriflag=0;
  for(s=0; s<anzGeo->s; s++)
  {
    /* if the surf is valid and not oriented go over all its lines */
    if((surf[s].name!=NULL)&&(stos[s]<0)) for(j=0; j<surf[s].nl; j++)
    {
      oriflag=1;
      if(surf[s].typ[j]=='l')
      {
        /* check the connected surfs based on the common lines if it is an oriented one */
        for(n=1;n<3;n++) if(ltos[surf[s].l[j]][n]>-1) if((stos[ltos[surf[s].l[j]][n]]-1!=s)&&(stos[ltos[surf[s].l[j]][n]]>0))
	{
	  sur=stos[ltos[surf[s].l[j]][n]]-1;
          surl= surf[s].l[j];
          printf("surf:%s line:%s oriented surf:%s\n", surf[s].name, line[surl].name, surf[sur].name);

          /* check if the surf must be inverted */
          /* based on the product of orientations of the oriented surf */
          /* determine the index of the connected line in sur */
          if(surf[sur].ori=='+') prod1=1; else prod1=-1;
          for(ll=0; ll<surf[sur].nl; ll++)
	  {
            if(surf[sur].typ[ll]=='l') 
            {
	      if(surl==surf[sur].l[ll])
              {
                if(surf[sur].o[ll]=='+') prod1*=1; else prod1*=-1;
                goto found1;
              }
	    }
	    else 
            {
              for(lll=0; lll<lcmb[surf[sur].l[ll]].nl; lll++) if(surl==lcmb[surf[sur].l[ll]].l[lll])
              {
                if(surf[sur].o[ll]=='+') prod1*=1; else prod1*=-1;
                if(lcmb[surf[sur].l[ll]].o[lll]=='+') prod1*=1; else prod1*=-1;
                goto found1;
	      }
	    }
	  }
	found1:;

          /* product of orientations of the actual surf */
          if(surf[s].ori=='+') prod2=1; else prod2=-1;
          if(surf[s].o[j]=='+') prod2*=1; else prod2*=-1;

          stos[s]=s+1;
          if(prod2==prod1)
	  {
            flipSurfori(s);
	  }
          goto new_surf;
	}
      }
      else
      {
        cl=surf[s].l[j];
        for(l=0; l<lcmb[cl].nl; l++)
	{
          /* check the connected surfs based on the common lines if it is an oriented one */
          for(n=1;n<3;n++) if(ltos[lcmb[cl].l[l]][n]>-1) if((stos[ltos[lcmb[cl].l[l]][n]]-1!=s)&&(stos[ltos[lcmb[cl].l[l]][n]]>0))
	  {
	    sur=stos[ltos[lcmb[cl].l[l]][n]];
            printf("surf:%s lcmb:%s line:%s oriented surf:%s\n", surf[s].name, lcmb[cl].name, line[lcmb[cl].l[l]].name, surf[sur].name);
            surl= lcmb[cl].l[l];

            /* check if the surf must be inverted */
            /* based on the product of orientations of the oriented surf */
            /* determine the index of the connected line in sur */
            if(surf[sur].ori=='+') prod1=1; else prod1=-1;
            for(ll=0; ll<surf[sur].nl; ll++)
            {
              if(surf[sur].typ[ll]=='l') 
              {
		if(surl==surf[sur].l[ll])
                {
                  if(surf[sur].o[ll]=='+') prod1*=1; else prod1*=-1;
                  goto found2;
                }
   	      }
   	      else 
              {
                for(lll=0; lll<lcmb[surf[sur].l[ll]].nl; lll++) 
                if(surl==lcmb[surf[sur].l[ll]].l[lll])
                {
                  if(surf[sur].o[ll]=='+') prod1*=1; else prod1*=-1;
                  if(lcmb[surf[sur].l[ll]].o[lll]=='+') prod1*=1; else prod1*=-1;
                  goto found2;
   	        }
   	      }
	    }
	   found2:;
 
            /* product of orientations of the actual surf */
            if(surf[s].ori=='+') prod2=1; else prod2=-1;
            if(surf[s].o[j]=='+') prod2*=1; else prod2*=-1;
            if(lcmb[cl].o[l]=='+') prod2*=1; else prod2*=-1;

            stos[s]=s+1;
            if(prod2==prod1)
	    {
              flipSurfori(s);
	    }
            goto new_surf;
	  }
	}
      }
    }
    new_surf:;    
  }
  if(oriflag)
  {
    counter++;
    if(counter<anzGeo->s) goto more;
    else printf(" WARNING: too much loops. Some surfs might be still unoriented.\n");
  }
}



void flip( unsigned char *type, int e)
{
  int s=0;
  int nbuf[20];

  if (((type[0]=='e')&&(anzGeo->s>0))||(type[0]=='s'))
  {
    /* switch surface and elements and embedded faces */
    /* identify the surf */
    if (type[0]=='e') s=selem[e];
    if (type[0]=='s') s=e;

    /* check if all connected surfs should be oriented according to the identified one */
    if(type[1]=='a')
    {
      oriAllSurfs(s);
    }
    else flipSurfori(s);
  } 
  else if ((type[0]=='e')&&(anzGeo->s==0))
  {
    /* switch orient of the element */
      if (e_enqire[e].type == 7)
      {
        nbuf[1]=e_enqire[e].nod[1];
        nbuf[2]=e_enqire[e].nod[2];
        e_enqire[e].nod[2]=nbuf[1];
        e_enqire[e].nod[1]=nbuf[2];
      }  
      else if (e_enqire[e].type == 8)
      {
        nbuf[0]=e_enqire[e].nod[0];
        nbuf[1]=e_enqire[e].nod[1];
        nbuf[4]=e_enqire[e].nod[4];
        nbuf[5]=e_enqire[e].nod[5];
        e_enqire[e].nod[0]=nbuf[1];
        e_enqire[e].nod[1]=nbuf[0];
        e_enqire[e].nod[4]=nbuf[5];
        e_enqire[e].nod[5]=nbuf[4];
      }  
      else if (e_enqire[e].type == 9)
      {
        nbuf[1]=e_enqire[e].nod[1];
        nbuf[3]=e_enqire[e].nod[3];
        e_enqire[e].nod[3]=nbuf[1];
        e_enqire[e].nod[1]=nbuf[3];
      }  
      else if (e_enqire[e].type == 10)
      {
        nbuf[1]=e_enqire[e].nod[1];
        nbuf[3]=e_enqire[e].nod[3];
        nbuf[4]=e_enqire[e].nod[4];
        nbuf[5]=e_enqire[e].nod[5];
        nbuf[6]=e_enqire[e].nod[6];
        nbuf[7]=e_enqire[e].nod[7];
        e_enqire[e].nod[3]=nbuf[1];
        e_enqire[e].nod[1]=nbuf[3];
        e_enqire[e].nod[7]=nbuf[4];
        e_enqire[e].nod[6]=nbuf[5];
        e_enqire[e].nod[5]=nbuf[6];
        e_enqire[e].nod[4]=nbuf[7];
      }  
      else  
      {
        printf(" ERROR: element type %d not known\n", e_enqire[e].type);
      }
  } 
  updateDispLists();
}
