$ git clone http://gcodetool.ion.nu/gcodetool.git
commit 5679fe6ba70680e29491bf9288e4cce44bdc4686
Author: Alicia <...>
Date:   Mon Oct 7 18:37:51 2019 +0200

    Fixed minor issues in the 'preview' subcommand.

diff --git a/preview.c b/preview.c
index e2402ef..fc49091 100644
--- a/preview.c
+++ b/preview.c
@@ -102,16 +102,16 @@ int gtool_preview(const char* filename, struct img* img, double angle, double zr
       {
         olde=eval;
         vector_draw(&vectors, oldx, oldy, xval, yval, zval);
+        if(isnan(max[0]) || xval>max[0]){max[0]=xval;}
+        if(isnan(max[1]) || yval>max[1]){max[1]=yval;}
+        if(isnan(max[2]) || zval>max[2]){max[2]=zval;}
+        if(isnan(min[0]) || xval<min[0]){min[0]=xval;}
+        if(isnan(min[1]) || yval<min[1]){min[1]=yval;}
+        if(isnan(min[2]) || zval<min[2]){min[2]=zval;}
       }
       oldx=xval;
       oldy=yval;
       oldz=zval;
-      if(isnan(max[0]) || xval>max[0]){max[0]=xval;}
-      if(isnan(max[1]) || yval>max[1]){max[1]=yval;}
-      if(isnan(max[2]) || zval>max[2]){max[2]=zval;}
-      if(isnan(min[0]) || xval<min[0]){min[0]=xval;}
-      if(isnan(min[1]) || yval<min[1]){min[1]=yval;}
-      if(isnan(min[2]) || zval<min[2]){min[2]=zval;}
     }
     if(cmd->key=='G' && cmd->num==92)
     {
@@ -120,7 +120,7 @@ int gtool_preview(const char* filename, struct img* img, double angle, double zr
     }
   }
   gcode_free(gcode);
-  double center[]={(min[0]+max[0])/2, (min[1]+max[1])/2};
+  double center[]={(min[0]+max[0])/2, (min[1]+max[1])/2, (min[2]+max[2])/2};
   // Figure out how to scale things
   double scale=0; // max[0];
   unsigned int i;
@@ -157,8 +157,8 @@ l->y[0]=sin(zrot)*cy(oldl->y[0])+cos(zrot)*cx(oldl->x[0]);
 l->x[0]=sin(zrot+M_PI_2)*cy(oldl->y[0])+cos(zrot+M_PI_2)*cx(oldl->x[0]);
 l->y[1]=sin(zrot)*cy(oldl->y[1])+cos(zrot)*cx(oldl->x[1]);
 l->x[1]=sin(zrot+M_PI_2)*cy(oldl->y[1])+cos(zrot+M_PI_2)*cx(oldl->x[1]);
-l->y[0]=l->y[0]*cos(angle)+vectors.layers[i].z*scale*sin(angle);
-l->y[1]=l->y[1]*cos(angle)+vectors.layers[i].z*scale*sin(angle);
+l->y[0]=l->y[0]*cos(angle)+(vectors.layers[i].z-center[2])*scale*sin(angle);
+l->y[1]=l->y[1]*cos(angle)+(vectors.layers[i].z-center[2])*scale*sin(angle);
 #define polcmp(n) ((n[0]>=0&&n[1]>=0) || (n[0]<0&&n[1]<0))
         // Skip lines that are just out of view (saves resources when zoomed in far)
         if(fabs(l->x[0])>img->width/2 && fabs(l->x[1])>img->width/2 && polcmp(l->x)){continue;}
@@ -268,7 +268,12 @@ int gtool_preview_arg(int argc, char** argv)
            "--r[xz] <angle>             = rotate X or Z <angle> degrees\n"
            "-o/--output <method> <file> = select output method and filename\n"
            "-s/--size <width>x<height>  = set output size\n"
-           "TODO: scale etc.\n", argv[0], argv[1]);
+           "TODO: scale etc.\n"
+           "\n"
+           "Available output methods:\n"
+           "term   (display using ANSI escape codes, use arrows and +/- to navigate)\n"
+           "pnm\n"
+      ,argv[0], argv[1]);
     return -1;
   }
 // TODO: Mechanism for selecting method by what's available. Not relevant until there's another direct display method
diff --git a/preview_term.c b/preview_term.c
index 76e8c8b..c11f5d3 100644
--- a/preview_term.c
+++ b/preview_term.c
@@ -110,7 +110,7 @@ struct img* gtool_preview_term(int width, int height, const char* filename)
   struct img_term* img=malloc(sizeof(struct img_term));
   if(filename && strcmp(filename, "-"))
   {
-    img->fd=open(filename, O_WRONLY|O_TRUNC);
+    img->fd=open(filename, O_WRONLY|O_TRUNC|O_CREAT, 0644);
   }else{
     img->fd=1;
   }
@@ -138,7 +138,7 @@ struct img* gtool_preview_term(int width, int height, const char* filename)
   img->img.drawpixel=cb_drawpixel;
   img->img.clear=cb_clear;
   img->img.display=cb_display;
-  img->img.input=cb_input;
+  img->img.input=(img->fd==1)?cb_input:0;
   img->img.clean=cb_clean;
   return (struct img*)img;
 }