diff --git a/Common/Context.h b/Common/Context.h
index 63e91f0889629d918ec42e210cd5ebb6910a9c4b..a1d7ffe10a561413ecbd94cbfef908ebfbbb11fe 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -90,8 +90,6 @@ public :
   int nopopup;                // never popup dialogs in scripts (use default values instead)
 
   double rot[16];             // current rotation matrix 
-  double mod[16];             // current modelview matrix 
-  double proj[16];            // current projection matrix
   double r[3];                // position angles (if succ. rot. along x, y and z) 
   double t[3], s[3];          // current translation and scale 
   double clip_factor;         // clipping plane distance factor
@@ -113,7 +111,8 @@ public :
   int draw_bbox;              // always draw the bounding boxes?
   int fast_redraw;            // only draw the bbox when rotating/panning the model?
   int axes, small_axes;       // draw axes? 
-  int small_axes_pos[2], small_axes_size; // small axes position and size
+  int axes_size, small_axes_size; // axes size
+  int small_axes_pos[2];      // small axes position
   int threads, threads_lock;  // threads?, lock (should be a mutex...) 
   int alpha;                  // enable alpha blending 
   double zoom_factor;         // mouse2 zoom coefficient
diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index 78a21a7d2c15ac0697da20885c0afa9c29a5c742..c363e089b68649cf954f9da03e75f683d1ddd548 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -366,7 +366,7 @@ StringXString ViewOptions_String[] = {
   { F|O, "AbscissaName" , opt_view_abscissa_name , "" , 
     "Abscissa name for 2D graphs" },
   { F|O, "AbscissaFormat" , opt_view_abscissa_format , "%.3g" , 
-    "Abscissa number format for 2D graphs (in standard C form)" },
+    "Abscissa number format (in standard C form)" },
 
   { F,   "FileName" , opt_view_filename , "" , 
     "Default post-processing view file name" },
@@ -403,6 +403,8 @@ StringXNumber GeneralOptions_Number[] = {
     "Relative radius of arrow stem" },
   { F|O, "Axes" , opt_general_axes , 0. ,
     "Display the axes linked to the model" },
+  { F|O, "AxesSize" , opt_general_axes_size , 100. ,
+    "Size (in pixels) of moving axes" },
   { F,   "Clip0" , opt_general_clip0 , 0. ,
     "Enable clipping plane 0 (Geometry=2^0, Mesh=2^1, View[i]=2^(2+i))" },
   { F,   "Clip0A" , opt_general_clip0a , 1.0 ,
@@ -811,7 +813,7 @@ StringXNumber MeshOptions_Number[] = {
     "Only display elements whose Gamma factor is smaller than GammaSup" },
 
   { F|O, "Interactive" , opt_mesh_interactive , 0. ,
-    "Show the construction of the 2D mesh in real time (only with the 2D anisotropic algorithm)" },
+    "Show the construction of 2D anisotropic mesh in real time" },
 
   { F|O, "Light" , opt_mesh_light , 0. , 
     "Enable lighting for the mesh" },
@@ -1075,8 +1077,8 @@ StringXNumber ViewOptions_Number[] = {
     "Generalized raise amplification factor" },
   { F|O, "GeneralizedRaiseView" , opt_view_gen_raise_view , -1. ,
     "Index of the view used for generalized raise (-1=self)" },
-  { F|O, "Grid" , opt_view_grid , 2 ,
-    "Grid mode for 2D graphs (0=none, 1=simple, 2=frame, 3=grid)" },
+  { F|O, "Grid" , opt_view_grid , 0 ,
+    "Grid mode (0=none, 1=axes, 2=box, 3=full grid, 4=open grid)" },
 
   { F|O, "Height" , opt_view_size1 , 200. , 
     "Height (in pixels) of the scale or 2D graph" }, 
@@ -1111,7 +1113,7 @@ StringXNumber ViewOptions_Number[] = {
     "Minimum view coordinate along the Z-axis (read-only)" }, 
 
   { F|O, "NbAbscissa" , opt_view_nb_abscissa , 5. ,
-    "Number of abscissa intervals for 2D graphs" },
+    "Number of tics on the grid axes" },
   { F|O, "NbIso" , opt_view_nb_iso , 15. ,
     "Number of intervals" },
   { F,   "NbTimeStep" , opt_view_nb_timestep , 1. ,
diff --git a/Common/Options.cpp b/Common/Options.cpp
index 7df9f309a375317abf0a9450d214be82e2775882..866a7c7b82d92a2bf1fe86ac8325e70c96f584f0 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -1,4 +1,4 @@
-// $Id: Options.cpp,v 1.227 2005-01-13 05:45:41 geuzaine Exp $
+// $Id: Options.cpp,v 1.228 2005-03-11 05:47:54 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -2474,6 +2474,13 @@ double opt_general_axes(OPT_ARGS_NUM)
   return CTX.axes;
 }
 
+double opt_general_axes_size(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET)
+    CTX.axes_size = (int)val;
+  return CTX.axes_size;
+}
+
 double opt_general_small_axes(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
@@ -5090,7 +5097,7 @@ double opt_view_grid(OPT_ARGS_NUM)
   GET_VIEW(0.);
   if(action & GMSH_SET) {
     v->Grid = (int)val;
-    if(v->Grid < 0 || v->Grid > 3)
+    if(v->Grid < 0 || v->Grid > 4)
       v->Grid = 0;
   }
 #if defined(HAVE_FLTK)
diff --git a/Common/Options.h b/Common/Options.h
index 960afd9f2f5d7badad50a6c0dfad91debb05a20c..897fb36e71d9441e1af5fd1529a69aae3644cb59 100644
--- a/Common/Options.h
+++ b/Common/Options.h
@@ -268,6 +268,7 @@ double opt_general_orthographic(OPT_ARGS_NUM);
 double opt_general_draw_bounding_box(OPT_ARGS_NUM);
 double opt_general_fast_redraw(OPT_ARGS_NUM);
 double opt_general_axes(OPT_ARGS_NUM);
+double opt_general_axes_size(OPT_ARGS_NUM);
 double opt_general_small_axes(OPT_ARGS_NUM);
 double opt_general_small_axes_position0(OPT_ARGS_NUM);
 double opt_general_small_axes_position1(OPT_ARGS_NUM);
diff --git a/Common/Views.cpp b/Common/Views.cpp
index 56187ecde8e7b1c3a3a44d0d8577c1073c3d8880..57e883bdb07baee878b1cc2231977331d7e4f7dd 100644
--- a/Common/Views.cpp
+++ b/Common/Views.cpp
@@ -1,4 +1,4 @@
-// $Id: Views.cpp,v 1.164 2005-01-24 17:39:28 geuzaine Exp $
+// $Id: Views.cpp,v 1.165 2005-03-11 05:47:54 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -176,8 +176,8 @@ Post_View *BeginView(int allocate)
   v->Max = -VAL_INF;
   v->adaptive = 0;
   for(i = 0; i < 3; i++) {
-    v->BBox[2 * i] = VAL_INF;
-    v->BBox[2 * i + 1] = -VAL_INF;
+    v->BBox[2 * i] = v->TmpBBox[2 * i] = VAL_INF;
+    v->BBox[2 * i + 1] = v->TmpBBox[2 * i + 1] = -VAL_INF;
   }
   for(i = 0; i < 3; i++)
     v->GenRaise_f[i] = NULL;
@@ -777,6 +777,7 @@ Post_View *Create2DGraph(char *xname, char *yname,
   sprintf(filename, "%s.pos", yname);
   EndView(v, 1, filename, yname);
   v->Type = DRAW_POST_2D_SPACE;
+  v->Grid = 2;
   strcpy(v->AbscissaName, xname);
   return v;
 }
diff --git a/Common/Views.h b/Common/Views.h
index 133090780732f128e61de6e64bcc3c3818a6b5d6..9d76e4e8b10a550d099973c07d6c330f3f957b22 100644
--- a/Common/Views.h
+++ b/Common/Views.h
@@ -114,6 +114,7 @@ class Post_View{
   int (*GIFV) (double min, double max, int nb, double value);
   int ExternalElementIndex;
   double ExternalMin, ExternalMax;
+  double TmpBBox[6]; // dynamically computed during drawing
 
   // smooth the view
   void smooth();
diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp
index 8b3b39130bc10cbf38e68336e0c81d8e4ca17c5d..78a6759fc2f76aa359b8b77107692058cdfb385a 100644
--- a/Fltk/Callbacks.cpp
+++ b/Fltk/Callbacks.cpp
@@ -1,4 +1,4 @@
-// $Id: Callbacks.cpp,v 1.339 2005-03-09 09:21:26 geuzaine Exp $
+// $Id: Callbacks.cpp,v 1.340 2005-03-11 05:47:54 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -1307,6 +1307,7 @@ void help_short_cb(CALLBACK_ARGS)
   Msg(DIRECT, "  Alt+c         Loop through predefined color schemes");
   Msg(DIRECT, "  Alt+d         Change surface mesh display mode (solid/wireframe)");
   Msg(DIRECT, "  Alt+f         Change redraw mode (fast/full)"); 
+  Msg(DIRECT, "  Alt+g         Loop through grid modes for all post-processing views"); 
   Msg(DIRECT, "  Alt+h         Hide/show all post-processing views"); 
   Msg(DIRECT, "  Alt+i         Hide/show all post-processing view scales");
   Msg(DIRECT, "  Alt+l         Hide/show geometry lines");
diff --git a/Fltk/GUI.cpp b/Fltk/GUI.cpp
index 11ef99c39b537c1318ed01c2ab193dd55d82269d..ffe7f6c3901f269b879e97fbdec476f539454c60 100644
--- a/Fltk/GUI.cpp
+++ b/Fltk/GUI.cpp
@@ -1,4 +1,4 @@
-// $Id: GUI.cpp,v 1.420 2005-03-09 09:21:26 geuzaine Exp $
+// $Id: GUI.cpp,v 1.421 2005-03-11 05:47:55 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -439,18 +439,39 @@ char *GetFontName(int index)
 int GetFontAlign(char *alignstr)
 {
   if(alignstr){
-    if(!strcmp(alignstr, "left") || !strcmp(alignstr, "Left"))
+    if(!strcmp(alignstr, "BottomLeft") || !strcmp(alignstr, "Left") ||
+       !strcmp(alignstr, "left"))
       return 0;
-    else if(!strcmp(alignstr, "center") || !strcmp(alignstr, "Center"))
+    else if(!strcmp(alignstr, "BottomCenter") || !strcmp(alignstr, "Center") ||
+	    !strcmp(alignstr, "center"))
       return 1;
-    else if(!strcmp(alignstr, "right") || !strcmp(alignstr, "Right"))
+    else if(!strcmp(alignstr, "BottomRight") || !strcmp(alignstr, "Right") ||
+	    !strcmp(alignstr, "right"))
       return 2;
+    else if(!strcmp(alignstr, "TopLeft"))
+      return 3;
+    else if(!strcmp(alignstr, "TopCenter"))
+      return 4;
+    else if(!strcmp(alignstr, "TopRight"))
+      return 5;
+    else if(!strcmp(alignstr, "CenterLeft"))
+      return 6;
+    else if(!strcmp(alignstr, "CenterCenter"))
+      return 7;
+    else if(!strcmp(alignstr, "CenterRight"))
+      return 8;
   }
   Msg(GERROR, "Unknown font alignment \"%s\" (using \"Left\" instead)", alignstr);
   Msg(INFO, "Available font alignments:");
-  Msg(INFO, "  \"Left\"");
-  Msg(INFO, "  \"Center\"");
-  Msg(INFO, "  \"Right\"");
+  Msg(INFO, "  \"Left\" (or \"BottomLeft\")");
+  Msg(INFO, "  \"Center\" (or \"BottomCenter\")");
+  Msg(INFO, "  \"Right\" (or \"BottomRight\")");
+  Msg(INFO, "  \"TopLeft\"");
+  Msg(INFO, "  \"TopCenter\"");
+  Msg(INFO, "  \"TopRight\"");
+  Msg(INFO, "  \"CenterLeft\"");
+  Msg(INFO, "  \"CenterCenter\"");
+  Msg(INFO, "  \"CenterRight\"");
   return 0;
 }
 
@@ -713,6 +734,14 @@ int GUI::global_shortcuts(int event)
     redraw_opengl();
     return 1;
   }
+  else if(Fl::test_shortcut(FL_ALT + 'g')) {
+    for(i = 0; i < List_Nbr(CTX.post.list); i++) {
+      if(opt_view_visible(i, GMSH_GET, 0))
+        opt_view_grid(i, GMSH_SET | GMSH_GUI, opt_view_grid(i, GMSH_GET, 0)+1);
+    }
+    redraw_opengl();
+    return 1;
+  }
   else if(Fl::test_shortcut(FL_ALT + 'n')) {
     for(i = 0; i < List_Nbr(CTX.post.list); i++)
       if(opt_view_visible(i, GMSH_GET, 0))
@@ -2474,38 +2503,34 @@ void GUI::create_option_window()
       view_input[0] = new Fl_Input(L + 2 * WB, 2 * WB + 5 * BH, IW, BH, "Name");
       view_input[0]->align(FL_ALIGN_RIGHT);
 
-      view_input[1] = new Fl_Input(L + 2 * WB, 2 * WB + 6 * BH, IW, BH, "Format");
+      view_input[1] = new Fl_Input(L + 2 * WB, 2 * WB + 6 * BH, IW, BH, "Number format");
       view_input[1]->align(FL_ALIGN_RIGHT);
 
-      {
-	view_2d = new Fl_Group(L + 2 * WB, 2 * WB + 7 * BH, width - 2 * WB, 4 * BH, 0);
-	
-	view_input[2] = new Fl_Input(L + 2 * WB, 2 * WB + 7 * BH, IW, BH, "Abscissa name");
-	view_input[2]->align(FL_ALIGN_RIGHT);
-	
-	view_input[3] = new Fl_Input(L + 2 * WB, 2 * WB + 8 * BH, IW, BH, "Abscissa format");
-	view_input[3]->align(FL_ALIGN_RIGHT);
-	
-	view_value[25] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 9 * BH, IW, BH, "Number of abscissa points");
-	view_value[25]->minimum(0.);
-	view_value[25]->step(1);
-	view_value[25]->maximum(256);
-	view_value[25]->align(FL_ALIGN_RIGHT);
-	
-	static Fl_Menu_Item menu_grid_mode[] = {
-	  {"None", 0, 0, 0},
-	  {"Axes", 0, 0, 0},
-	  {"Box", 0, 0, 0},
-	  {"Full", 0, 0, 0},
-	  {0}
-	};
-	view_choice[8] = new Fl_Choice(L + 2 * WB, 2 * WB + 10 * BH, IW, BH, "Grid mode");
-	view_choice[8]->menu(menu_grid_mode);
-	view_choice[8]->align(FL_ALIGN_RIGHT);
-	
-	view_2d->end();
-      }
+      static Fl_Menu_Item menu_grid_mode[] = {
+	{"None", 0, 0, 0},
+	{"Axes", 0, 0, 0},
+	{"Box", 0, 0, 0},
+	{"Full grid", 0, 0, 0},
+	{"Open grid", 0, 0, 0},
+	{0}
+      };
+      view_choice[8] = new Fl_Choice(L + 2 * WB, 2 * WB + 7 * BH, IW, BH, "Grid mode");
+      view_choice[8]->menu(menu_grid_mode);
+      view_choice[8]->align(FL_ALIGN_RIGHT);
+      view_choice[8]->tooltip("(Alt+g)");
 
+      view_input[3] = new Fl_Input(L + 2 * WB, 2 * WB + 8 * BH, IW, BH, "Grid number format");
+      view_input[3]->align(FL_ALIGN_RIGHT);
+      
+      view_value[25] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 9 * BH, IW, BH, "Axis tics");
+      view_value[25]->minimum(0.);
+      view_value[25]->step(1);
+      view_value[25]->maximum(256);
+      view_value[25]->align(FL_ALIGN_RIGHT);
+
+      view_input[2] = new Fl_Input(L + 2 * WB, 2 * WB + 10 * BH, IW, BH, "Abscissa name");
+      view_input[2]->align(FL_ALIGN_RIGHT);
+      
       view_butt[7] = new Fl_Check_Button(L + width / 2, 2 * WB + 1 * BH, BW / 2 - WB, BH, "Set position automatically");
       view_butt[7]->type(FL_TOGGLE_BUTTON);
       view_butt[7]->down_box(GMSH_TOGGLE_BOX);
@@ -3006,14 +3031,15 @@ void GUI::update_view_window(int num)
   opt_view_normals(num, GMSH_GUI, 0);
   opt_view_tangents(num, GMSH_GUI, 0);
 
+  opt_view_grid(num, GMSH_GUI, 0);
+  opt_view_abscissa_format(num, GMSH_GUI, NULL);
+  opt_view_nb_abscissa(num, GMSH_GUI, 0);
+
   if(v->NbSP)
-    view_2d->activate();
+    view_input[2]->activate();
   else
-    view_2d->deactivate();
+    view_input[2]->deactivate();
   opt_view_abscissa_name(num, GMSH_GUI, NULL);
-  opt_view_abscissa_format(num, GMSH_GUI, NULL);
-  opt_view_nb_abscissa(num, GMSH_GUI, 0);
-  opt_view_grid(num, GMSH_GUI, 0);
 
   opt_view_nb_iso(num, GMSH_GUI, 0);
   opt_view_intervals_type(num, GMSH_GUI, 0);
diff --git a/Fltk/GUI.h b/Fltk/GUI.h
index 11d0bb988db6431576e1cc49b04971f856852b01..6dd0834788bff371a0e79ded70b22828414af7d7 100644
--- a/Fltk/GUI.h
+++ b/Fltk/GUI.h
@@ -197,7 +197,7 @@ public:
   // view options
   int view_number ;
   Fl_Group         *view_group ;
-  Fl_Group         *view_2d, *view_range, *view_vector ;
+  Fl_Group         *view_range, *view_vector ;
   Fl_Check_Button  *view_butt[100] ;
   Fl_Value_Input   *view_value[100] ;
   Fl_Input         *view_input[100] ;
diff --git a/Fltk/Opengl.cpp b/Fltk/Opengl.cpp
index 28b865f7c741fa12a3edc3d2b0db6016058ec0a6..58fb869c70b0a2d9d0519e3f876cfa81523fead1 100644
--- a/Fltk/Opengl.cpp
+++ b/Fltk/Opengl.cpp
@@ -1,4 +1,4 @@
-// $Id: Opengl.cpp,v 1.49 2005-01-01 19:35:28 geuzaine Exp $
+// $Id: Opengl.cpp,v 1.50 2005-03-11 05:47:55 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -66,7 +66,7 @@ void Draw(void)
   WID->redraw_opengl();
 }
 
-void SanitizeTexString(char *in, char *out)
+void SanitizeTeXString(char *in, char *out)
 {
   // if there is a '$' or a '\' in the string, assume the author knows
   // what he's doing:
@@ -96,14 +96,25 @@ void Draw_String(char *s, char *font_name, int font_enum, int font_size, int ali
       GLboolean valid;
       glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid);
       if(valid == GL_TRUE){
-	GLfloat pos[4];
-	glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
+	GLdouble pos[4];
+	glGetDoublev(GL_CURRENT_RASTER_POSITION, pos);
+	double x[3], w[3] = {pos[0], pos[1], pos[2]};
 	gl_font(font_enum, font_size);
 	float width = gl_width(s);
-	if(align == 1) // center
-	  glRasterPos2d(pos[0]-width/2., pos[1]);
-	else if(align == 2) // right
-	  glRasterPos2d(pos[0]-width, pos[1]);
+	float height = gl_height();
+	switch(align){
+	case 1: w[0] -= width/2.;                     break; // bottom center
+	case 2: w[0] -= width;                        break; // bottom right
+	case 3:                    w[1] -= height;    break; // top left
+	case 4: w[0] -= width/2.;  w[1] -= height;    break; // top center
+	case 5: w[0] -= width;     w[1] -= height;    break; // top right
+	case 6:                    w[1] -= height/2.; break; // center left
+	case 7: w[0] -= width/2.;  w[1] -= height/2.; break; // center center
+	case 8: w[0] -= width;     w[1] -= height/2.; break; // center right
+	default: break;
+	}
+	Viewport2World(w, x);
+	glRasterPos3d(x[0], x[1], x[2]);
       }
     }
   }
@@ -118,11 +129,20 @@ void Draw_String(char *s, char *font_name, int font_enum, int font_size, int ali
       return;
     if(CTX.print.format == FORMAT_TEX){
       char tmp[1024];
-      SanitizeTexString(s, tmp);
-      gl2psTextOpt(tmp, font_name, font_size, 
-		   (align == 0) ? GL2PS_TEXT_BL :
-		   (align == 1) ? GL2PS_TEXT_B :
-		   GL2PS_TEXT_BR, 0.);
+      SanitizeTeXString(s, tmp);
+      int opt;
+      switch(align){
+      case 1: opt = GL2PS_TEXT_B;   break; // bottom center
+      case 2: opt = GL2PS_TEXT_BR;  break; // bottom right
+      case 3: opt = GL2PS_TEXT_TL;  break; // top left
+      case 4: opt = GL2PS_TEXT_T;   break; // top center
+      case 5: opt = GL2PS_TEXT_TR;  break; // top right
+      case 6: opt = GL2PS_TEXT_CL;  break; // center left
+      case 7: opt = GL2PS_TEXT_C;   break; // center center
+      case 8: opt = GL2PS_TEXT_CR;  break; // center right
+      default: opt = GL2PS_TEXT_BL; break; // bottom left
+      }
+      gl2psTextOpt(tmp, font_name, font_size, opt, 0.);
     }
     else
       gl2psText(s, font_name, font_size);
@@ -164,7 +184,6 @@ void Draw_String(char *s, double style)
 
 void Draw_OnScreenMessages()
 {
-
   glColor4ubv((GLubyte *) & CTX.color.text);
   gl_font(CTX.gl_font_enum, CTX.gl_fontsize);
   double h = gl_height();
diff --git a/Graphics/Axes.cpp b/Graphics/Axes.cpp
index 7bf404925c14a0e1f39ea439bceda24164584b24..3658b7b76339c38560bb291d423ee47170656b72 100644
--- a/Graphics/Axes.cpp
+++ b/Graphics/Axes.cpp
@@ -1,4 +1,4 @@
-// $Id: Axes.cpp,v 1.25 2005-01-02 18:10:12 geuzaine Exp $
+// $Id: Axes.cpp,v 1.26 2005-03-11 05:47:55 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -29,20 +29,20 @@
 
 extern Context_T CTX;
 
-void Draw_Axes(double s)
+void Draw_Axes()
 {
-  double f, g, b, c;
-
-  if(s == 0.)
+  if(!CTX.range[0] && !CTX.range[1] && !CTX.range[2])
     return;
 
-  if(!CTX.range[0] && !CTX.range[1] && !CTX.range[2])
+  double s = CTX.axes_size * CTX.pixel_equiv_x / CTX.s[0];
+
+  if(s == 0.)
     return;
 
-  f = 0.666 * s;
-  g = 1.233 * s;
-  b = .1 * s;
-  c = 0.666 * b;
+  double f = 0.666 * s;
+  double g = 1.233 * s;
+  double b = .1 * s;
+  double c = 0.666 * b;
 
   glLineWidth(CTX.line_width);
   gl2psLineWidth(CTX.line_width * CTX.print.eps_line_width_factor);
diff --git a/Graphics/Draw.cpp b/Graphics/Draw.cpp
index 1e1e0722b884ae185b4901d381f40e521717f964..43e94d931c2ad1e655857a289b8dcc934bae7a45 100644
--- a/Graphics/Draw.cpp
+++ b/Graphics/Draw.cpp
@@ -1,4 +1,4 @@
-// $Id: Draw.cpp,v 1.73 2005-03-09 02:18:40 geuzaine Exp $
+// $Id: Draw.cpp,v 1.74 2005-03-11 05:47:55 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -45,7 +45,7 @@ int NeedPolygonOffset()
   for(int i = 0; i < List_Nbr(CTX.post.list); i++){
     Post_View *v = *(Post_View**)List_Pointer(CTX.post.list, i);
     if(v->Visible){
-      if(v->ShowElement)
+      if(v->ShowElement || v->Grid)
 	return 1;
       if((v->NbST || v->NbSQ) && (v->IntervalsType == DRAW_POST_ISO))
 	return 1;
@@ -275,10 +275,6 @@ void InitPosition(void)
     glTranslated(-CTX.rotation_center[0],
 		 -CTX.rotation_center[1],
 		 -CTX.rotation_center[2]);
-
-  // store the modelview and projection matrices
-  glGetDoublev(GL_MODELVIEW_MATRIX, CTX.mod);
-  glGetDoublev(GL_PROJECTION_MATRIX, CTX.proj);
 }
 
 // Entity selection
@@ -377,15 +373,18 @@ void myZoom(GLdouble X1, GLdouble X2, GLdouble Y1, GLdouble Y2,
 void unproject(double x, double y, double p[3], double d[3])
 {
   GLint viewport[4];
+  GLdouble model[16], proj[16];
   glGetIntegerv(GL_VIEWPORT, viewport);
+  glGetDoublev(GL_PROJECTION_MATRIX, proj);
+  glGetDoublev(GL_MODELVIEW_MATRIX, model);
 
   y = viewport[3]-y;
 
   GLdouble x0, y0, z0, x1, y1, z1;
   
-  if(!gluUnProject(x, y, 0.0, CTX.mod, CTX.proj, viewport, &x0, &y0, &z0))
+  if(!gluUnProject(x, y, 0.0, model, proj, viewport, &x0, &y0, &z0))
     Msg(WARNING, "unproject1 failed");
-  if(!gluUnProject(x, y, 1.0, CTX.mod, CTX.proj, viewport, &x1, &y1, &z1))
+  if(!gluUnProject(x, y, 1.0, model, proj, viewport, &x1, &y1, &z1))
     Msg(WARNING, "unproject2 failed");
   
   p[0] = x0;
@@ -399,3 +398,23 @@ void unproject(double x, double y, double p[3], double d[3])
   d[1] /= len;
   d[2] /= len;
 }
+
+void Viewport2World(double win[3], double xyz[3])
+{
+  GLint viewport[4];
+  GLdouble model[16], proj[16];
+  glGetIntegerv(GL_VIEWPORT, viewport);
+  glGetDoublev(GL_PROJECTION_MATRIX, proj);
+  glGetDoublev(GL_MODELVIEW_MATRIX, model);
+  gluUnProject(win[0], win[1], win[2], model, proj, viewport, &xyz[0], &xyz[1], &xyz[2]);
+}
+
+void World2Viewport(double xyz[3], double win[3])
+{
+  GLint viewport[4];
+  GLdouble model[16], proj[16];
+  glGetIntegerv(GL_VIEWPORT, viewport);
+  glGetDoublev(GL_PROJECTION_MATRIX, proj);
+  glGetDoublev(GL_MODELVIEW_MATRIX, model);
+  gluProject(xyz[0], xyz[1], xyz[2], model, proj, viewport, &win[0], &win[1], &win[2]);
+}
diff --git a/Graphics/Draw.h b/Graphics/Draw.h
index d1643003c151ba2d909386cccea8428cdefc9383..c444654d995e4ca7243a66227e9613c3a5c3eef2 100644
--- a/Graphics/Draw.h
+++ b/Graphics/Draw.h
@@ -43,6 +43,8 @@ void set_t(int i, double val);
 void set_s(int i, double val);
 
 void unproject(double x, double y, double p[3], double d[3]);
+void Viewport2World(double win[3], double xyz[3]);
+void World2Viewport(double xyz[3], double win[3]);
 
 unsigned int PaletteContinuous(Post_View * View, double min, double max, double val);
 unsigned int PaletteContinuousLinear(Post_View * v, double min, double max, double val);
@@ -71,7 +73,7 @@ void Draw_Text2D3D(int dim, int timestep, int nb, List_T *td, List_T *tc);
 void FixText2DCoordinates(double *x, double *y);
 void Draw_OnScreenMessages(void);
 void Draw_Scales(void);
-void Draw_Axes(double s);
+void Draw_Axes(void);
 void Draw_SmallAxes(void);
 void Draw_Disk(double size, double rint, double x, double y, double z, int light);
 void Draw_Sphere(double size, double x, double y, double z, int light);
@@ -84,6 +86,10 @@ void Draw_Vector(int Type, int Fill,
 		 double relHeadRadius, double relStemLength, double relStemRadius,
 		 double x, double y, double z, double dx, double dy, double dz,
 		 int light);
+void Draw_PlaneInBoundingBox(double xmin, double ymin, double zmin,
+			     double xmax, double ymax, double zmax,
+			     double a, double b, double c, double d);
+void Draw_3DGrid(int mode, int tics, char *format, double bbox[6]);
 
 void Draw_Mesh(Mesh *M);
 void Draw_Mesh_Volume(void *a, void *b);
@@ -100,10 +106,6 @@ void Draw_Mesh_Prism(void *a, void *b);
 void Draw_Mesh_Pyramid(void *a, void *b);
 void Draw_Mesh_Array(VertexArray *va, int faces, int edges);
 
-void Draw_PlaneInBoundingBox(double xmin, double ymin, double zmin,
-			     double xmax, double ymax, double zmax,
-			     double a, double b, double c, double d);
-
 #define ARGS Post_View *View, int preproNormals, \
              double ValMin, double ValMax, 	 \
              double *X, double *Y, double *Z, double *V
diff --git a/Graphics/Entity.cpp b/Graphics/Entity.cpp
index 111813b822b4d3f35f6fb1b5f83d42d651710051..3cecec5d6d3ce038efbca3f44456a50fbc549022 100644
--- a/Graphics/Entity.cpp
+++ b/Graphics/Entity.cpp
@@ -1,4 +1,4 @@
-// $Id: Entity.cpp,v 1.56 2005-03-09 09:21:26 geuzaine Exp $
+// $Id: Entity.cpp,v 1.57 2005-03-11 05:47:55 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -26,6 +26,7 @@
 #include "Numeric.h"
 #include "Draw.h"
 #include "Context.h"
+#include "gl2ps.h"
 
 extern Context_T CTX;
 
@@ -501,3 +502,176 @@ void Draw_PlaneInBoundingBox(double xmin, double ymin, double zmin,
     }
   }
 }
+
+int Draw_Tics(int comp, int n, char *format, 
+	      double p1[3], double p2[3], double perp[3])
+{
+  // draws n tic marks (in direction perp) and labels along the line p1->p2
+
+  if(n < 2) return 0;
+
+  if(!strlen(format)) return n;
+
+  double t[3] = { p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2] };
+  double l = norme(t);
+  norme(perp);
+  double w = 10 * CTX.pixel_equiv_x / CTX.s[0]; // big tics 10 pixels
+  double w2 = 4 * CTX.pixel_equiv_x / CTX.s[0]; // small tics 4 pixels
+
+  double tmp = 2. * CTX.gl_fontsize * CTX.pixel_equiv_x / CTX.s[0];
+  if(n * tmp > l) n = 3;
+  if(n * tmp > l) n = 2;
+  
+  double step = l/(double)(n-1);
+
+  for(int i = 0; i < n; i++){
+    double d = i * step;
+    double p[3] = { p1[0]+t[0]*d, p1[1]+t[1]*d, p1[2]+t[2]*d };
+    double q[3] = { p[0]+perp[0]*w, p[1]+perp[1]*w, p[2]+perp[2]*w };
+    double r[3] = { p[0]+perp[0]*w*1.4, p[1]+perp[1]*w*1.4, p[2]+perp[2]*w*1.4 };
+
+    glBegin(GL_LINES);
+    glVertex3d(p[0], p[1], p[2]);
+    glVertex3d(q[0], q[1], q[2]);
+    glEnd();
+
+    if(i < n-1){
+      for(int j = 1; j < 10; j++){
+	double dd = d + j * step/10.;
+	double pp[3] = { p1[0]+t[0]*dd, p1[1]+t[1]*dd, p1[2]+t[2]*dd };
+	double qq[3] = { pp[0]+perp[0]*w2, pp[1]+perp[1]*w2, pp[2]+perp[2]*w2 };
+	glBegin(GL_LINES);
+	glVertex3d(pp[0], pp[1], pp[2]);
+	glVertex3d(qq[0], qq[1], qq[2]);
+	glEnd();
+      }
+    }
+
+    char label[256];
+    sprintf(label, format, p[comp]);
+    double winp[3], winr[3];
+    World2Viewport(p, winp);
+    World2Viewport(r, winr);
+    gl_font(CTX.gl_font_enum, CTX.gl_fontsize);
+    if(fabs(winr[0] - winp[0]) < 2.) // center align
+      winr[0] -= gl_width(label) / 2.;
+    else if(winr[0] < winp[0]) // right align
+      winr[0] -= gl_width(label);
+    if(fabs(winr[1] - winp[1]) < 2.) // center align
+      winr[1] -= gl_height() / 3.;
+    else if(winr[1] < winp[1]) // top align
+      winr[1] -= gl_height();
+    Viewport2World(winr, r);
+    glRasterPos3d(r[0], r[1], r[2]);
+    Draw_String(label);
+  }
+
+  return n;
+}
+
+void Draw_GridStipple(int n1, int n2, double p1[3], double p2[3], double p3[3])
+{
+  double t1[3] = { p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2] };
+  double t2[3] = { p3[0]-p1[0], p3[1]-p1[1], p3[2]-p1[2] };
+  double l1 = norme(t1);
+  double l2 = norme(t2);
+
+  glEnable(GL_LINE_STIPPLE);
+  glLineStipple(1, 0x1111);
+  gl2psEnable(GL2PS_LINE_STIPPLE);
+  glBegin(GL_LINES);
+  
+  for(int i = 1; i < n1-1; i++){
+    double d = (double)i/(double)(n1-1) * l1;
+    glVertex3d(p1[0] + t1[0]*d,
+	       p1[1] + t1[1]*d,
+	       p1[2] + t1[2]*d);
+    glVertex3d(p1[0] + t1[0]*d + t2[0]*l2, 
+	       p1[1] + t1[1]*d + t2[1]*l2, 
+	       p1[2] + t1[2]*d + t2[2]*l2);
+  }
+  for(int i = 1; i < n2-1; i++){
+    double d = (double)i/(double)(n2-1) * l2;
+    glVertex3d(p1[0] + t2[0]*d, 
+	       p1[1] + t2[1]*d, 
+	       p1[2] + t2[2]*d);
+    glVertex3d(p1[0] + t2[0]*d + t1[0]*l1, 
+	       p1[1] + t2[1]*d + t1[1]*l1, 
+	       p1[2] + t2[2]*d + t1[2]*l1);
+  }
+
+  glEnd();
+  glDisable(GL_LINE_STIPPLE);
+  gl2psDisable(GL2PS_LINE_STIPPLE);
+}
+
+void Draw_3DGrid(int mode, int tics, char *format, double bb[6])
+{
+  // mode 0: nothing
+  //      1: axes
+  //      2: box
+  //      3: full grid
+  //      4: open grid
+
+  if( (mode < 1) || 
+      (bb[0] == bb[1] && bb[2] == bb[3]) ||
+      (bb[0] == bb[1] && bb[4] == bb[5]) ||
+      (bb[2] == bb[3] && bb[4] == bb[5]) )
+    return;
+  
+  double xmin = bb[0], xmax = bb[1];
+  double ymin = bb[2], ymax = bb[3];
+  double zmin = bb[4], zmax = bb[5];
+
+  glColor4ubv((GLubyte *) & CTX.color.fg);
+
+  glBegin(GL_LINES);
+  // 3 axes
+  glVertex3d(xmin, ymin, zmin); glVertex3d(xmax, ymin, zmin);
+  glVertex3d(xmin, ymin, zmin); glVertex3d(xmin, ymax, zmin);
+  glVertex3d(xmin, ymin, zmin); glVertex3d(xmin, ymin, zmax);
+  // open box
+  if(mode > 1){
+    glVertex3d(xmin, ymax, zmin); glVertex3d(xmax, ymax, zmin);
+    glVertex3d(xmax, ymin, zmin); glVertex3d(xmax, ymax, zmin);
+    glVertex3d(xmin, ymin, zmax); glVertex3d(xmax, ymin, zmax);
+    glVertex3d(xmax, ymin, zmin); glVertex3d(xmax, ymin, zmax);
+    glVertex3d(xmin, ymin, zmax); glVertex3d(xmin, ymax, zmax);
+    glVertex3d(xmin, ymax, zmin); glVertex3d(xmin, ymax, zmax);
+  }
+  // closed box
+  if(mode == 2 || mode == 3){
+    glVertex3d(xmax, ymax, zmax); glVertex3d(xmin, ymax, zmax);
+    glVertex3d(xmax, ymax, zmax); glVertex3d(xmax, ymin, zmax);
+    glVertex3d(xmax, ymax, zmax); glVertex3d(xmax, ymax, zmin);
+  }
+  glEnd();
+
+  double orig[3] = {xmin, ymin, zmin};
+  double xx[3] = {xmax, ymin, zmin};
+  double yy[3] = {xmin, ymax, zmin};
+  double zz[3] = {xmin, ymin, zmax};
+  double dxm[3] = {0., (ymin != ymax) ? -1. : 0., (zmin != zmax) ? -1. : 0.};
+  double dym[3] = {(xmin != xmax) ? -1. : 0., 0., (zmin != zmax) ? -1. : 0.};
+  double dzm[3] = {(xmin != xmax) ? -1. : 0., (ymin != ymax) ? -1. : 0., 0.};
+
+  int nx = (xmin != xmax) ? Draw_Tics(0, tics, format, orig, xx, dxm) : 0;
+  int ny = (ymin != ymax) ? Draw_Tics(1, tics, format, orig, yy, dym) : 0;
+  int nz = (zmin != zmax) ? Draw_Tics(2, tics, format, orig, zz, dzm) : 0;
+  
+  if(mode > 2){
+    Draw_GridStipple(nx, ny, orig, xx, yy);
+    Draw_GridStipple(ny, nz, orig, yy, zz);
+    Draw_GridStipple(nx, nz, orig, xx, zz);
+  }
+
+  if(mode == 3){
+    double orig2[3] = {xmax, ymax, zmax};
+    double xy[3] = {xmax, ymax, zmin};
+    double yz[3] = {xmin, ymax, zmax};
+    double xz[3] = {xmax, ymin, zmax};
+    if(zmin != zmax) Draw_GridStipple(nx, ny, orig2, yz, xz);
+    if(xmin != xmax) Draw_GridStipple(ny, nz, orig2, xz, xy);
+    if(ymin != ymax) Draw_GridStipple(nx, nz, orig2, yz, xy);
+  }
+}
diff --git a/Graphics/Makefile b/Graphics/Makefile
index 4afb9071bffe5854e7f3e85613e58d003e390834..f2f37ac4a3e4489a1f80328e51daf0b14e575ba7 100644
--- a/Graphics/Makefile
+++ b/Graphics/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.67 2005-01-08 20:15:12 geuzaine Exp $
+# $Id: Makefile,v 1.68 2005-03-11 05:47:55 geuzaine Exp $
 #
 # Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 #
@@ -134,7 +134,7 @@ Entity.o: Entity.cpp ../Mesh/Mesh.h ../DataStr/List.h ../DataStr/Tree.h \
   ../Common/Gmsh.h ../Common/Message.h ../DataStr/Malloc.h \
   ../DataStr/Tools.h ../Common/GmshUI.h ../Numeric/Numeric.h Draw.h \
   ../Common/Views.h ../Common/ColorTable.h ../Common/GmshMatrix.h \
-  ../Common/AdaptiveViews.h ../Common/Context.h
+  ../Common/AdaptiveViews.h ../Common/Context.h gl2ps.h
 ReadImg.o: ReadImg.cpp ReadImg.h ../Common/Gmsh.h ../Common/Message.h \
   ../DataStr/Malloc.h ../DataStr/List.h ../DataStr/Tree.h \
   ../DataStr/avl.h ../DataStr/Tools.h ../Common/GmshUI.h \
diff --git a/Graphics/Mesh.cpp b/Graphics/Mesh.cpp
index 11367aa6554d99caf3bfc2aeb31086028f3ebae3..c53f8328b7e7b0d6cd924cdedcc3286b2ff34615 100644
--- a/Graphics/Mesh.cpp
+++ b/Graphics/Mesh.cpp
@@ -1,4 +1,4 @@
-// $Id: Mesh.cpp,v 1.120 2005-01-09 02:18:59 geuzaine Exp $
+// $Id: Mesh.cpp,v 1.121 2005-03-11 05:47:55 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -250,7 +250,7 @@ void Draw_Mesh(Mesh * M)
   // draw the big moving axes
 
   if(CTX.axes)
-    Draw_Axes(CTX.lc_middle / 4.);
+    Draw_Axes();
 
   // draw any plugin-specific stuff
   
diff --git a/Graphics/Post.cpp b/Graphics/Post.cpp
index 4cd280facf4810b7cbfd1b38d1c482eb87bcc5d6..622f2209a9392d17ac3575de05094f73d901040a 100644
--- a/Graphics/Post.cpp
+++ b/Graphics/Post.cpp
@@ -1,4 +1,4 @@
-// $Id: Post.cpp,v 1.94 2005-01-14 22:53:20 geuzaine Exp $
+// $Id: Post.cpp,v 1.95 2005-03-11 05:47:56 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -291,6 +291,15 @@ void Get_Coords(Post_View *v, int type, int nbnod, int nbcomp,
 				v->ViewIndexForGenRaise);
     ApplyGeneralizedRaise(v, nbnod, ext_nbcomp, ext_vals, x2, y2, z2);
   }
+
+  for(int i = 0; i < nbnod; i++){
+    if(x2[i] < v->TmpBBox[0]) v->TmpBBox[0] = x2[i];
+    if(x2[i] > v->TmpBBox[1]) v->TmpBBox[1] = x2[i];
+    if(y2[i] < v->TmpBBox[2]) v->TmpBBox[2] = y2[i];
+    if(y2[i] > v->TmpBBox[3]) v->TmpBBox[3] = y2[i];
+    if(z2[i] < v->TmpBBox[4]) v->TmpBBox[4] = z2[i];
+    if(z2[i] > v->TmpBBox[5]) v->TmpBBox[5] = z2[i];
+  }
 }
 
 // Compare barycenters with viewpoint (eye)
@@ -552,6 +561,13 @@ void Draw_Post(void)
       if(v->UseGenRaise)
 	InitGeneralizedRaise(v);
 
+      if(v->Changed){
+	for(int i = 0; i < 3; i++) {
+	  v->TmpBBox[2 * i] = VAL_INF;
+	  v->TmpBBox[2 * i + 1] = -VAL_INF;
+	}
+      }
+
       // initialize alpha blending for transparency
       if(CTX.alpha && ColorTable_IsAlpha(&v->CT)){
 	if(v->FakeTransparency){
@@ -763,15 +779,27 @@ void Draw_Post(void)
 	Draw_Text2D3D(3, v->TimeStep, v->NbT3, v->T3D, v->T3C);
       }
 
+      for(int i = 0; i < 6; i++)
+	glDisable((GLenum)(GL_CLIP_PLANE0 + i));
+
+      if(v->Grid && v->Type == DRAW_POST_3D){
+	int ok = 1;
+	for(int i = 0; i < 6; i++) {
+	  if(fabs(v->TmpBBox[i]) == VAL_INF){
+	    ok = 0;
+	    break;
+	  }
+	}
+	if(ok)
+	  Draw_3DGrid(v->Grid, v->NbAbscissa, v->AbscissaFormat, v->TmpBBox);
+      }
+      
       // reset alpha blending
       if(CTX.alpha){
 	glDisable(GL_BLEND);
 	glEnable(GL_DEPTH_TEST);
       }
 
-      for(int i = 0; i < 6; i++)
-	glDisable((GLenum)(GL_CLIP_PLANE0 + i));
-
       v->Changed = 0;
     }
   }
diff --git a/Graphics/PostElement.cpp b/Graphics/PostElement.cpp
index d1ec4ae1dff8d7765831b6dd0fcbb2b26a2fe516..2741dda4c6c85cf46cee3ecaa5f97c93ea182f62 100644
--- a/Graphics/PostElement.cpp
+++ b/Graphics/PostElement.cpp
@@ -1,4 +1,4 @@
-// $Id: PostElement.cpp,v 1.61 2005-01-08 20:15:12 geuzaine Exp $
+// $Id: PostElement.cpp,v 1.62 2005-03-11 05:47:56 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -911,6 +911,13 @@ void Draw_VectorElement(int type, Post_View * View, int preproNormals,
       xx[k] = X[k] + fact * Val[k][0];
       yy[k] = Y[k] + fact * Val[k][1];
       zz[k] = Z[k] + fact * Val[k][2];
+      // update the dynamic bounding box
+      if(xx[k] < View->TmpBBox[0]) View->TmpBBox[0] = xx[k];
+      if(xx[k] > View->TmpBBox[1]) View->TmpBBox[1] = xx[k];
+      if(yy[k] < View->TmpBBox[2]) View->TmpBBox[2] = yy[k];
+      if(yy[k] > View->TmpBBox[3]) View->TmpBBox[3] = yy[k];
+      if(zz[k] < View->TmpBBox[4]) View->TmpBBox[4] = zz[k];
+      if(zz[k] > View->TmpBBox[5]) View->TmpBBox[5] = zz[k];
     }
     
     int ts = View->TimeStep;
diff --git a/Numeric/Numeric.cpp b/Numeric/Numeric.cpp
index 04fa3ecb80bc75f3bbe019404d7375866cb0b0da..75700c0c224b95671ca8f928246cd296ebeef300 100644
--- a/Numeric/Numeric.cpp
+++ b/Numeric/Numeric.cpp
@@ -1,4 +1,4 @@
-// $Id: Numeric.cpp,v 1.22 2005-01-12 19:10:41 geuzaine Exp $
+// $Id: Numeric.cpp,v 1.23 2005-03-11 05:47:56 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -113,9 +113,14 @@ void prosca(double a[3], double b[3], double *c)
   *c = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
 }
 
+double norm3(double a[3])
+{
+  return sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
+}
+
 double norme(double a[3])
 {
-  double mod = sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
+  double mod = norm3(a);
   if(mod != 0.0){
     a[0] /= mod;
     a[1] /= mod;
diff --git a/Numeric/Numeric.h b/Numeric/Numeric.h
index a04f8b790928e6b2993410492ba18bfdbe2c577a..19afc092b19126df04ff7963c6db59bf84dfcde3 100644
--- a/Numeric/Numeric.h
+++ b/Numeric/Numeric.h
@@ -62,6 +62,7 @@ double myacos(double a);
 void prodve(double a[3], double b[3], double c[3]);
 void prosca(double a[3], double b[3], double *c);
 void matvec(double mat[3][3], double vec[3], double res[3]);
+double norm3(double a[3]);
 double norme(double a[3]);
 void normal3points(double x0, double y0, double z0,
 		   double x1, double y1, double z1,
diff --git a/Plugin/Annotate.cpp b/Plugin/Annotate.cpp
index 126abd67c1179504df5dec06c3efc8bd0a1f7e63..392e53be27f4ac5a19792f4c201f42e196acd193 100644
--- a/Plugin/Annotate.cpp
+++ b/Plugin/Annotate.cpp
@@ -1,4 +1,4 @@
-// $Id: Annotate.cpp,v 1.8 2005-03-09 07:35:11 geuzaine Exp $
+// $Id: Annotate.cpp,v 1.9 2005-03-11 05:47:56 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -67,9 +67,7 @@ static double getStyle()
   int fontsize = (int)AnnotateOptions_Number[4].def, font = 0, align = 0;
 #if defined(HAVE_FLTK)
   font = GetFontIndex(AnnotateOptions_String[1].def);
-  // align only makes sense in screen coordinates at the moment:
-  if(!AnnotateOptions_Number[3].def)
-    align = GetFontAlign(AnnotateOptions_String[2].def);
+  align = GetFontAlign(AnnotateOptions_String[2].def);
 #endif
   return (double)((align<<16)|(font<<8)|(fontsize));
 }
@@ -203,14 +201,14 @@ void GMSH_AnnotatePlugin::getInfos(char *author, char *copyright,
   strcpy(author, "C. Geuzaine (geuz@geuz.org)");
   strcpy(copyright, "DGR (www.multiphysics.com)");
   strcpy(help_text,
-         "Plugin(Annotate) adds the text string `Text' in\n"
-	 "font `Font' and size `FontSize' in the view `iView'.\n"
+         "Plugin(Annotate) adds the text string `Text', in\n"
+	 "font `Font' and size `FontSize', in the view `iView'.\n"
 	 "If `3D' is equal to 1, the plugin inserts the\n"
 	 "string in model coordinates at the position\n"
 	 "(`X',`Y',`Z'). If `3D' is equal to 0, the plugin\n"
 	 "inserts the string in screen coordinates at the\n"
-	 "position (`X',`Y'), and aligns it according to\n"
-	 "`Align'. If `iView' < 0, the plugin is run on the\n"
+	 "position (`X',`Y'). The string is aligned according\n"
+	 "to `Align'. If `iView' < 0, the plugin is run on the\n"
 	 "current view.\n"
 	 "\n"
 	 "Plugin(Annotate) is executed in-place.\n");
diff --git a/TODO b/TODO
index 45151248ed91a214fc3e0c8574bc1ba9ad726f35..747b42454e4a0699a141ad1ff0e70a75d71debc9 100644
--- a/TODO
+++ b/TODO
@@ -1,4 +1,4 @@
-$Id: TODO,v 1.86 2005-02-28 23:57:59 geuzaine Exp $
+$Id: TODO,v 1.87 2005-03-11 05:47:53 geuzaine Exp $
 
 ********************************************************************
 
@@ -93,11 +93,6 @@ index-based format)
 
 ********************************************************************
 
-Should Raise & offsets modify the bounding boxes? (I don't think
-so --Christophe)
-
-********************************************************************
-
 Test and reintroduce the cylindrical surfaces (cylinder, cone, torus)
 
 ********************************************************************
diff --git a/doc/VERSIONS b/doc/VERSIONS
index 8c5d6434ea8e482f24ae95c9c3fd1f73e2d06f24..4d1bce9c62e4616f28508934c2cd692ae4365aa9 100644
--- a/doc/VERSIONS
+++ b/doc/VERSIONS
@@ -1,11 +1,12 @@
-$Id: VERSIONS,v 1.315 2005-03-09 09:21:26 geuzaine Exp $
+$Id: VERSIONS,v 1.316 2005-03-11 05:47:56 geuzaine Exp $
 
 New since 1.59: added support for discrete curves; new Window menu on
 Mac OS X; generalized all octree-based plugins (CutGrid, StreamLines,
 Probe, etc.) to handle all element types (and not only scalar and
 vector triangles+tetrahedra); generalized Plugin(Evaluate) and
-Plugin(Extract); enhanced clipping plane interface; various small
-enhancements and bug fixes.
+Plugin(Extract); enhanced clipping plane interface; new grid options
+for 3D post-processing views; various small enhancements and bug
+fixes.
 
 New in 1.59: added support for discrete (triangulated) surfaces,
 either in STL format or with the new "Discrete Surface" command; added
diff --git a/doc/texinfo/gmsh.texi b/doc/texinfo/gmsh.texi
index 7e9666c7535a7ce189a0877bd13e10774e860e09..d551a0f849e1b9f42092c21d3e4eb06bdfd6f918 100644
--- a/doc/texinfo/gmsh.texi
+++ b/doc/texinfo/gmsh.texi
@@ -1,5 +1,5 @@
 \input texinfo.tex @c -*-texinfo-*-
-@c $Id: gmsh.texi,v 1.173 2005-02-20 06:36:59 geuzaine Exp $
+@c $Id: gmsh.texi,v 1.174 2005-03-11 05:47:56 geuzaine Exp $
 @c
 @c Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 @c
@@ -2316,10 +2316,9 @@ e.g., @ref{t8.geo}, and @ref{t9.geo}).
 The two following sections summarize all available post-processing commands
 and options. Most options apply to both 2D and 3D plots (colormaps,
 point/line sizes, interval types, time step selection, etc.), but some are
-peculiar to 3D (lightning, element selection, etc.) or 2D plots (graph
-style, labels, etc.). Note that 2D plots can be positioned explicitly
-inside the graphical window, or be automatically positioned in order to
-avoid overlaps.
+peculiar to 3D (lightning, element selection, etc.) or 2D plots (abscissa
+labels, etc.). Note that 2D plots can be positioned explicitly inside the
+graphical window, or be automatically positioned in order to avoid overlaps.
 
 Sample post-processing files in human-readable ``parsed'' format
 (@pxref{Parsed post-processing file format}) are available in the
@@ -3182,12 +3181,14 @@ coordinates, measured from the top-left corner of the window. If the first
 from the right (respectively bottom) edge of the window. If the value of the
 first (respectively second) @var{expression} is larger than 99999, the
 string is centered horizontally (respectively vertically). If the third
-@var{expression} is equal to zero, the text is left-aligned and displayed
-using the default font and size. Otherwise, the third @var{expression} is
-converted into an integer whose eight lower bits give the font size, whose
-eight next bits select the font (the index corresponds to the position in
-the font menu in the GUI), and whose eight next bits define the text
-alignment (0=left, 1=center, 2=right).
+@var{expression} is equal to zero, the text is aligned bottom-left and
+displayed using the default font and size. Otherwise, the third
+@var{expression} is converted into an integer whose eight lower bits give
+the font size, whose eight next bits select the font (the index corresponds
+to the position in the font menu in the GUI), and whose eight next bits
+define the text alignment (0=bottom-left, 1=bottom-center, 2=bottom-right,
+3=top-left, 4=top-center, 5=top-right, 6=center-left, 7=center-center,
+8=center-right).
 
 For the 3D text objects, the three first @w{@var{expression}s} in
 @var{list-of-coords} give the position of the leftmost element of the string
@@ -3332,12 +3333,13 @@ where @var{index} gives the starting index of the string in
 the position is measured from the right (respectively bottom) edge of the
 window. If @var{coord1} (respectively @var{coord2}) is larger than 99999,
 the string is centered horizontally (respectively vertically).  If
-@var{style} is equal to zero, the text is left-aligned and displayed using
-the default font and size. Otherwise, @var{style} is converted into an
+@var{style} is equal to zero, the text is aligned bottom-left and displayed
+using the default font and size. Otherwise, @var{style} is converted into an
 integer whose eight lower bits give the font size, whose eight next bits
 select the font (the index corresponds to the position in the font menu in
-the GUI), and whose eight next bits define the text alignment (0=left,
-1=center, 2=right).
+the GUI), and whose eight next bits define the text alignment
+(0=bottom-left, 1=bottom-center, 2=bottom-right, 3=top-left, 4=top-center,
+5=top-right, 6=center-left, 7=center-center, 8=center-right).
 
 @item @var{text2d-chars}
 is a list of @var{nb-text2d-chars} characters. Substrings are separated with
diff --git a/doc/texinfo/opt_general.texi b/doc/texinfo/opt_general.texi
index 16b36af3fc72260881a3283b6986f6b0d048b4b2..cbfaf9bcf7b699749fbefad78ab3712aa5bb9283 100644
--- a/doc/texinfo/opt_general.texi
+++ b/doc/texinfo/opt_general.texi
@@ -74,6 +74,11 @@ Display the axes linked to the model@*
 Default value: @code{0}@*
 Saved in: @code{General.OptionsFileName}
 
+@item General.AxesSize
+Size (in pixels) of moving axes@*
+Default value: @code{100}@*
+Saved in: @code{General.OptionsFileName}
+
 @item General.Clip0
 Enable clipping plane 0 (Geometry=2^0, Mesh=2^1, View[i]=2^(2+i))@*
 Default value: @code{0}@*
diff --git a/doc/texinfo/opt_mesh.texi b/doc/texinfo/opt_mesh.texi
index fa326e0a7b61e59016c38c0158044508b05a95f7..c277edbcda7912baf730f37331f0b68f08c39d9a 100644
--- a/doc/texinfo/opt_mesh.texi
+++ b/doc/texinfo/opt_mesh.texi
@@ -110,7 +110,7 @@ Default value: @code{0}@*
 Saved in: @code{General.OptionsFileName}
 
 @item Mesh.Interactive
-Show the construction of the 2D mesh in real time (only with the 2D anisotropic algorithm)@*
+Show the construction of 2D anisotropic mesh in real time@*
 Default value: @code{0}@*
 Saved in: @code{General.OptionsFileName}
 
diff --git a/doc/texinfo/opt_plugin.texi b/doc/texinfo/opt_plugin.texi
index 8e6f85c13386f15335bd0909e11e9f8d93d02e24..663378f23d353f1145b8a084776a32172bbc3d33 100644
--- a/doc/texinfo/opt_plugin.texi
+++ b/doc/texinfo/opt_plugin.texi
@@ -1,13 +1,13 @@
 @ftable @code
 @item Plugin(Annotate)
-Plugin(Annotate) adds the text string `Text' in
-font `Font' and size `FontSize' in the view `iView'.
+Plugin(Annotate) adds the text string `Text', in
+font `Font' and size `FontSize', in the view `iView'.
 If `3D' is equal to 1, the plugin inserts the
 string in model coordinates at the position
 (`X',`Y',`Z'). If `3D' is equal to 0, the plugin
 inserts the string in screen coordinates at the
-position (`X',`Y'), and aligns it according to
-`Align'. If `iView' < 0, the plugin is run on the
+position (`X',`Y'). The string is aligned according
+to `Align'. If `iView' < 0, the plugin is run on the
 current view.
 
 Plugin(Annotate) is executed in-place.
diff --git a/doc/texinfo/opt_view.texi b/doc/texinfo/opt_view.texi
index 344b519da18e504d57b023245ebfeaa370c8f3be..49a30f3684df9a8a37c2dfe186a63a442776a2cf 100644
--- a/doc/texinfo/opt_view.texi
+++ b/doc/texinfo/opt_view.texi
@@ -5,7 +5,7 @@ Default value: @code{""}@*
 Saved in: @code{General.OptionsFileName}
 
 @item View.AbscissaFormat
-Abscissa number format for 2D graphs (in standard C form)@*
+Abscissa number format (in standard C form)@*
 Default value: @code{"%.3g"}@*
 Saved in: @code{General.OptionsFileName}
 
@@ -230,8 +230,8 @@ Default value: @code{-1}@*
 Saved in: @code{General.OptionsFileName}
 
 @item View.Grid
-Grid mode for 2D graphs (0=none, 1=simple, 2=frame, 3=grid)@*
-Default value: @code{2}@*
+Grid mode (0=none, 1=axes, 2=box, 3=full grid, 4=open grid)@*
+Default value: @code{0}@*
 Saved in: @code{General.OptionsFileName}
 
 @item View.Height
@@ -305,7 +305,7 @@ Default value: @code{0}@*
 Saved in: @code{-}
 
 @item View.NbAbscissa
-Number of abscissa intervals for 2D graphs@*
+Number of tics on the grid axes@*
 Default value: @code{5}@*
 Saved in: @code{General.OptionsFileName}
 
diff --git a/doc/texinfo/shortcuts.texi b/doc/texinfo/shortcuts.texi
index d36760166da907d43a0cf43ba875d63dd8c86b27..c280ec2100227230c9940b93d81a9e3ce54033c5 100644
--- a/doc/texinfo/shortcuts.texi
+++ b/doc/texinfo/shortcuts.texi
@@ -94,6 +94,8 @@ Loop through predefined color schemes
 Change surface mesh display mode (solid/wireframe)
 @item Alt+f
 Change redraw mode (fast/full) 
+@item Alt+g
+Loop through grid modes for all post-processing views 
 @item Alt+h
 Hide/show all post-processing views 
 @item Alt+i