From 94a7756b50a3c46ec91af0a8fca4f231953ccb6f Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Wed, 17 May 2006 01:19:21 +0000
Subject: [PATCH] merging offscreen rendering from branch

---
 Fltk/Opengl.cpp         |   8 +-
 Graphics/CreateFile.cpp | 205 +++++++++---------
 Graphics/Makefile       |  97 ++++++---
 Graphics/gl2gif.cpp     |  39 ++--
 Graphics/gl2gif.h       |   3 +-
 Graphics/gl2jpeg.cpp    |  41 ++--
 Graphics/gl2jpeg.h      |   4 +-
 Graphics/gl2png.cpp     |  62 +++---
 Graphics/gl2png.h       |   3 +-
 Graphics/gl2ppm.cpp     |  26 ++-
 Graphics/gl2ppm.h       |   3 +-
 Graphics/gl2yuv.cpp     |  26 +--
 Graphics/gl2yuv.h       |   3 +-
 Parser/Gmsh.tab.cpp     | 457 ++++++++++++++++++++--------------------
 Parser/Gmsh.y           |  13 +-
 Parser/Gmsh.yy.cpp      |   4 +-
 configure.in            |  32 ++-
 17 files changed, 529 insertions(+), 497 deletions(-)

diff --git a/Fltk/Opengl.cpp b/Fltk/Opengl.cpp
index 2033bb6017..44c302d8c6 100644
--- a/Fltk/Opengl.cpp
+++ b/Fltk/Opengl.cpp
@@ -1,4 +1,4 @@
-// $Id: Opengl.cpp,v 1.57 2006-01-06 00:34:23 geuzaine Exp $
+// $Id: Opengl.cpp,v 1.58 2006-05-17 01:19:05 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -37,11 +37,13 @@ extern Context_T CTX;
 
 void SetOpenglContext(void)
 {
+  if(!WID) return;
   WID->make_opengl_current();
 }
 
 void Draw(void)
 {
+  if(!WID) return;
   WID->redraw_opengl();
 }
 
@@ -163,6 +165,8 @@ void Draw_String(char *s, double style)
 
 void Draw_OnScreenMessages()
 {
+  if(!WID) return;
+
   glColor4ubv((GLubyte *) & CTX.color.text);
   gl_font(CTX.gl_font_enum, CTX.gl_fontsize);
   double h = gl_height();
@@ -186,6 +190,8 @@ char SelectEntity(int type, int *n,
 		  Curve *c[SELECTION_MAX_HITS], 
 		  Surface *s[SELECTION_MAX_HITS])
 {
+  if(!WID) return 'q';
+
   WID->g_opengl_window->take_focus(); // force keyboard focus in GL window 
   WID->g_opengl_window->SelectionMode = true; // enable lasso selection
 
diff --git a/Graphics/CreateFile.cpp b/Graphics/CreateFile.cpp
index 585f3af0c2..c819fe3a8c 100644
--- a/Graphics/CreateFile.cpp
+++ b/Graphics/CreateFile.cpp
@@ -1,4 +1,4 @@
-// $Id: CreateFile.cpp,v 1.76 2006-01-06 00:34:24 geuzaine Exp $
+// $Id: CreateFile.cpp,v 1.77 2006-05-17 01:19:05 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -23,13 +23,9 @@
 #include "GmshUI.h"
 #include "Mesh.h"
 #include "OpenFile.h"
-#include "Draw.h"
 #include "Context.h"
 #include "Options.h"
 
-extern Context_T CTX;
-extern Mesh M;
-
 #include "gl2ps.h"
 #include "gl2gif.h"
 #include "gl2jpeg.h"
@@ -37,13 +33,8 @@ extern Mesh M;
 #include "gl2ppm.h"
 #include "gl2yuv.h"
 
-void FillBuffer(void)
-{
-  SetOpenglContext();
-  ClearOpengl();
-  Draw3d();
-  Draw2d();
-}
+extern Context_T CTX;
+extern Mesh M;
 
 int GuessFileFormatFromFileName(char *name)
 {
@@ -131,66 +122,62 @@ void CreateOutputFile(char *name, int format)
     Msg(STATUS2N, "Wrote '%s'", name);
     break;
 
+  case FORMAT_PPM:
+  case FORMAT_YUV:
+  case FORMAT_GIF:  
   case FORMAT_JPEG:
   case FORMAT_JPEGTEX:
   case FORMAT_PNG:
   case FORMAT_PNGTEX:
-    if(!(fp = fopen(name, "wb"))) {
-      Msg(GERROR, "Unable to open file '%s'", name);
-      return;
-    }
-    if(format == FORMAT_JPEGTEX || format == FORMAT_PNGTEX){
-      CTX.print.gl_fonts = 0;
-    }
-    FillBuffer();
-    CTX.print.gl_fonts = 1;
-    if(format == FORMAT_JPEG || format == FORMAT_JPEGTEX){
-      Msg(INFO, "Writing JPEG file '%s'", name);
-      create_jpeg(fp, width, height, 
-		  CTX.print.jpeg_quality, CTX.print.jpeg_smoothing);
-      Msg(INFO, "Wrote JPEG file '%s'", name);
-    }
-    else{
-      Msg(INFO, "Writing PNG file '%s'", name);
-      create_png(fp, width, height, 100);
-      Msg(INFO, "Wrote PNG file '%s'", name);
-    }
-    Msg(STATUS2N, "Wrote '%s'", name);
-    fclose(fp);
-    break;
+    {
+      if(!(fp = fopen(name, "wb"))) {
+	Msg(GERROR, "Unable to open file '%s'", name);
+	return;
+      }
 
-  case FORMAT_PPM:
-  case FORMAT_YUV:
-  case FORMAT_GIF:
-    if(!(fp = fopen(name, "wb"))) {
-      Msg(GERROR, "Unable to open file '%s'", name);
-      return;
-    }
-    FillBuffer();
-    if(format == FORMAT_PPM){
-      Msg(INFO, "Writing PPM file '%s'", name);
-      create_ppm(fp, width, height);
-      Msg(INFO, "Wrote PPM file '%s'", name);
-    }
-    else if (format == FORMAT_YUV){
-      Msg(INFO, "Writing YUV file '%s'", name);
-      create_yuv(fp, width, height);
-      Msg(INFO, "Wrote YUV file '%s'", name);
-    }
-    else{
-      Msg(INFO, "Writing GIF file '%s'", name);
-      create_gif(fp, width, height,
-		 CTX.print.gif_dither,
-		 CTX.print.gif_sort,
-		 CTX.print.gif_interlace,
-		 CTX.print.gif_transparent,
-		 CTX.UNPACK_RED(CTX.color.bg),
-		 CTX.UNPACK_GREEN(CTX.color.bg), 
-		 CTX.UNPACK_BLUE(CTX.color.bg));
-      Msg(INFO, "Wrote GIF file '%s'", name);
+      if(format == FORMAT_JPEGTEX || format == FORMAT_PNGTEX)
+	CTX.print.gl_fonts = 0;
+
+      PixelBuffer buffer(width, height, GL_RGB, GL_UNSIGNED_BYTE);
+      buffer.Fill();
+
+      CTX.print.gl_fonts = 1;
+      if(format == FORMAT_PPM){
+	Msg(INFO, "Writing PPM file '%s'", name);
+	create_ppm(fp, &buffer);
+	Msg(INFO, "Wrote PPM file '%s'", name);
+      }
+      else if (format == FORMAT_YUV){
+	Msg(INFO, "Writing YUV file '%s'", name);
+	create_yuv(fp, &buffer);
+	Msg(INFO, "Wrote YUV file '%s'", name);
+      }
+      else if (format == FORMAT_GIF){
+	Msg(INFO, "Writing GIF file '%s'", name);
+	create_gif(fp, &buffer,
+		   CTX.print.gif_dither,
+		   CTX.print.gif_sort,
+		   CTX.print.gif_interlace,
+		   CTX.print.gif_transparent,
+		   CTX.UNPACK_RED(CTX.color.bg),
+		   CTX.UNPACK_GREEN(CTX.color.bg), 
+		   CTX.UNPACK_BLUE(CTX.color.bg));
+	Msg(INFO, "Wrote GIF file '%s'", name);
+      }
+      else if(format == FORMAT_JPEG || format == FORMAT_JPEGTEX){
+	Msg(INFO, "Writing JPEG file '%s'", name);
+	create_jpeg(fp, &buffer, CTX.print.jpeg_quality, CTX.print.jpeg_smoothing);
+	Msg(INFO, "Wrote JPEG file '%s'", name);
+      }
+      else{
+	Msg(INFO, "Writing PNG file '%s'", name);
+	create_png(fp, &buffer, 100);
+	Msg(INFO, "Wrote PNG file '%s'", name);
+      }
+      
+      Msg(STATUS2N, "Wrote '%s'", name);
+      fclose(fp);
     }
-    Msg(STATUS2N, "Wrote '%s'", name);
-    fclose(fp);
     break;
 
   case FORMAT_PS:
@@ -198,33 +185,32 @@ void CreateOutputFile(char *name, int format)
   case FORMAT_EPSTEX:
   case FORMAT_PDF:
   case FORMAT_PDFTEX:
-    if(!(fp = fopen(name, "wb"))) {
-      Msg(GERROR, "Unable to open file '%s'", name);
-      return;
-    }
-
-    switch(format){
-    case FORMAT_PDF:
-    case FORMAT_PDFTEX:
-      psformat = GL2PS_PDF;
-      break;
-    case FORMAT_PS:
-      psformat = GL2PS_PS;
-      break;
-    default:
-      psformat = GL2PS_EPS;
-      break;
-    }
-
     {
-      float *pixels = NULL;
+      if(!(fp = fopen(name, "wb"))) {
+	Msg(GERROR, "Unable to open file '%s'", name);
+	return;
+      }
+      
+      switch(format){
+      case FORMAT_PDF:
+      case FORMAT_PDFTEX:
+	psformat = GL2PS_PDF;
+	break;
+      case FORMAT_PS:
+	psformat = GL2PS_PS;
+	break;
+      default:
+	psformat = GL2PS_EPS;
+	break;
+      }
+      
+      PixelBuffer buffer(width, height, GL_RGB, GL_FLOAT);
+      
       if(CTX.print.eps_quality == 0){
 	if(format == FORMAT_EPSTEX || format == FORMAT_PDFTEX)
 	  CTX.print.gl_fonts = 0;
-	FillBuffer();
+	buffer.Fill();
 	CTX.print.gl_fonts = 1;
-	pixels = new float[width * height * 3];
-	glReadPixels(0, 0, width, height, GL_RGB, GL_FLOAT, pixels);
       }
       
       pssort = (CTX.print.eps_quality == 2) ? GL2PS_BSP_SORT : GL2PS_SIMPLE_SORT;
@@ -258,42 +244,45 @@ void CreateOutputFile(char *name, int format)
 	  glMatrixMode(GL_MODELVIEW);
 	  glLoadIdentity();
 	  glRasterPos2d(0, 0);
-	  gl2psDrawPixels(width, height, 0, 0, GL_RGB, GL_FLOAT, pixels);
+	  gl2psDrawPixels(width, height, 0, 0, GL_RGB, GL_FLOAT, buffer.GetPixels());
 	  glMatrixMode(GL_PROJECTION);
 	  glLoadMatrixd(projection);
 	  glMatrixMode(GL_MODELVIEW);
 	  glLoadMatrixd(modelview);
-	  delete [] pixels;
 	}
 	else{
 	  CTX.print.gl_fonts = 0;
-	  FillBuffer();
+	  buffer.Fill();
 	  CTX.print.gl_fonts = 1;
 	}
 	res = gl2psEndPage();
       }
+
+      Msg(INFO, "Wrote %s file '%s'", (psformat == GL2PS_PDF) ? "PDF" : "PS/EPS", name);
+      Msg(STATUS2N, "Wrote '%s'", name);
+      fclose(fp);
     }
-    Msg(INFO, "Wrote %s file '%s'", (psformat == GL2PS_PDF) ? "PDF" : "PS/EPS", name);
-    Msg(STATUS2N, "Wrote '%s'", name);
-    fclose(fp);
     break;
 
   case FORMAT_TEX:
-    if(!(fp = fopen(name, "w"))) {
-      Msg(GERROR, "Unable to open file '%s'", name);
-      return;
+    {
+      if(!(fp = fopen(name, "w"))) {
+	Msg(GERROR, "Unable to open file '%s'", name);
+	return;
+      }
+      Msg(INFO, "Writing TEX file '%s'", name);
+      gl2psBeginPage(CTX.base_filename, "Gmsh", viewport,
+		     GL2PS_TEX, GL2PS_NO_SORT, GL2PS_SILENT, GL_RGBA, 0, NULL, 
+		     0, 0, 0, 1000, fp, name);
+      CTX.print.gl_fonts = 0;
+      PixelBuffer buffer(width, height, GL_RGB, GL_UNSIGNED_BYTE);
+      buffer.Fill();
+      CTX.print.gl_fonts = 1;
+      res = gl2psEndPage();
+      Msg(INFO, "Wrote TEX file '%s'", name);
+      Msg(STATUS2N, "Wrote '%s'", name);
+      fclose(fp);
     }
-    Msg(INFO, "Writing TEX file '%s'", name);
-    gl2psBeginPage(CTX.base_filename, "Gmsh", viewport,
-                   GL2PS_TEX, GL2PS_NO_SORT, GL2PS_SILENT, GL_RGBA, 0, NULL, 
-		   0, 0, 0, 1000, fp, name);
-    CTX.print.gl_fonts = 0;
-    FillBuffer();
-    CTX.print.gl_fonts = 1;
-    res = gl2psEndPage();
-    Msg(INFO, "Wrote TEX file '%s'", name);
-    Msg(STATUS2N, "Wrote '%s'", name);
-    fclose(fp);
     break;
 
   default:
diff --git a/Graphics/Makefile b/Graphics/Makefile
index 20b5d47a26..a4d3f8b303 100644
--- a/Graphics/Makefile
+++ b/Graphics/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.79 2006-03-17 21:04:34 geuzaine Exp $
+# $Id: Makefile,v 1.80 2006-05-17 01:19:06 geuzaine Exp $
 #
 # Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 #
@@ -218,36 +218,81 @@ CreateFile.o: CreateFile.cpp ../Common/Gmsh.h ../Common/Message.h \
   ../Mesh/Vertex.h ../Mesh/Simplex.h ../Geo/ExtrudeParams.h \
   ../Common/VertexArray.h ../Common/SmoothNormals.h ../Numeric/Numeric.h \
   ../Mesh/Metric.h ../Mesh/Vertex.h ../Mesh/Simplex.h ../Mesh/Mesh.h \
-  ../Mesh/Matrix.h ../Parser/OpenFile.h Draw.h ../Common/Views.h \
-  ../Common/ColorTable.h ../Common/VertexArray.h \
+  ../Mesh/Matrix.h ../Parser/OpenFile.h ../Common/Context.h \
+  ../Common/Options.h gl2ps.h gl2gif.h PixelBuffer.h Draw.h \
+  ../Common/Views.h ../Common/ColorTable.h ../Common/VertexArray.h \
   ../Common/SmoothNormals.h ../Common/GmshMatrix.h \
-  ../Common/AdaptiveViews.h ../Common/GmshMatrix.h ../Common/Context.h \
-  ../Common/Options.h gl2ps.h gl2gif.h gl2jpeg.h gl2png.h gl2ppm.h \
-  gl2yuv.h
+  ../Common/AdaptiveViews.h ../Common/GmshMatrix.h gl2jpeg.h gl2png.h \
+  gl2ppm.h gl2yuv.h
 # 1 "/Users/geuzaine/.gmsh/Graphics//"
 gl2ps.o: gl2ps.cpp gl2ps.h
 # 1 "/Users/geuzaine/.gmsh/Graphics//"
-gl2gif.o: gl2gif.cpp ../Common/Gmsh.h ../Common/Message.h \
-  ../DataStr/Malloc.h ../DataStr/List.h ../DataStr/Tree.h \
-  ../DataStr/avl.h ../DataStr/Tools.h ../DataStr/List.h ../DataStr/Tree.h \
-  ../Common/GmshUI.h gl2gif.h
+gl2gif.o: gl2gif.cpp gl2gif.h PixelBuffer.h ../Common/Gmsh.h \
+  ../Common/Message.h ../DataStr/Malloc.h ../DataStr/List.h \
+  ../DataStr/Tree.h ../DataStr/avl.h ../DataStr/Tools.h ../DataStr/List.h \
+  ../DataStr/Tree.h ../Common/GmshUI.h Draw.h ../Mesh/Mesh.h \
+  ../Mesh/Vertex.h ../Mesh/Element.h ../Mesh/Vertex.h ../Mesh/Simplex.h \
+  ../Mesh/Vertex.h ../Mesh/Element.h ../Mesh/Face.h ../Mesh/Vertex.h \
+  ../Mesh/Element.h ../Mesh/Edge.h ../Mesh/Vertex.h ../Mesh/Simplex.h \
+  ../Geo/ExtrudeParams.h ../Common/VertexArray.h \
+  ../Common/SmoothNormals.h ../Numeric/Numeric.h ../Mesh/Metric.h \
+  ../Mesh/Vertex.h ../Mesh/Simplex.h ../Mesh/Mesh.h ../Mesh/Matrix.h \
+  ../Common/Views.h ../Common/ColorTable.h ../Common/VertexArray.h \
+  ../Common/SmoothNormals.h ../Common/GmshMatrix.h \
+  ../Common/AdaptiveViews.h ../Common/GmshMatrix.h ../Common/Context.h
 # 1 "/Users/geuzaine/.gmsh/Graphics//"
-gl2jpeg.o: gl2jpeg.cpp ../Common/Gmsh.h ../Common/Message.h \
-  ../DataStr/Malloc.h ../DataStr/List.h ../DataStr/Tree.h \
-  ../DataStr/avl.h ../DataStr/Tools.h ../DataStr/List.h ../DataStr/Tree.h \
-  ../Common/GmshUI.h
+gl2jpeg.o: gl2jpeg.cpp gl2jpeg.h PixelBuffer.h ../Common/Gmsh.h \
+  ../Common/Message.h ../DataStr/Malloc.h ../DataStr/List.h \
+  ../DataStr/Tree.h ../DataStr/avl.h ../DataStr/Tools.h ../DataStr/List.h \
+  ../DataStr/Tree.h ../Common/GmshUI.h Draw.h ../Mesh/Mesh.h \
+  ../Mesh/Vertex.h ../Mesh/Element.h ../Mesh/Vertex.h ../Mesh/Simplex.h \
+  ../Mesh/Vertex.h ../Mesh/Element.h ../Mesh/Face.h ../Mesh/Vertex.h \
+  ../Mesh/Element.h ../Mesh/Edge.h ../Mesh/Vertex.h ../Mesh/Simplex.h \
+  ../Geo/ExtrudeParams.h ../Common/VertexArray.h \
+  ../Common/SmoothNormals.h ../Numeric/Numeric.h ../Mesh/Metric.h \
+  ../Mesh/Vertex.h ../Mesh/Simplex.h ../Mesh/Mesh.h ../Mesh/Matrix.h \
+  ../Common/Views.h ../Common/ColorTable.h ../Common/VertexArray.h \
+  ../Common/SmoothNormals.h ../Common/GmshMatrix.h \
+  ../Common/AdaptiveViews.h ../Common/GmshMatrix.h ../Common/Context.h
 # 1 "/Users/geuzaine/.gmsh/Graphics//"
-gl2png.o: gl2png.cpp ../Common/Gmsh.h ../Common/Message.h \
-  ../DataStr/Malloc.h ../DataStr/List.h ../DataStr/Tree.h \
-  ../DataStr/avl.h ../DataStr/Tools.h ../DataStr/List.h ../DataStr/Tree.h \
-  ../Common/GmshUI.h
+gl2png.o: gl2png.cpp gl2png.h PixelBuffer.h ../Common/Gmsh.h \
+  ../Common/Message.h ../DataStr/Malloc.h ../DataStr/List.h \
+  ../DataStr/Tree.h ../DataStr/avl.h ../DataStr/Tools.h ../DataStr/List.h \
+  ../DataStr/Tree.h ../Common/GmshUI.h Draw.h ../Mesh/Mesh.h \
+  ../Mesh/Vertex.h ../Mesh/Element.h ../Mesh/Vertex.h ../Mesh/Simplex.h \
+  ../Mesh/Vertex.h ../Mesh/Element.h ../Mesh/Face.h ../Mesh/Vertex.h \
+  ../Mesh/Element.h ../Mesh/Edge.h ../Mesh/Vertex.h ../Mesh/Simplex.h \
+  ../Geo/ExtrudeParams.h ../Common/VertexArray.h \
+  ../Common/SmoothNormals.h ../Numeric/Numeric.h ../Mesh/Metric.h \
+  ../Mesh/Vertex.h ../Mesh/Simplex.h ../Mesh/Mesh.h ../Mesh/Matrix.h \
+  ../Common/Views.h ../Common/ColorTable.h ../Common/VertexArray.h \
+  ../Common/SmoothNormals.h ../Common/GmshMatrix.h \
+  ../Common/AdaptiveViews.h ../Common/GmshMatrix.h ../Common/Context.h
 # 1 "/Users/geuzaine/.gmsh/Graphics//"
-gl2ppm.o: gl2ppm.cpp ../Common/Gmsh.h ../Common/Message.h \
-  ../DataStr/Malloc.h ../DataStr/List.h ../DataStr/Tree.h \
-  ../DataStr/avl.h ../DataStr/Tools.h ../DataStr/List.h ../DataStr/Tree.h \
-  ../Common/GmshUI.h
+gl2ppm.o: gl2ppm.cpp gl2ppm.h PixelBuffer.h ../Common/Gmsh.h \
+  ../Common/Message.h ../DataStr/Malloc.h ../DataStr/List.h \
+  ../DataStr/Tree.h ../DataStr/avl.h ../DataStr/Tools.h ../DataStr/List.h \
+  ../DataStr/Tree.h ../Common/GmshUI.h Draw.h ../Mesh/Mesh.h \
+  ../Mesh/Vertex.h ../Mesh/Element.h ../Mesh/Vertex.h ../Mesh/Simplex.h \
+  ../Mesh/Vertex.h ../Mesh/Element.h ../Mesh/Face.h ../Mesh/Vertex.h \
+  ../Mesh/Element.h ../Mesh/Edge.h ../Mesh/Vertex.h ../Mesh/Simplex.h \
+  ../Geo/ExtrudeParams.h ../Common/VertexArray.h \
+  ../Common/SmoothNormals.h ../Numeric/Numeric.h ../Mesh/Metric.h \
+  ../Mesh/Vertex.h ../Mesh/Simplex.h ../Mesh/Mesh.h ../Mesh/Matrix.h \
+  ../Common/Views.h ../Common/ColorTable.h ../Common/VertexArray.h \
+  ../Common/SmoothNormals.h ../Common/GmshMatrix.h \
+  ../Common/AdaptiveViews.h ../Common/GmshMatrix.h ../Common/Context.h
 # 1 "/Users/geuzaine/.gmsh/Graphics//"
-gl2yuv.o: gl2yuv.cpp ../Common/Gmsh.h ../Common/Message.h \
-  ../DataStr/Malloc.h ../DataStr/List.h ../DataStr/Tree.h \
-  ../DataStr/avl.h ../DataStr/Tools.h ../DataStr/List.h ../DataStr/Tree.h \
-  ../Common/GmshUI.h
+gl2yuv.o: gl2yuv.cpp gl2yuv.h PixelBuffer.h ../Common/Gmsh.h \
+  ../Common/Message.h ../DataStr/Malloc.h ../DataStr/List.h \
+  ../DataStr/Tree.h ../DataStr/avl.h ../DataStr/Tools.h ../DataStr/List.h \
+  ../DataStr/Tree.h ../Common/GmshUI.h Draw.h ../Mesh/Mesh.h \
+  ../Mesh/Vertex.h ../Mesh/Element.h ../Mesh/Vertex.h ../Mesh/Simplex.h \
+  ../Mesh/Vertex.h ../Mesh/Element.h ../Mesh/Face.h ../Mesh/Vertex.h \
+  ../Mesh/Element.h ../Mesh/Edge.h ../Mesh/Vertex.h ../Mesh/Simplex.h \
+  ../Geo/ExtrudeParams.h ../Common/VertexArray.h \
+  ../Common/SmoothNormals.h ../Numeric/Numeric.h ../Mesh/Metric.h \
+  ../Mesh/Vertex.h ../Mesh/Simplex.h ../Mesh/Mesh.h ../Mesh/Matrix.h \
+  ../Common/Views.h ../Common/ColorTable.h ../Common/VertexArray.h \
+  ../Common/SmoothNormals.h ../Common/GmshMatrix.h \
+  ../Common/AdaptiveViews.h ../Common/GmshMatrix.h ../Common/Context.h
diff --git a/Graphics/gl2gif.cpp b/Graphics/gl2gif.cpp
index 3d4fdd1f35..d1e00f8fda 100644
--- a/Graphics/gl2gif.cpp
+++ b/Graphics/gl2gif.cpp
@@ -1,4 +1,4 @@
-/* $Id: gl2gif.cpp,v 1.21 2003-11-04 17:10:29 geuzaine Exp $ */
+/* $Id: gl2gif.cpp,v 1.22 2006-05-17 01:19:06 geuzaine Exp $ */
 /*
  * GL2GIF, an OpenGL to GIF Printing Library
  * Copyright (C) 1999-2003 Christophe Geuzaine <geuz@geuz.org>
@@ -71,8 +71,6 @@
  *
  */
 
-#include "Gmsh.h"
-#include "GmshUI.h"
 #include "gl2gif.h"
 
 /* PPM colormap routines */
@@ -1172,7 +1170,7 @@ static void GIFEncode(FILE * fp,
 #define FS_SCALE   1024
 #define MAXCOL2    32767
 
-void create_gif(FILE * outfile, int width, int height,
+void create_gif(FILE * outfile, PixelBuffer *buffer,
                 int dither, int sort, int interlace,
                 int transparency, int bg_r, int bg_g, int bg_b)
 {
@@ -1181,7 +1179,6 @@ void create_gif(FILE * outfile, int width, int height,
   pixel transcolor;
   colorhist_vector chv, colormap;
   int BitsPerPixel, usehash;
-  unsigned char *RedBuffer, *GreenBuffer, *BlueBuffer;
   pixval maxval = MAXCOL2, newmaxval;
   colorhash_table cht;
   register pixel *pP;
@@ -1192,34 +1189,26 @@ void create_gif(FILE * outfile, int width, int height,
   register long sr = 0, sg = 0, sb = 0, err = 0;
   int fs_direction = 0;
 
-  /* This is stupid, but I couldn't figure out how to pack the data
-     directly from the OpenGL frame buffer into unsigned long
-     pixel[][] */
-
-  glPixelStorei(GL_PACK_ALIGNMENT, 1);
-  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-  RedBuffer = (unsigned char *)Malloc(height * width * sizeof(unsigned char));
-  GreenBuffer =
-    (unsigned char *)Malloc(height * width * sizeof(unsigned char));
-  BlueBuffer =
-    (unsigned char *)Malloc(height * width * sizeof(unsigned char));
-  glReadPixels(0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, RedBuffer);
-  glReadPixels(0, 0, width, height, GL_GREEN, GL_UNSIGNED_BYTE, GreenBuffer);
-  glReadPixels(0, 0, width, height, GL_BLUE, GL_UNSIGNED_BYTE, BlueBuffer);
+  int width = buffer->GetWidth();
+  int height = buffer->GetHeight();
+  int numcomp = buffer->GetNumComp();
+
+  if(numcomp != 3){
+    Msg(GERROR, "GIF only implemented for GL_RGB");
+    return;
+  }
 
   static_pixels = (pixel **) Malloc(height * sizeof(pixel *));
   for(i = 0; i < height; i++)
     static_pixels[i] = (pixel *) Malloc(3 * width * sizeof(pixel));
 
+  unsigned char *pixels = (unsigned char*)buffer->GetPixels();
   for(i = 0; i < height; i++)
     for(j = 0; j < width; j++)
       PPM_ASSIGN(static_pixels[height - 1 - i][j],
-                 RedBuffer[i * width + j],
-                 GreenBuffer[i * width + j], BlueBuffer[i * width + j]);
-
-  Free(RedBuffer);
-  Free(GreenBuffer);
-  Free(BlueBuffer);
+                 pixels[i * width * 3 + j * 3],
+                 pixels[i * width * 3 + j * 3 + 1],
+                 pixels[i * width * 3 + j * 3 + 2]);
 
   /* Try to compute color histogram */
 
diff --git a/Graphics/gl2gif.h b/Graphics/gl2gif.h
index 4e65ebe7e7..30e3f7e3f9 100644
--- a/Graphics/gl2gif.h
+++ b/Graphics/gl2gif.h
@@ -32,6 +32,7 @@
  */
 
 #include <stdio.h>
+#include "PixelBuffer.h"
 
 #define MAX_GIFCOLORS  256
 
@@ -80,7 +81,7 @@ typedef colorhist_list* colorhash_table;
 
 /* Public function */
 
-void create_gif(FILE *outfile, int width, int height, 
+void create_gif(FILE *outfile, PixelBuffer *buffer, 
 		int dither, int sort, int interlace, 
 		int transparency, int r, int g, int b);
 
diff --git a/Graphics/gl2jpeg.cpp b/Graphics/gl2jpeg.cpp
index b3166e69c6..e40f82b5a8 100644
--- a/Graphics/gl2jpeg.cpp
+++ b/Graphics/gl2jpeg.cpp
@@ -1,4 +1,4 @@
-/* $Id: gl2jpeg.cpp,v 1.26 2006-02-24 22:07:06 geuzaine Exp $ */
+/* $Id: gl2jpeg.cpp,v 1.27 2006-05-17 01:19:06 geuzaine Exp $ */
 /*
  * GL2JPEG, an OpenGL to JPEG Printing Library
  * Copyright (C) 1999-2003 Christophe Geuzaine <geuz@geuz.org>
@@ -29,13 +29,12 @@
  * to provide one.
  */
 
-#include "Gmsh.h"
-#include "GmshUI.h"
+#include "gl2jpeg.h"
+#undef EXTERN
 
 #if !defined(HAVE_LIBJPEG)
 
-void create_jpeg(FILE * outfile, int width, int height,
-		 int quality, int smoothing)
+void create_jpeg(FILE *outfile, PixelBuffer *buffer, int quality, int smoothing)
 {
   Msg(GERROR, "This version of Gmsh was compiled without JPEG support");
 }
@@ -67,24 +66,23 @@ void my_output_message(j_common_ptr cinfo)
   Msg(DEBUG, "%s", buffer);
 }
 
-void create_jpeg(FILE * outfile, int width, int height, 
-		 int quality, int smoothing)
+void create_jpeg(FILE *outfile, PixelBuffer *buffer, int quality, int smoothing)
 {
-  int i;
-  unsigned char *pixels;
+  if(buffer->GetFormat() != GL_RGB || buffer->GetType() != GL_UNSIGNED_BYTE){
+    Msg(GERROR, "JPEG only implemented for GL_RGB and GL_UNSIGNED_BYTE");
+    return;
+  }
+
   struct jpeg_compress_struct cinfo;
   struct jpeg_error_mgr jerr;
-  JSAMPROW row_pointer[1];
-  int row_stride;
-
   cinfo.err = jpeg_std_error(&jerr);
   cinfo.err->output_message = my_output_message;
 
   jpeg_create_compress(&cinfo);
   jpeg_stdio_dest(&cinfo, outfile);
-  cinfo.image_width = width;    // in pixels
-  cinfo.image_height = height;
-  cinfo.input_components = 3;   // 3 color components per pixel
+  cinfo.image_width = buffer->GetWidth();
+  cinfo.image_height = buffer->GetHeight();
+  cinfo.input_components = 3;
   cinfo.in_color_space = JCS_RGB;
   jpeg_set_defaults(&cinfo);
   jpeg_set_quality(&cinfo, quality, TRUE);
@@ -92,13 +90,10 @@ void create_jpeg(FILE * outfile, int width, int height,
   cinfo.smoothing_factor = smoothing;
   jpeg_start_compress(&cinfo, TRUE);
 
-  glPixelStorei(GL_PACK_ALIGNMENT, 1);
-  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-  pixels = (unsigned char *)Malloc(height * width * 3);
-  glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels);
-
-  row_stride = width * 3;
-  i = cinfo.image_height - 1;
+  unsigned char *pixels = (unsigned char*)buffer->GetPixels();
+  JSAMPROW row_pointer[1]; 
+  int row_stride = cinfo.image_width * cinfo.input_components;
+  int i = cinfo.image_height - 1;
   while(i >= 0) {
     row_pointer[0] = &pixels[i * row_stride];
     (void)jpeg_write_scanlines(&cinfo, row_pointer, 1);
@@ -106,8 +101,6 @@ void create_jpeg(FILE * outfile, int width, int height,
   }
   jpeg_finish_compress(&cinfo);
   jpeg_destroy_compress(&cinfo);
-
-  Free(pixels);
 }
 
 #endif
diff --git a/Graphics/gl2jpeg.h b/Graphics/gl2jpeg.h
index 95dae72651..92244f6069 100644
--- a/Graphics/gl2jpeg.h
+++ b/Graphics/gl2jpeg.h
@@ -32,8 +32,8 @@
  */
 
 #include <stdio.h>
+#include "PixelBuffer.h"
 
-void create_jpeg(FILE *outfile, int width, int height,
-		 int quality, int smoothing);
+void create_jpeg(FILE *outfile, PixelBuffer *buffer, int quality, int smoothing);
 
 #endif
diff --git a/Graphics/gl2png.cpp b/Graphics/gl2png.cpp
index 735dc60b1a..37cbf1f3c4 100644
--- a/Graphics/gl2png.cpp
+++ b/Graphics/gl2png.cpp
@@ -28,12 +28,11 @@
  * to provide one.
  */
 
-#include "Gmsh.h"
-#include "GmshUI.h"
+#include "gl2png.h"
 
 #if !defined(HAVE_LIBPNG)
 
-void create_png(FILE * file, int width, int height, int quality)
+void create_png(FILE *file, PixelBuffer *buffer, int quality)
 {
   Msg(GERROR, "This version of Gmsh was compiled without PNG support");
 }
@@ -46,33 +45,22 @@ void create_png(FILE * file, int width, int height, int quality)
 #  define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
 #endif
 
-/*
-  compression_level = Z_DEFAULT_COMPRESSION;
-  compression_level = Z_BEST_SPEED;
-  compression_level = Z_BEST_COMPRESSION;
-  compression_level = Z_NO_COMPRESSION;
-*/
-
-void create_png(FILE * file, int width, int height, int quality)
+void create_png(FILE *file, PixelBuffer *buffer, int quality)
 {
-  int row;
-  int compression_level = Z_DEFAULT_COMPRESSION;
-  png_structp png_ptr;
-  png_infop info_ptr;
-  png_text text_ptr[10];
-  unsigned char *pixels;
-  time_t now;
+  if((buffer->GetFormat() != GL_RGB && buffer->GetFormat() != GL_RGBA) ||
+     buffer->GetType() != GL_UNSIGNED_BYTE){
+    Msg(GERROR, "PNG only implemented for GL_RGB/GL_RGBA and GL_UNSIGNED_BYTE");
+    return;
+  }
 
-  time(&now);
-  
-  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+  png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
   
   if(png_ptr == NULL) {
     Msg(GERROR, "Could not create PNG write struct");
     return;
   }
   
-  info_ptr = png_create_info_struct(png_ptr);
+  png_infop info_ptr = png_create_info_struct(png_ptr);
 
   if(info_ptr == NULL) {
     png_destroy_write_struct(&png_ptr, NULL);
@@ -88,11 +76,18 @@ void create_png(FILE * file, int width, int height, int quality)
   
   png_init_io(png_ptr, file);
   
-  png_set_compression_level(png_ptr, compression_level);
+  int height = buffer->GetHeight();
+  int width = buffer->GetWidth();
+  int numcomp = buffer->GetNumComp();
 
-  png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
+  // Z_DEFAULT_COMPRESSION, Z_BEST_SPEED, Z_BEST_COMPRESSION, Z_NO_COMPRESSION
+  png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);
+  png_set_IHDR(png_ptr, info_ptr, width, height, 8, 
+	       (numcomp == 3) ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGBA,
 	       PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
-  
+  time_t now;
+  time(&now);
+  png_text text_ptr[10];  
   text_ptr[0].key = "Creator";
   text_ptr[0].text = "Gmsh";
   text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
@@ -100,22 +95,15 @@ void create_png(FILE * file, int width, int height, int quality)
   text_ptr[1].text = ctime(&now);
   text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
   png_set_text(png_ptr, info_ptr, text_ptr, 2);
-  
   png_write_info(png_ptr, info_ptr);
-  
-  glPixelStorei(GL_PACK_ALIGNMENT, 1);
-  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-  pixels = (unsigned char *)Malloc(width * 3 * sizeof(unsigned char));
-  for(row = height - 1; row >= 0; row--) {
-    glReadPixels(0, row, width, 1, GL_RGB, GL_UNSIGNED_BYTE, pixels);
-    png_write_row(png_ptr, (png_bytep)pixels);
-  }
-  Free(pixels);
 
+  unsigned char *pixels = (unsigned char *)buffer->GetPixels();
+  for(int row = height - 1; row >= 0; row--) {
+    unsigned char *row_pointer = &pixels[row * width * numcomp];
+    png_write_row(png_ptr, (png_bytep)row_pointer);
+  }
   png_write_end(png_ptr, info_ptr);
-  
   png_destroy_write_struct(&png_ptr, &info_ptr);
 }
 
 #endif
-
diff --git a/Graphics/gl2png.h b/Graphics/gl2png.h
index 18acdfa952..f71d99bb8f 100644
--- a/Graphics/gl2png.h
+++ b/Graphics/gl2png.h
@@ -32,7 +32,8 @@
  */
 
 #include <stdio.h>
+#include "PixelBuffer.h"
 
-void create_png(FILE *outfile, int width, int height, int quality);
+void create_png(FILE *outfile, PixelBuffer *buffer, int quality);
 
 #endif
diff --git a/Graphics/gl2ppm.cpp b/Graphics/gl2ppm.cpp
index 3005fb7398..585173e0cb 100644
--- a/Graphics/gl2ppm.cpp
+++ b/Graphics/gl2ppm.cpp
@@ -1,4 +1,4 @@
-/* $Id: gl2ppm.cpp,v 1.13 2003-11-04 17:10:29 geuzaine Exp $ */
+/* $Id: gl2ppm.cpp,v 1.14 2006-05-17 01:19:06 geuzaine Exp $ */
 /*
  * GL2PPM, an OpenGL to PPM Printing Library
  * Copyright (C) 1999-2003 Christophe Geuzaine <geuz@geuz.org>
@@ -29,29 +29,27 @@
  * to provide one.
  */
 
-#include "Gmsh.h"
-#include "GmshUI.h"
+#include "gl2ppm.h"
 
-void create_ppm(FILE * outfile, int width, int height)
+void create_ppm(FILE *outfile, PixelBuffer *buffer)
 {
-  unsigned char *pixels;
-  int i, row_stride;
+  if(buffer->GetFormat() != GL_RGB || buffer->GetType() != GL_UNSIGNED_BYTE){
+    Msg(GERROR, "PPM only implemented for GL_RGB and GL_UNSIGNED_BYTE");
+    return;
+  }
 
-  glPixelStorei(GL_PACK_ALIGNMENT, 1);
-  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-  pixels = (unsigned char *)Malloc(height * width * 3);
-  glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels);
+  int width = buffer->GetWidth();
+  int height = buffer->GetHeight();
+  unsigned char *pixels = (unsigned char*)buffer->GetPixels();
 
   fprintf(outfile, "P6\n");
   fprintf(outfile, "%d %d\n", width, height);
   fprintf(outfile, "%d\n", 255);
 
-  row_stride = width * 3;
-  i = height - 1;
+  int row_stride = width * 3;
+  int i = height - 1;
   while(i >= 0) {
     fwrite(&pixels[i * row_stride], 1, row_stride, outfile);
     i--;
   }
-
-  Free(pixels);
 }
diff --git a/Graphics/gl2ppm.h b/Graphics/gl2ppm.h
index f785379fc8..7d4c36c9f1 100644
--- a/Graphics/gl2ppm.h
+++ b/Graphics/gl2ppm.h
@@ -32,7 +32,8 @@
  */
 
 #include <stdio.h>
+#include "PixelBuffer.h"
 
-void create_ppm(FILE *outfile, int width, int height);
+void create_ppm(FILE *outfile, PixelBuffer *buffer);
 
 #endif
diff --git a/Graphics/gl2yuv.cpp b/Graphics/gl2yuv.cpp
index 09a0feb7ec..1bc0004e69 100644
--- a/Graphics/gl2yuv.cpp
+++ b/Graphics/gl2yuv.cpp
@@ -1,4 +1,4 @@
-/* $Id: gl2yuv.cpp,v 1.11 2003-11-04 17:10:29 geuzaine Exp $ */
+/* $Id: gl2yuv.cpp,v 1.12 2006-05-17 01:19:06 geuzaine Exp $ */
 /*
  * GL2YUV, an OpenGL to YUV Printing Library
  * Copyright (C) 1999-2003 Christophe Geuzaine <geuz@geuz.org>
@@ -56,11 +56,15 @@
  */
 
 
-#include "Gmsh.h"
-#include "GmshUI.h"
+#include "gl2yuv.h"
 
-void create_yuv(FILE * outfile, int width, int height)
+void create_yuv(FILE * outfile, PixelBuffer *buffer)
 {
+  if(buffer->GetFormat() != GL_RGB || buffer->GetType() != GL_UNSIGNED_BYTE){
+    Msg(GERROR, "YUV only implemented for GL_RGB and GL_UNSIGNED_BYTE");
+    return;
+  }
+
   register int x, y;
   register unsigned char *dy0, *dy1;
   register unsigned char *dcr, *dcb;
@@ -72,9 +76,7 @@ void create_yuv(FILE * outfile, int width, int height)
   static float mult16874[1024], mult33126[1024], mult5[1024];
   static float mult41869[1024], mult08131[1024];
 
-  unsigned char *pixels;
   unsigned char **orig_y, **orig_cr, **orig_cb;
-  int row_stride;
 
   if(first) {
     register int index;
@@ -96,15 +98,15 @@ void create_yuv(FILE * outfile, int width, int height)
     first = 0;
   }
 
+  int width = buffer->GetWidth();
+  int height = buffer->GetHeight();
+  unsigned char *pixels = (unsigned char *)buffer->GetPixels();
+  
   // yuv format assumes even number of rows and columns
   height -= height % 2;
   width -= width % 2;
 
-  glPixelStorei(GL_PACK_ALIGNMENT, 1);
-  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-  pixels = (unsigned char *)Malloc(height * width * 3);
-  glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels);
-  row_stride = width * 3;
+  int row_stride = width * 3;
 
   orig_y = (unsigned char **)Malloc(sizeof(unsigned char *) * height);
   for(y = 0; y < height; y++) {
@@ -186,8 +188,6 @@ void create_yuv(FILE * outfile, int width, int height)
   for(y = height / 2 - 1; y >= 0; y--)
     fwrite(orig_cr[y], 1, width / 2, outfile);
 
-  Free(pixels);
-
   for(y = 0; y < height; y++)
     Free(orig_y[y]);
   Free(orig_y);
diff --git a/Graphics/gl2yuv.h b/Graphics/gl2yuv.h
index 87e0707eb1..3d35c82249 100644
--- a/Graphics/gl2yuv.h
+++ b/Graphics/gl2yuv.h
@@ -32,7 +32,8 @@
  */
 
 #include <stdio.h>
+#include "PixelBuffer.h"
 
-void create_yuv(FILE *outfile, int width, int height);
+void create_yuv(FILE *outfile, PixelBuffer *buffer);
 
 #endif
diff --git a/Parser/Gmsh.tab.cpp b/Parser/Gmsh.tab.cpp
index a6553d5cb4..0065eaafb3 100644
--- a/Parser/Gmsh.tab.cpp
+++ b/Parser/Gmsh.tab.cpp
@@ -126,7 +126,7 @@
 
 #line 1 "Gmsh.y"
 
-// $Id: Gmsh.tab.cpp,v 1.265 2006-04-04 04:35:00 geuzaine Exp $
+// $Id: Gmsh.tab.cpp,v 1.266 2006-05-17 01:19:06 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -518,27 +518,27 @@ static const short yyrline[] = { 0,
   1287,  1306,  1325,  1364,  1389,  1408,  1427,  1443,  1463,  1480,
   1497,  1517,  1523,  1528,  1533,  1540,  1542,  1543,  1546,  1551,
   1555,  1571,  1587,  1603,  1623,  1638,  1644,  1650,  1661,  1671,
-  1681,  1695,  1713,  1727,  1736,  1742,  1753,  1766,  1811,  1826,
-  1837,  1856,  1866,  1888,  1892,  1897,  1902,  1913,  1930,  1946,
-  1972,  1999,  2031,  2038,  2043,  2049,  2053,  2061,  2070,  2078,
-  2086,  2091,  2099,  2104,  2112,  2117,  2127,  2134,  2141,  2148,
-  2155,  2162,  2169,  2176,  2183,  2190,  2195,  2202,  2207,  2214,
-  2219,  2226,  2231,  2238,  2243,  2250,  2255,  2262,  2267,  2274,
-  2279,  2286,  2291,  2301,  2305,  2310,  2337,  2361,  2369,  2388,
-  2406,  2424,  2453,  2488,  2515,  2542,  2556,  2574,  2579,  2588,
-  2590,  2591,  2592,  2593,  2594,  2595,  2596,  2597,  2604,  2605,
-  2606,  2607,  2608,  2609,  2610,  2611,  2612,  2613,  2614,  2615,
-  2616,  2617,  2618,  2619,  2620,  2621,  2622,  2623,  2624,  2625,
-  2626,  2627,  2628,  2629,  2630,  2631,  2632,  2633,  2634,  2635,
-  2637,  2638,  2639,  2640,  2641,  2642,  2643,  2644,  2645,  2646,
-  2647,  2648,  2649,  2650,  2651,  2652,  2653,  2654,  2655,  2656,
-  2657,  2662,  2667,  2668,  2669,  2670,  2671,  2672,  2676,  2689,
-  2709,  2723,  2736,  2759,  2777,  2795,  2813,  2831,  2838,  2843,
-  2847,  2851,  2855,  2861,  2866,  2870,  2874,  2880,  2884,  2888,
-  2894,  2900,  2907,  2913,  2917,  2922,  2926,  2937,  2944,  2955,
-  2975,  2985,  2995,  3005,  3022,  3041,  3065,  3093,  3099,  3103,
-  3107,  3119,  3124,  3136,  3143,  3164,  3169,  3183,  3189,  3195,
-  3200,  3208,  3216,  3230,  3244,  3248,  3267,  3289
+  1681,  1695,  1713,  1727,  1736,  1742,  1753,  1766,  1809,  1824,
+  1835,  1854,  1864,  1886,  1890,  1895,  1900,  1910,  1927,  1943,
+  1969,  1996,  2028,  2035,  2040,  2046,  2050,  2058,  2067,  2075,
+  2083,  2088,  2096,  2101,  2109,  2114,  2124,  2131,  2138,  2145,
+  2152,  2159,  2166,  2173,  2180,  2187,  2192,  2199,  2204,  2211,
+  2216,  2223,  2228,  2235,  2240,  2247,  2252,  2259,  2264,  2271,
+  2276,  2283,  2288,  2298,  2302,  2307,  2334,  2358,  2366,  2385,
+  2403,  2421,  2450,  2485,  2512,  2539,  2553,  2571,  2576,  2585,
+  2587,  2588,  2589,  2590,  2591,  2592,  2593,  2594,  2601,  2602,
+  2603,  2604,  2605,  2606,  2607,  2608,  2609,  2610,  2611,  2612,
+  2613,  2614,  2615,  2616,  2617,  2618,  2619,  2620,  2621,  2622,
+  2623,  2624,  2625,  2626,  2627,  2628,  2629,  2630,  2631,  2632,
+  2634,  2635,  2636,  2637,  2638,  2639,  2640,  2641,  2642,  2643,
+  2644,  2645,  2646,  2647,  2648,  2649,  2650,  2651,  2652,  2653,
+  2654,  2659,  2664,  2665,  2666,  2667,  2668,  2669,  2673,  2686,
+  2706,  2720,  2733,  2756,  2774,  2792,  2810,  2828,  2835,  2840,
+  2844,  2848,  2852,  2858,  2863,  2867,  2871,  2877,  2881,  2885,
+  2891,  2897,  2904,  2910,  2914,  2919,  2923,  2934,  2941,  2952,
+  2972,  2982,  2992,  3002,  3019,  3038,  3062,  3090,  3096,  3100,
+  3104,  3116,  3121,  3133,  3140,  3161,  3166,  3180,  3186,  3192,
+  3197,  3205,  3213,  3227,  3241,  3245,  3264,  3286
 };
 #endif
 
@@ -4441,11 +4441,9 @@ case 128:
       }
       else if(!strcmp(yyvsp[-2].c, "Print")){
 #if defined(HAVE_FLTK)
-	if(!CTX.batch){
-	  char tmpstring[1024];
-	  FixRelativePath(yyvsp[-1].c, tmpstring);
-	  CreateOutputFile(tmpstring, CTX.print.format);
-	}
+	char tmpstring[1024];
+	FixRelativePath(yyvsp[-1].c, tmpstring);
+	CreateOutputFile(tmpstring, CTX.print.format);
 #endif
       }
       else if(!strcmp(yyvsp[-2].c, "Save")){
@@ -4471,7 +4469,7 @@ case 128:
     ;
     break;}
 case 129:
-#line 1812 "Gmsh.y"
+#line 1810 "Gmsh.y"
 {
       if(!strcmp(yyvsp[-6].c, "Save") && !strcmp(yyvsp[-5].c, "View")){
 	Post_View **vv = (Post_View **)List_Pointer_Test(CTX.post.list, (int)yyvsp[-3].d);
@@ -4488,7 +4486,7 @@ case 129:
     ;
     break;}
 case 130:
-#line 1827 "Gmsh.y"
+#line 1825 "Gmsh.y"
 {
       if(!strcmp(yyvsp[-6].c, "Background") && !strcmp(yyvsp[-5].c, "Mesh")  && !strcmp(yyvsp[-4].c, "View")){
 	Post_View **vv = (Post_View **)List_Pointer_Test(CTX.post.list, (int)yyvsp[-2].d);
@@ -4501,7 +4499,7 @@ case 130:
     ;
     break;}
 case 131:
-#line 1838 "Gmsh.y"
+#line 1836 "Gmsh.y"
 {
       if(!strcmp(yyvsp[-2].c, "Sleep")){
 	SleepInSeconds(yyvsp[-1].d);
@@ -4522,7 +4520,7 @@ case 131:
     ;
     break;}
 case 132:
-#line 1857 "Gmsh.y"
+#line 1855 "Gmsh.y"
 {
        try {
 	 GMSH_PluginManager::instance()->action(yyvsp[-4].c, yyvsp[-1].c, 0);
@@ -4534,7 +4532,7 @@ case 132:
      ;
     break;}
 case 133:
-#line 1867 "Gmsh.y"
+#line 1865 "Gmsh.y"
 {
       if(!strcmp(yyvsp[-1].c, "ElementsFromAllViews"))
 	CombineViews(0, 1, CTX.post.combine_remove_orig);
@@ -4558,36 +4556,35 @@ case 133:
     ;
     break;}
 case 134:
-#line 1889 "Gmsh.y"
+#line 1887 "Gmsh.y"
 {
       exit(0);
     ;
     break;}
 case 135:
-#line 1893 "Gmsh.y"
+#line 1891 "Gmsh.y"
 {
       CTX.forced_bbox = 0;
       SetBoundingBox();
     ;
     break;}
 case 136:
-#line 1898 "Gmsh.y"
+#line 1896 "Gmsh.y"
 {
       CTX.forced_bbox = 1;
       SetBoundingBox(yyvsp[-12].d, yyvsp[-10].d, yyvsp[-8].d, yyvsp[-6].d, yyvsp[-4].d, yyvsp[-2].d);
     ;
     break;}
 case 137:
-#line 1903 "Gmsh.y"
+#line 1901 "Gmsh.y"
 {
 #if defined(HAVE_FLTK)
-      if(!CTX.batch) // we're in interactive mode
-	Draw();
+      Draw();
 #endif
     ;
     break;}
 case 138:
-#line 1916 "Gmsh.y"
+#line 1913 "Gmsh.y"
 {
       LoopControlVariablesTab[ImbricatedLoop][0] = yyvsp[-3].d;
       LoopControlVariablesTab[ImbricatedLoop][1] = yyvsp[-1].d;
@@ -4604,7 +4601,7 @@ case 138:
     ;
     break;}
 case 139:
-#line 1931 "Gmsh.y"
+#line 1928 "Gmsh.y"
 {
       LoopControlVariablesTab[ImbricatedLoop][0] = yyvsp[-5].d;
       LoopControlVariablesTab[ImbricatedLoop][1] = yyvsp[-3].d;
@@ -4622,7 +4619,7 @@ case 139:
     ;
     break;}
 case 140:
-#line 1947 "Gmsh.y"
+#line 1944 "Gmsh.y"
 {
       LoopControlVariablesTab[ImbricatedLoop][0] = yyvsp[-3].d;
       LoopControlVariablesTab[ImbricatedLoop][1] = yyvsp[-1].d;
@@ -4650,7 +4647,7 @@ case 140:
     ;
     break;}
 case 141:
-#line 1973 "Gmsh.y"
+#line 1970 "Gmsh.y"
 {
       LoopControlVariablesTab[ImbricatedLoop][0] = yyvsp[-5].d;
       LoopControlVariablesTab[ImbricatedLoop][1] = yyvsp[-3].d;
@@ -4679,7 +4676,7 @@ case 141:
     ;
     break;}
 case 142:
-#line 2000 "Gmsh.y"
+#line 1997 "Gmsh.y"
 {
       if(ImbricatedLoop <= 0){
 	yymsg(GERROR, "Invalid For/EndFor loop");
@@ -4713,7 +4710,7 @@ case 142:
     ;
     break;}
 case 143:
-#line 2032 "Gmsh.y"
+#line 2029 "Gmsh.y"
 {
       if(!FunctionManager::Instance()->createFunction(yyvsp[0].c, yyin, yyname, yylineno))
 	yymsg(GERROR, "Redefinition of function %s", yyvsp[0].c);
@@ -4722,14 +4719,14 @@ case 143:
     ;
     break;}
 case 144:
-#line 2039 "Gmsh.y"
+#line 2036 "Gmsh.y"
 {
       if(!FunctionManager::Instance()->leaveFunction(&yyin, yyname, yylineno))
 	yymsg(GERROR, "Error while exiting function");
     ;
     break;}
 case 145:
-#line 2044 "Gmsh.y"
+#line 2041 "Gmsh.y"
 {
       if(!FunctionManager::Instance()->enterFunction(yyvsp[-1].c, &yyin, yyname, yylineno))
 	yymsg(GERROR, "Unknown function %s", yyvsp[-1].c);
@@ -4737,18 +4734,18 @@ case 145:
     ;
     break;}
 case 146:
-#line 2050 "Gmsh.y"
+#line 2047 "Gmsh.y"
 {
       if(!yyvsp[-1].d) skip_until("If", "EndIf");
     ;
     break;}
 case 147:
-#line 2054 "Gmsh.y"
+#line 2051 "Gmsh.y"
 {
     ;
     break;}
 case 148:
-#line 2063 "Gmsh.y"
+#line 2060 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShapes(TRANSLATE, yyvsp[-1].l, 
@@ -4758,7 +4755,7 @@ case 148:
     ;
     break;}
 case 149:
-#line 2071 "Gmsh.y"
+#line 2068 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShapes(ROTATE, yyvsp[-1].l, 
@@ -4768,7 +4765,7 @@ case 149:
     ;
     break;}
 case 150:
-#line 2079 "Gmsh.y"
+#line 2076 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShapes(TRANSLATE_ROTATE, yyvsp[-1].l, 
@@ -4778,14 +4775,14 @@ case 150:
     ;
     break;}
 case 151:
-#line 2087 "Gmsh.y"
+#line 2084 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 152:
-#line 2092 "Gmsh.y"
+#line 2089 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShapes(TRANSLATE, yyvsp[-3].l, 
@@ -4795,14 +4792,14 @@ case 152:
     ;
     break;}
 case 153:
-#line 2100 "Gmsh.y"
+#line 2097 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 154:
-#line 2105 "Gmsh.y"
+#line 2102 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShapes(ROTATE, yyvsp[-3].l, 
@@ -4812,14 +4809,14 @@ case 154:
     ;
     break;}
 case 155:
-#line 2113 "Gmsh.y"
+#line 2110 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 156:
-#line 2118 "Gmsh.y"
+#line 2115 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShapes(TRANSLATE_ROTATE, yyvsp[-3].l, 
@@ -4829,7 +4826,7 @@ case 156:
     ;
     break;}
 case 157:
-#line 2128 "Gmsh.y"
+#line 2125 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE, MSH_POINT, (int)yyvsp[-4].d, 
@@ -4838,7 +4835,7 @@ case 157:
     ;
     break;}
 case 158:
-#line 2135 "Gmsh.y"
+#line 2132 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE, MSH_SEGM_LINE, (int)yyvsp[-4].d, 
@@ -4847,7 +4844,7 @@ case 158:
     ;
     break;}
 case 159:
-#line 2142 "Gmsh.y"
+#line 2139 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE, MSH_SURF_PLAN, (int)yyvsp[-4].d, 
@@ -4856,7 +4853,7 @@ case 159:
     ;
     break;}
 case 160:
-#line 2149 "Gmsh.y"
+#line 2146 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(ROTATE, MSH_POINT, (int)yyvsp[-8].d, 
@@ -4865,7 +4862,7 @@ case 160:
     ;
     break;}
 case 161:
-#line 2156 "Gmsh.y"
+#line 2153 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(ROTATE, MSH_SEGM_LINE, (int)yyvsp[-8].d, 
@@ -4874,7 +4871,7 @@ case 161:
     ;
     break;}
 case 162:
-#line 2163 "Gmsh.y"
+#line 2160 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(ROTATE, MSH_SURF_PLAN, (int)yyvsp[-8].d, 
@@ -4883,7 +4880,7 @@ case 162:
     ;
     break;}
 case 163:
-#line 2170 "Gmsh.y"
+#line 2167 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE_ROTATE, MSH_POINT, (int)yyvsp[-10].d, 
@@ -4892,7 +4889,7 @@ case 163:
     ;
     break;}
 case 164:
-#line 2177 "Gmsh.y"
+#line 2174 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE_ROTATE, MSH_SEGM_LINE, (int)yyvsp[-10].d, 
@@ -4901,7 +4898,7 @@ case 164:
     ;
     break;}
 case 165:
-#line 2184 "Gmsh.y"
+#line 2181 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE_ROTATE, MSH_SURF_PLAN, (int)yyvsp[-10].d, 
@@ -4910,14 +4907,14 @@ case 165:
     ;
     break;}
 case 166:
-#line 2191 "Gmsh.y"
+#line 2188 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 167:
-#line 2196 "Gmsh.y"
+#line 2193 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE, MSH_POINT, (int)yyvsp[-8].d, 
@@ -4926,14 +4923,14 @@ case 167:
     ;
     break;}
 case 168:
-#line 2203 "Gmsh.y"
+#line 2200 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 169:
-#line 2208 "Gmsh.y"
+#line 2205 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE, MSH_SEGM_LINE, (int)yyvsp[-8].d, 
@@ -4942,14 +4939,14 @@ case 169:
     ;
     break;}
 case 170:
-#line 2215 "Gmsh.y"
+#line 2212 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 171:
-#line 2220 "Gmsh.y"
+#line 2217 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE, MSH_SURF_PLAN, (int)yyvsp[-8].d, 
@@ -4958,14 +4955,14 @@ case 171:
     ;
     break;}
 case 172:
-#line 2227 "Gmsh.y"
+#line 2224 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 173:
-#line 2232 "Gmsh.y"
+#line 2229 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(ROTATE, MSH_POINT, (int)yyvsp[-12].d, 
@@ -4974,14 +4971,14 @@ case 173:
     ;
     break;}
 case 174:
-#line 2239 "Gmsh.y"
+#line 2236 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 175:
-#line 2244 "Gmsh.y"
+#line 2241 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(ROTATE, MSH_SEGM_LINE, (int)yyvsp[-12].d, 
@@ -4990,14 +4987,14 @@ case 175:
     ;
     break;}
 case 176:
-#line 2251 "Gmsh.y"
+#line 2248 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 177:
-#line 2256 "Gmsh.y"
+#line 2253 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(ROTATE, MSH_SURF_PLAN, (int)yyvsp[-12].d, 
@@ -5006,14 +5003,14 @@ case 177:
     ;
     break;}
 case 178:
-#line 2263 "Gmsh.y"
+#line 2260 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 179:
-#line 2268 "Gmsh.y"
+#line 2265 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE_ROTATE, MSH_POINT, (int)yyvsp[-14].d, 
@@ -5022,14 +5019,14 @@ case 179:
     ;
     break;}
 case 180:
-#line 2275 "Gmsh.y"
+#line 2272 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 181:
-#line 2280 "Gmsh.y"
+#line 2277 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE_ROTATE, MSH_SEGM_LINE, (int)yyvsp[-14].d, 
@@ -5038,14 +5035,14 @@ case 181:
     ;
     break;}
 case 182:
-#line 2287 "Gmsh.y"
+#line 2284 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 183:
-#line 2292 "Gmsh.y"
+#line 2289 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE_ROTATE, MSH_SURF_PLAN, (int)yyvsp[-14].d, 
@@ -5054,17 +5051,17 @@ case 183:
     ;
     break;}
 case 184:
-#line 2303 "Gmsh.y"
+#line 2300 "Gmsh.y"
 {
     ;
     break;}
 case 185:
-#line 2306 "Gmsh.y"
+#line 2303 "Gmsh.y"
 {
     ;
     break;}
 case 186:
-#line 2312 "Gmsh.y"
+#line 2309 "Gmsh.y"
 {
       double d;
       extr.mesh.ExtrudeMesh = true;
@@ -5092,7 +5089,7 @@ case 186:
     ;
     break;}
 case 187:
-#line 2338 "Gmsh.y"
+#line 2335 "Gmsh.y"
 {
       double d;
       extr.mesh.ExtrudeMesh = true;
@@ -5118,13 +5115,13 @@ case 187:
     ;
     break;}
 case 188:
-#line 2362 "Gmsh.y"
+#line 2359 "Gmsh.y"
 {
       extr.mesh.Recombine = true;
     ;
     break;}
 case 189:
-#line 2371 "Gmsh.y"
+#line 2368 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-3].l); i++){
 	double d;
@@ -5144,7 +5141,7 @@ case 189:
     ;
     break;}
 case 190:
-#line 2389 "Gmsh.y"
+#line 2386 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-6].l); i++){
 	double d;
@@ -5164,7 +5161,7 @@ case 190:
     ;
     break;}
 case 191:
-#line 2407 "Gmsh.y"
+#line 2404 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-6].l); i++){
 	double d;
@@ -5184,7 +5181,7 @@ case 191:
     ;
     break;}
 case 192:
-#line 2425 "Gmsh.y"
+#line 2422 "Gmsh.y"
 {
       Surface *s = FindSurface((int)yyvsp[-4].d, THEM);
       if(!s)
@@ -5215,7 +5212,7 @@ case 192:
     ;
     break;}
 case 193:
-#line 2454 "Gmsh.y"
+#line 2451 "Gmsh.y"
 {
       Surface *s = FindSurface((int)yyvsp[-5].d, THEM);
       if(!s)
@@ -5252,7 +5249,7 @@ case 193:
     ;
     break;}
 case 194:
-#line 2489 "Gmsh.y"
+#line 2486 "Gmsh.y"
 {
       Surface *s = FindSurface((int)yyvsp[-4].d, THEM);
       if(!s)
@@ -5281,7 +5278,7 @@ case 194:
     ;
     break;}
 case 195:
-#line 2516 "Gmsh.y"
+#line 2513 "Gmsh.y"
 {
       Volume *v = FindVolume((int)yyvsp[-4].d, THEM);
       if(!v)
@@ -5310,7 +5307,7 @@ case 195:
     ;
     break;}
 case 196:
-#line 2543 "Gmsh.y"
+#line 2540 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-3].l); i++){
 	double d;
@@ -5326,7 +5323,7 @@ case 196:
     ;
     break;}
 case 197:
-#line 2557 "Gmsh.y"
+#line 2554 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-1].l); i++){
 	double d;
@@ -5341,51 +5338,51 @@ case 197:
     ;
     break;}
 case 198:
-#line 2576 "Gmsh.y"
+#line 2573 "Gmsh.y"
 { 
       ReplaceAllDuplicates(THEM);
     ;
     break;}
 case 199:
-#line 2580 "Gmsh.y"
+#line 2577 "Gmsh.y"
 { 
       IntersectAllSegmentsTogether();
     ;
     break;}
 case 200:
-#line 2589 "Gmsh.y"
+#line 2586 "Gmsh.y"
 { yyval.d = yyvsp[0].d;           ;
     break;}
 case 201:
-#line 2590 "Gmsh.y"
+#line 2587 "Gmsh.y"
 { yyval.d = yyvsp[-1].d;           ;
     break;}
 case 202:
-#line 2591 "Gmsh.y"
+#line 2588 "Gmsh.y"
 { yyval.d = -yyvsp[0].d;          ;
     break;}
 case 203:
-#line 2592 "Gmsh.y"
+#line 2589 "Gmsh.y"
 { yyval.d = yyvsp[0].d;           ;
     break;}
 case 204:
-#line 2593 "Gmsh.y"
+#line 2590 "Gmsh.y"
 { yyval.d = !yyvsp[0].d;          ;
     break;}
 case 205:
-#line 2594 "Gmsh.y"
+#line 2591 "Gmsh.y"
 { yyval.d = yyvsp[-2].d - yyvsp[0].d;      ;
     break;}
 case 206:
-#line 2595 "Gmsh.y"
+#line 2592 "Gmsh.y"
 { yyval.d = yyvsp[-2].d + yyvsp[0].d;      ;
     break;}
 case 207:
-#line 2596 "Gmsh.y"
+#line 2593 "Gmsh.y"
 { yyval.d = yyvsp[-2].d * yyvsp[0].d;      ;
     break;}
 case 208:
-#line 2598 "Gmsh.y"
+#line 2595 "Gmsh.y"
 { 
       if(!yyvsp[0].d)
 	yymsg(GERROR, "Division by zero in '%g / %g'", yyvsp[-2].d, yyvsp[0].d);
@@ -5394,247 +5391,247 @@ case 208:
     ;
     break;}
 case 209:
-#line 2604 "Gmsh.y"
+#line 2601 "Gmsh.y"
 { yyval.d = (int)yyvsp[-2].d % (int)yyvsp[0].d;  ;
     break;}
 case 210:
-#line 2605 "Gmsh.y"
+#line 2602 "Gmsh.y"
 { yyval.d = pow(yyvsp[-2].d, yyvsp[0].d);  ;
     break;}
 case 211:
-#line 2606 "Gmsh.y"
+#line 2603 "Gmsh.y"
 { yyval.d = yyvsp[-2].d < yyvsp[0].d;      ;
     break;}
 case 212:
-#line 2607 "Gmsh.y"
+#line 2604 "Gmsh.y"
 { yyval.d = yyvsp[-2].d > yyvsp[0].d;      ;
     break;}
 case 213:
-#line 2608 "Gmsh.y"
+#line 2605 "Gmsh.y"
 { yyval.d = yyvsp[-2].d <= yyvsp[0].d;     ;
     break;}
 case 214:
-#line 2609 "Gmsh.y"
+#line 2606 "Gmsh.y"
 { yyval.d = yyvsp[-2].d >= yyvsp[0].d;     ;
     break;}
 case 215:
-#line 2610 "Gmsh.y"
+#line 2607 "Gmsh.y"
 { yyval.d = yyvsp[-2].d == yyvsp[0].d;     ;
     break;}
 case 216:
-#line 2611 "Gmsh.y"
+#line 2608 "Gmsh.y"
 { yyval.d = yyvsp[-2].d != yyvsp[0].d;     ;
     break;}
 case 217:
-#line 2612 "Gmsh.y"
+#line 2609 "Gmsh.y"
 { yyval.d = yyvsp[-2].d && yyvsp[0].d;     ;
     break;}
 case 218:
-#line 2613 "Gmsh.y"
+#line 2610 "Gmsh.y"
 { yyval.d = yyvsp[-2].d || yyvsp[0].d;     ;
     break;}
 case 219:
-#line 2614 "Gmsh.y"
+#line 2611 "Gmsh.y"
 { yyval.d = yyvsp[-4].d? yyvsp[-2].d : yyvsp[0].d;  ;
     break;}
 case 220:
-#line 2615 "Gmsh.y"
+#line 2612 "Gmsh.y"
 { yyval.d = exp(yyvsp[-1].d);      ;
     break;}
 case 221:
-#line 2616 "Gmsh.y"
+#line 2613 "Gmsh.y"
 { yyval.d = log(yyvsp[-1].d);      ;
     break;}
 case 222:
-#line 2617 "Gmsh.y"
+#line 2614 "Gmsh.y"
 { yyval.d = log10(yyvsp[-1].d);    ;
     break;}
 case 223:
-#line 2618 "Gmsh.y"
+#line 2615 "Gmsh.y"
 { yyval.d = sqrt(yyvsp[-1].d);     ;
     break;}
 case 224:
-#line 2619 "Gmsh.y"
+#line 2616 "Gmsh.y"
 { yyval.d = sin(yyvsp[-1].d);      ;
     break;}
 case 225:
-#line 2620 "Gmsh.y"
+#line 2617 "Gmsh.y"
 { yyval.d = asin(yyvsp[-1].d);     ;
     break;}
 case 226:
-#line 2621 "Gmsh.y"
+#line 2618 "Gmsh.y"
 { yyval.d = cos(yyvsp[-1].d);      ;
     break;}
 case 227:
-#line 2622 "Gmsh.y"
+#line 2619 "Gmsh.y"
 { yyval.d = acos(yyvsp[-1].d);     ;
     break;}
 case 228:
-#line 2623 "Gmsh.y"
+#line 2620 "Gmsh.y"
 { yyval.d = tan(yyvsp[-1].d);      ;
     break;}
 case 229:
-#line 2624 "Gmsh.y"
+#line 2621 "Gmsh.y"
 { yyval.d = atan(yyvsp[-1].d);     ;
     break;}
 case 230:
-#line 2625 "Gmsh.y"
+#line 2622 "Gmsh.y"
 { yyval.d = atan2(yyvsp[-3].d, yyvsp[-1].d);;
     break;}
 case 231:
-#line 2626 "Gmsh.y"
+#line 2623 "Gmsh.y"
 { yyval.d = sinh(yyvsp[-1].d);     ;
     break;}
 case 232:
-#line 2627 "Gmsh.y"
+#line 2624 "Gmsh.y"
 { yyval.d = cosh(yyvsp[-1].d);     ;
     break;}
 case 233:
-#line 2628 "Gmsh.y"
+#line 2625 "Gmsh.y"
 { yyval.d = tanh(yyvsp[-1].d);     ;
     break;}
 case 234:
-#line 2629 "Gmsh.y"
+#line 2626 "Gmsh.y"
 { yyval.d = fabs(yyvsp[-1].d);     ;
     break;}
 case 235:
-#line 2630 "Gmsh.y"
+#line 2627 "Gmsh.y"
 { yyval.d = floor(yyvsp[-1].d);    ;
     break;}
 case 236:
-#line 2631 "Gmsh.y"
+#line 2628 "Gmsh.y"
 { yyval.d = ceil(yyvsp[-1].d);     ;
     break;}
 case 237:
-#line 2632 "Gmsh.y"
+#line 2629 "Gmsh.y"
 { yyval.d = fmod(yyvsp[-3].d, yyvsp[-1].d); ;
     break;}
 case 238:
-#line 2633 "Gmsh.y"
+#line 2630 "Gmsh.y"
 { yyval.d = fmod(yyvsp[-3].d, yyvsp[-1].d); ;
     break;}
 case 239:
-#line 2634 "Gmsh.y"
+#line 2631 "Gmsh.y"
 { yyval.d = sqrt(yyvsp[-3].d*yyvsp[-3].d+yyvsp[-1].d*yyvsp[-1].d); ;
     break;}
 case 240:
-#line 2635 "Gmsh.y"
+#line 2632 "Gmsh.y"
 { yyval.d = yyvsp[-1].d*(double)rand()/(double)RAND_MAX; ;
     break;}
 case 241:
-#line 2637 "Gmsh.y"
+#line 2634 "Gmsh.y"
 { yyval.d = exp(yyvsp[-1].d);      ;
     break;}
 case 242:
-#line 2638 "Gmsh.y"
+#line 2635 "Gmsh.y"
 { yyval.d = log(yyvsp[-1].d);      ;
     break;}
 case 243:
-#line 2639 "Gmsh.y"
+#line 2636 "Gmsh.y"
 { yyval.d = log10(yyvsp[-1].d);    ;
     break;}
 case 244:
-#line 2640 "Gmsh.y"
+#line 2637 "Gmsh.y"
 { yyval.d = sqrt(yyvsp[-1].d);     ;
     break;}
 case 245:
-#line 2641 "Gmsh.y"
+#line 2638 "Gmsh.y"
 { yyval.d = sin(yyvsp[-1].d);      ;
     break;}
 case 246:
-#line 2642 "Gmsh.y"
+#line 2639 "Gmsh.y"
 { yyval.d = asin(yyvsp[-1].d);     ;
     break;}
 case 247:
-#line 2643 "Gmsh.y"
+#line 2640 "Gmsh.y"
 { yyval.d = cos(yyvsp[-1].d);      ;
     break;}
 case 248:
-#line 2644 "Gmsh.y"
+#line 2641 "Gmsh.y"
 { yyval.d = acos(yyvsp[-1].d);     ;
     break;}
 case 249:
-#line 2645 "Gmsh.y"
+#line 2642 "Gmsh.y"
 { yyval.d = tan(yyvsp[-1].d);      ;
     break;}
 case 250:
-#line 2646 "Gmsh.y"
+#line 2643 "Gmsh.y"
 { yyval.d = atan(yyvsp[-1].d);     ;
     break;}
 case 251:
-#line 2647 "Gmsh.y"
+#line 2644 "Gmsh.y"
 { yyval.d = atan2(yyvsp[-3].d, yyvsp[-1].d);;
     break;}
 case 252:
-#line 2648 "Gmsh.y"
+#line 2645 "Gmsh.y"
 { yyval.d = sinh(yyvsp[-1].d);     ;
     break;}
 case 253:
-#line 2649 "Gmsh.y"
+#line 2646 "Gmsh.y"
 { yyval.d = cosh(yyvsp[-1].d);     ;
     break;}
 case 254:
-#line 2650 "Gmsh.y"
+#line 2647 "Gmsh.y"
 { yyval.d = tanh(yyvsp[-1].d);     ;
     break;}
 case 255:
-#line 2651 "Gmsh.y"
+#line 2648 "Gmsh.y"
 { yyval.d = fabs(yyvsp[-1].d);     ;
     break;}
 case 256:
-#line 2652 "Gmsh.y"
+#line 2649 "Gmsh.y"
 { yyval.d = floor(yyvsp[-1].d);    ;
     break;}
 case 257:
-#line 2653 "Gmsh.y"
+#line 2650 "Gmsh.y"
 { yyval.d = ceil(yyvsp[-1].d);     ;
     break;}
 case 258:
-#line 2654 "Gmsh.y"
+#line 2651 "Gmsh.y"
 { yyval.d = fmod(yyvsp[-3].d, yyvsp[-1].d); ;
     break;}
 case 259:
-#line 2655 "Gmsh.y"
+#line 2652 "Gmsh.y"
 { yyval.d = fmod(yyvsp[-3].d, yyvsp[-1].d); ;
     break;}
 case 260:
-#line 2656 "Gmsh.y"
+#line 2653 "Gmsh.y"
 { yyval.d = sqrt(yyvsp[-3].d*yyvsp[-3].d+yyvsp[-1].d*yyvsp[-1].d); ;
     break;}
 case 261:
-#line 2657 "Gmsh.y"
+#line 2654 "Gmsh.y"
 { yyval.d = yyvsp[-1].d*(double)rand()/(double)RAND_MAX; ;
     break;}
 case 262:
-#line 2666 "Gmsh.y"
+#line 2663 "Gmsh.y"
 { yyval.d = yyvsp[0].d; ;
     break;}
 case 263:
-#line 2667 "Gmsh.y"
+#line 2664 "Gmsh.y"
 { yyval.d = 3.141592653589793; ;
     break;}
 case 264:
-#line 2668 "Gmsh.y"
+#line 2665 "Gmsh.y"
 { yyval.d = ParUtil::Instance()->rank(); ;
     break;}
 case 265:
-#line 2669 "Gmsh.y"
+#line 2666 "Gmsh.y"
 { yyval.d = ParUtil::Instance()->size(); ;
     break;}
 case 266:
-#line 2670 "Gmsh.y"
+#line 2667 "Gmsh.y"
 { yyval.d = Get_GmshMajorVersion(); ;
     break;}
 case 267:
-#line 2671 "Gmsh.y"
+#line 2668 "Gmsh.y"
 { yyval.d = Get_GmshMinorVersion(); ;
     break;}
 case 268:
-#line 2672 "Gmsh.y"
+#line 2669 "Gmsh.y"
 { yyval.d = Get_GmshPatchVersion(); ;
     break;}
 case 269:
-#line 2677 "Gmsh.y"
+#line 2674 "Gmsh.y"
 {
       Symbol TheSymbol;
       TheSymbol.Name = yyvsp[0].c;
@@ -5649,7 +5646,7 @@ case 269:
     ;
     break;}
 case 270:
-#line 2690 "Gmsh.y"
+#line 2687 "Gmsh.y"
 {
       Symbol TheSymbol;
       TheSymbol.Name = yyvsp[-3].c;
@@ -5671,7 +5668,7 @@ case 270:
     ;
     break;}
 case 271:
-#line 2710 "Gmsh.y"
+#line 2707 "Gmsh.y"
 {
       Symbol TheSymbol;
       TheSymbol.Name = yyvsp[-2].c;
@@ -5687,7 +5684,7 @@ case 271:
     ;
     break;}
 case 272:
-#line 2724 "Gmsh.y"
+#line 2721 "Gmsh.y"
 {
       Symbol TheSymbol;
       TheSymbol.Name = yyvsp[-1].c;
@@ -5702,7 +5699,7 @@ case 272:
     ;
     break;}
 case 273:
-#line 2737 "Gmsh.y"
+#line 2734 "Gmsh.y"
 {
       Symbol TheSymbol;
       TheSymbol.Name = yyvsp[-4].c;
@@ -5724,7 +5721,7 @@ case 273:
     ;
     break;}
 case 274:
-#line 2760 "Gmsh.y"
+#line 2757 "Gmsh.y"
 {
       double (*pNumOpt)(int num, int action, double value);
       StringXNumber *pNumCat;
@@ -5744,7 +5741,7 @@ case 274:
     ;
     break;}
 case 275:
-#line 2778 "Gmsh.y"
+#line 2775 "Gmsh.y"
 {
       double (*pNumOpt)(int num, int action, double value);
       StringXNumber *pNumCat;
@@ -5764,7 +5761,7 @@ case 275:
     ;
     break;}
 case 276:
-#line 2796 "Gmsh.y"
+#line 2793 "Gmsh.y"
 {
       double (*pNumOpt)(int num, int action, double value);
       StringXNumber *pNumCat;
@@ -5784,7 +5781,7 @@ case 276:
     ;
     break;}
 case 277:
-#line 2814 "Gmsh.y"
+#line 2811 "Gmsh.y"
 {
       double (*pNumOpt)(int num, int action, double value);
       StringXNumber *pNumCat;
@@ -5804,124 +5801,124 @@ case 277:
     ;
     break;}
 case 278:
-#line 2832 "Gmsh.y"
+#line 2829 "Gmsh.y"
 { 
       yyval.d = GetValue(yyvsp[-3].c, yyvsp[-1].d);
       Free(yyvsp[-3].c);
     ;
     break;}
 case 279:
-#line 2840 "Gmsh.y"
+#line 2837 "Gmsh.y"
 {
       memcpy(yyval.v, yyvsp[0].v, 5*sizeof(double));
     ;
     break;}
 case 280:
-#line 2844 "Gmsh.y"
+#line 2841 "Gmsh.y"
 {
       for(int i = 0; i < 5; i++) yyval.v[i] = -yyvsp[0].v[i];
     ;
     break;}
 case 281:
-#line 2848 "Gmsh.y"
+#line 2845 "Gmsh.y"
 { 
       for(int i = 0; i < 5; i++) yyval.v[i] = yyvsp[0].v[i];
     ;
     break;}
 case 282:
-#line 2852 "Gmsh.y"
+#line 2849 "Gmsh.y"
 { 
       for(int i = 0; i < 5; i++) yyval.v[i] = yyvsp[-2].v[i] - yyvsp[0].v[i];
     ;
     break;}
 case 283:
-#line 2856 "Gmsh.y"
+#line 2853 "Gmsh.y"
 {
       for(int i = 0; i < 5; i++) yyval.v[i] = yyvsp[-2].v[i] + yyvsp[0].v[i];
     ;
     break;}
 case 284:
-#line 2863 "Gmsh.y"
+#line 2860 "Gmsh.y"
 { 
       yyval.v[0] = yyvsp[-9].d;  yyval.v[1] = yyvsp[-7].d;  yyval.v[2] = yyvsp[-5].d;  yyval.v[3] = yyvsp[-3].d; yyval.v[4] = yyvsp[-1].d;
     ;
     break;}
 case 285:
-#line 2867 "Gmsh.y"
+#line 2864 "Gmsh.y"
 { 
       yyval.v[0] = yyvsp[-7].d;  yyval.v[1] = yyvsp[-5].d;  yyval.v[2] = yyvsp[-3].d;  yyval.v[3] = yyvsp[-1].d; yyval.v[4] = 1.0;
     ;
     break;}
 case 286:
-#line 2871 "Gmsh.y"
+#line 2868 "Gmsh.y"
 {
       yyval.v[0] = yyvsp[-5].d;  yyval.v[1] = yyvsp[-3].d;  yyval.v[2] = yyvsp[-1].d;  yyval.v[3] = 0.0; yyval.v[4] = 1.0;
     ;
     break;}
 case 287:
-#line 2875 "Gmsh.y"
+#line 2872 "Gmsh.y"
 {
       yyval.v[0] = yyvsp[-5].d;  yyval.v[1] = yyvsp[-3].d;  yyval.v[2] = yyvsp[-1].d;  yyval.v[3] = 0.0; yyval.v[4] = 1.0;
     ;
     break;}
 case 288:
-#line 2882 "Gmsh.y"
+#line 2879 "Gmsh.y"
 {
     ;
     break;}
 case 289:
-#line 2885 "Gmsh.y"
+#line 2882 "Gmsh.y"
 {
        yyval.l = yyvsp[-1].l;
     ;
     break;}
 case 290:
-#line 2889 "Gmsh.y"
+#line 2886 "Gmsh.y"
 {
        yyval.l = yyvsp[-1].l;
     ;
     break;}
 case 291:
-#line 2896 "Gmsh.y"
+#line 2893 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(List_T*));
       List_Add(yyval.l, &(yyvsp[0].l));
     ;
     break;}
 case 292:
-#line 2901 "Gmsh.y"
+#line 2898 "Gmsh.y"
 {
       List_Add(yyval.l, &(yyvsp[0].l));
     ;
     break;}
 case 293:
-#line 2909 "Gmsh.y"
+#line 2906 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(double));
       List_Add(yyval.l, &(yyvsp[0].d));
     ;
     break;}
 case 294:
-#line 2914 "Gmsh.y"
+#line 2911 "Gmsh.y"
 {
       yyval.l = yyvsp[0].l;
     ;
     break;}
 case 295:
-#line 2918 "Gmsh.y"
+#line 2915 "Gmsh.y"
 {
       // creates an empty list
       yyval.l = List_Create(2, 1, sizeof(double));
     ;
     break;}
 case 296:
-#line 2923 "Gmsh.y"
+#line 2920 "Gmsh.y"
 {
       yyval.l = yyvsp[-1].l;
     ;
     break;}
 case 297:
-#line 2927 "Gmsh.y"
+#line 2924 "Gmsh.y"
 {
       yyval.l = yyvsp[-1].l;
       double *pd;
@@ -5932,7 +5929,7 @@ case 297:
     ;
     break;}
 case 298:
-#line 2939 "Gmsh.y"
+#line 2936 "Gmsh.y"
 { 
       yyval.l = List_Create(2, 1, sizeof(double)); 
       for(double d = yyvsp[-2].d; (yyvsp[-2].d < yyvsp[0].d) ? (d <= yyvsp[0].d) : (d >= yyvsp[0].d); (yyvsp[-2].d < yyvsp[0].d) ? (d += 1.) : (d -= 1.)) 
@@ -5940,7 +5937,7 @@ case 298:
     ;
     break;}
 case 299:
-#line 2945 "Gmsh.y"
+#line 2942 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(double)); 
       if(!yyvsp[0].d || (yyvsp[-4].d < yyvsp[-2].d && yyvsp[0].d < 0) || (yyvsp[-4].d > yyvsp[-2].d && yyvsp[0].d > 0)){
@@ -5953,7 +5950,7 @@ case 299:
    ;
     break;}
 case 300:
-#line 2956 "Gmsh.y"
+#line 2953 "Gmsh.y"
 {
       // Returns the coordinates of a point and fills a list with it.
       // This allows to ensure e.g. that relative point positions are
@@ -5975,7 +5972,7 @@ case 300:
     ;
     break;}
 case 301:
-#line 2976 "Gmsh.y"
+#line 2973 "Gmsh.y"
 {
       yyval.l = List_Create(List_Nbr(yyvsp[0].l), 1, sizeof(double));
       for(int i = 0; i < List_Nbr(yyvsp[0].l); i++){
@@ -5987,7 +5984,7 @@ case 301:
     ;
     break;}
 case 302:
-#line 2986 "Gmsh.y"
+#line 2983 "Gmsh.y"
 {
       yyval.l = List_Create(List_Nbr(yyvsp[0].l), 1, sizeof(double));
       for(int i = 0; i < List_Nbr(yyvsp[0].l); i++){
@@ -5999,7 +5996,7 @@ case 302:
     ;
     break;}
 case 303:
-#line 2996 "Gmsh.y"
+#line 2993 "Gmsh.y"
 {
       yyval.l = List_Create(List_Nbr(yyvsp[0].l), 1, sizeof(double));
       for(int i = 0; i < List_Nbr(yyvsp[0].l); i++){
@@ -6011,7 +6008,7 @@ case 303:
     ;
     break;}
 case 304:
-#line 3006 "Gmsh.y"
+#line 3003 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(double));
       Symbol TheSymbol;
@@ -6030,7 +6027,7 @@ case 304:
     ;
     break;}
 case 305:
-#line 3023 "Gmsh.y"
+#line 3020 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(double));
       Symbol TheSymbol;
@@ -6051,7 +6048,7 @@ case 305:
     ;
     break;}
 case 306:
-#line 3042 "Gmsh.y"
+#line 3039 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(double));
       Symbol TheSymbol;
@@ -6077,7 +6074,7 @@ case 306:
     ;
     break;}
 case 307:
-#line 3066 "Gmsh.y"
+#line 3063 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(double));
       Symbol TheSymbol;
@@ -6105,26 +6102,26 @@ case 307:
     ;
     break;}
 case 308:
-#line 3095 "Gmsh.y"
+#line 3092 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(double));
       List_Add(yyval.l, &(yyvsp[0].d));
     ;
     break;}
 case 309:
-#line 3100 "Gmsh.y"
+#line 3097 "Gmsh.y"
 {
       yyval.l = yyvsp[0].l;
     ;
     break;}
 case 310:
-#line 3104 "Gmsh.y"
+#line 3101 "Gmsh.y"
 {
       List_Add(yyval.l, &(yyvsp[0].d));
     ;
     break;}
 case 311:
-#line 3108 "Gmsh.y"
+#line 3105 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[0].l); i++){
 	double d;
@@ -6135,19 +6132,19 @@ case 311:
     ;
     break;}
 case 312:
-#line 3121 "Gmsh.y"
+#line 3118 "Gmsh.y"
 {
       yyval.u = CTX.PACK_COLOR((int)yyvsp[-7].d, (int)yyvsp[-5].d, (int)yyvsp[-3].d, (int)yyvsp[-1].d);
     ;
     break;}
 case 313:
-#line 3125 "Gmsh.y"
+#line 3122 "Gmsh.y"
 {
       yyval.u = CTX.PACK_COLOR((int)yyvsp[-5].d, (int)yyvsp[-3].d, (int)yyvsp[-1].d, 255);
     ;
     break;}
 case 314:
-#line 3137 "Gmsh.y"
+#line 3134 "Gmsh.y"
 {
       int flag;
       yyval.u = Get_ColorForString(ColorString, -1, yyvsp[0].c, &flag);
@@ -6156,7 +6153,7 @@ case 314:
     ;
     break;}
 case 315:
-#line 3144 "Gmsh.y"
+#line 3141 "Gmsh.y"
 {
       unsigned int (*pColOpt)(int num, int action, unsigned int value);
       StringXColor *pColCat;
@@ -6177,13 +6174,13 @@ case 315:
     ;
     break;}
 case 316:
-#line 3166 "Gmsh.y"
+#line 3163 "Gmsh.y"
 {
       yyval.l = yyvsp[-1].l;
     ;
     break;}
 case 317:
-#line 3170 "Gmsh.y"
+#line 3167 "Gmsh.y"
 {
       yyval.l = List_Create(256, 10, sizeof(unsigned int));
       GmshColorTable *ct = Get_ColorTable((int)yyvsp[-3].d);
@@ -6197,26 +6194,26 @@ case 317:
     ;
     break;}
 case 318:
-#line 3185 "Gmsh.y"
+#line 3182 "Gmsh.y"
 {
       yyval.l = List_Create(256, 10, sizeof(unsigned int));
       List_Add(yyval.l, &(yyvsp[0].u));
     ;
     break;}
 case 319:
-#line 3190 "Gmsh.y"
+#line 3187 "Gmsh.y"
 {
       List_Add(yyval.l, &(yyvsp[0].u));
     ;
     break;}
 case 320:
-#line 3197 "Gmsh.y"
+#line 3194 "Gmsh.y"
 {
       yyval.c = yyvsp[0].c;
     ;
     break;}
 case 321:
-#line 3201 "Gmsh.y"
+#line 3198 "Gmsh.y"
 {
       yyval.c = (char *)Malloc(32*sizeof(char));
       time_t now;
@@ -6226,7 +6223,7 @@ case 321:
     ;
     break;}
 case 322:
-#line 3209 "Gmsh.y"
+#line 3206 "Gmsh.y"
 {
       yyval.c = (char *)Malloc((strlen(yyvsp[-3].c)+strlen(yyvsp[-1].c)+1)*sizeof(char));
       strcpy(yyval.c, yyvsp[-3].c);
@@ -6236,7 +6233,7 @@ case 322:
     ;
     break;}
 case 323:
-#line 3217 "Gmsh.y"
+#line 3214 "Gmsh.y"
 {
       yyval.c = (char *)Malloc((strlen(yyvsp[-1].c)+1)*sizeof(char));
       int i;
@@ -6252,7 +6249,7 @@ case 323:
     ;
     break;}
 case 324:
-#line 3231 "Gmsh.y"
+#line 3228 "Gmsh.y"
 {
       yyval.c = (char *)Malloc((strlen(yyvsp[-1].c)+1)*sizeof(char));
       int i;
@@ -6268,13 +6265,13 @@ case 324:
     ;
     break;}
 case 325:
-#line 3245 "Gmsh.y"
+#line 3242 "Gmsh.y"
 {
       yyval.c = yyvsp[-1].c;
     ;
     break;}
 case 326:
-#line 3249 "Gmsh.y"
+#line 3246 "Gmsh.y"
 {
       char tmpstring[1024];
       int i = PrintListOfDouble(yyvsp[-3].c, yyvsp[-1].l, tmpstring);
@@ -6295,7 +6292,7 @@ case 326:
     ;
     break;}
 case 327:
-#line 3268 "Gmsh.y"
+#line 3265 "Gmsh.y"
 { 
       char* (*pStrOpt)(int num, int action, char *value);
       StringXString *pStrCat;
@@ -6319,7 +6316,7 @@ case 327:
     ;
     break;}
 case 328:
-#line 3290 "Gmsh.y"
+#line 3287 "Gmsh.y"
 { 
       char* (*pStrOpt)(int num, int action, char *value);
       StringXString *pStrCat;
@@ -6564,7 +6561,7 @@ yyerrhandle:
     }
   return 1;
 }
-#line 3313 "Gmsh.y"
+#line 3310 "Gmsh.y"
 
 
 void DeleteSymbol(void *a, void *b){
diff --git a/Parser/Gmsh.y b/Parser/Gmsh.y
index 75db073c0d..06f07c006d 100644
--- a/Parser/Gmsh.y
+++ b/Parser/Gmsh.y
@@ -1,5 +1,5 @@
 %{
-// $Id: Gmsh.y,v 1.227 2006-04-04 04:32:34 geuzaine Exp $
+// $Id: Gmsh.y,v 1.228 2006-05-17 01:19:21 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -1780,11 +1780,9 @@ Command :
       }
       else if(!strcmp($1, "Print")){
 #if defined(HAVE_FLTK)
-	if(!CTX.batch){
-	  char tmpstring[1024];
-	  FixRelativePath($2, tmpstring);
-	  CreateOutputFile(tmpstring, CTX.print.format);
-	}
+	char tmpstring[1024];
+	FixRelativePath($2, tmpstring);
+	CreateOutputFile(tmpstring, CTX.print.format);
 #endif
       }
       else if(!strcmp($1, "Save")){
@@ -1902,8 +1900,7 @@ Command :
    | tDraw tEND
     {
 #if defined(HAVE_FLTK)
-      if(!CTX.batch) // we're in interactive mode
-	Draw();
+      Draw();
 #endif
     }
 ;
diff --git a/Parser/Gmsh.yy.cpp b/Parser/Gmsh.yy.cpp
index 5d29ad4c72..daf840277c 100644
--- a/Parser/Gmsh.yy.cpp
+++ b/Parser/Gmsh.yy.cpp
@@ -2,7 +2,7 @@
 /* A lexical scanner generated by flex */
 
 /* Scanner skeleton version:
- * $Header: /cvsroot/gmsh/Parser/Gmsh.yy.cpp,v 1.264 2006-04-04 04:35:00 geuzaine Exp $
+ * $Header: /cvsroot/gmsh/Parser/Gmsh.yy.cpp,v 1.265 2006-05-17 01:19:21 geuzaine Exp $
  */
 
 #define FLEX_SCANNER
@@ -727,7 +727,7 @@ char *yytext;
 #line 1 "Gmsh.l"
 #define INITIAL 0
 #line 2 "Gmsh.l"
-// $Id: Gmsh.yy.cpp,v 1.264 2006-04-04 04:35:00 geuzaine Exp $
+// $Id: Gmsh.yy.cpp,v 1.265 2006-05-17 01:19:21 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
diff --git a/configure.in b/configure.in
index f9c3dae10b..9dacc848f4 100644
--- a/configure.in
+++ b/configure.in
@@ -1,4 +1,4 @@
-dnl $Id: configure.in,v 1.96 2006-05-05 17:48:55 geuzaine Exp $
+dnl $Id: configure.in,v 1.97 2006-05-17 01:19:05 geuzaine Exp $
 dnl
 dnl Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 dnl
@@ -49,6 +49,10 @@ AC_ARG_WITH(zlib-prefix,
             AC_HELP_STRING([--with-zlib-prefix=PFX],
                            [prefix where the ZLIB library and includes are installed]),
             [ZLIB_PREFIX=$withval])
+AC_ARG_WITH(osmesa-prefix,
+            AC_HELP_STRING([--with-osmesa-prefix=PFX],
+                           [prefix where OSMesa is installed]),
+            [OSMESA_PREFIX=$withval])
 
 dnl Parse '--enable' command line options
 AC_ARG_ENABLE(gsl,
@@ -96,6 +100,9 @@ AC_ARG_ENABLE(matheval,
 AC_ARG_ENABLE(model,
               AC_HELP_STRING([--enable-model],
                              [compile Model interface if available (default=yes)]))
+AC_ARG_ENABLE(osmesa,
+              AC_HELP_STRING([--enable-osmesa],
+                             [use OSMesa for offscreen rendering (default=no)]))
 
 dnl Get the operating system name
 UNAME=`uname`
@@ -163,8 +170,27 @@ if test "x$enable_gui" != "xno"; then
     AC_MSG_ERROR([Could not find fltk-config. Try --with-fltk-prefix?])
   fi
 
-  GMSH_LIBS="${GMSH_LIBS} `$FLTKCONFIG --use-gl --use-images --ldflags`"
-  FLAGS="${FLAGS} `$FLTKCONFIG --use-gl --use-images --cxxflags`"
+  dnl Check for offscreen rendering using OSMesa
+  if test "x$enable_osmesa" = "xyes"; then
+    if test "x${OSMESA_PREFIX}" != "x"; then
+      LDFLAGS="-L${OSMESA_PREFIX} -L${OSMESA_PREFIX}/lib ${LDFLAGS}"
+    fi
+    AC_CHECK_LIB(OSMesa,main,OSMESA="yes",OSMESA="no")
+  fi
+
+  if test "x${OSMESA}" = "xyes"; then
+    GMSH_LIBS="${GMSH_LIBS} `$FLTKCONFIG --use-images --ldflags` -lfltk_gl"
+    FLAGS="${FLAGS} -DHAVE_OSMESA `$FLTKCONFIG --use-images --cxxflags`"
+    if test "x${OSMESA_PREFIX}" = "x"; then
+      GMSH_LIBS="${GMSH_LIBS} -lOSMesa -lGL -lGLU"
+    else
+      GMSH_LIBS="${GMSH_LIBS} -L${OSMESA_PREFIX} -L${OSMESA_PREFIX}/lib -lOSMesa -lGL -lGLU"
+      FLAGS="${FLAGS} -I${OSMESA_PREFIX} -I${OSMESA_PREFIX}/include"
+    fi
+  else
+    GMSH_LIBS="${GMSH_LIBS} `$FLTKCONFIG --use-gl --use-images --ldflags`"
+    FLAGS="${FLAGS} `$FLTKCONFIG --use-gl --use-images --cxxflags`"
+  fi
 
   FL_JPEG=""
   expr "x${GMSH_LIBS}" : 'x.*fltk_jpeg.*' >/dev/null && FL_JPEG="yes"
-- 
GitLab