http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.03.tar.gz
[xscreensaver] / hacks / glx / glsnake.c
index 66c125551948e771a6bce7891ecc6e44d5eab0ef..bc9c631399f9057f23d1ced0014bd7299b66ddce 100644 (file)
@@ -38,7 +38,8 @@ extern XtAppContext app;
 #define DEF_YSPIN       "0.10"
 #define DEF_ZSPIN       "0.14"
 #define DEF_SCARYCOLOUR "False"
-#define DEF_LABELS             "True"
+#define DEF_LABELS     "True"
+#define DEF_BBOX        "False"
 
 #define DEFAULTS       "*delay:        30000        \n" \
                        "*count:        30            \n" \
@@ -54,6 +55,7 @@ extern XtAppContext app;
                        "*scarycolour:" DEF_SCARYCOLOUR " \n" \
                        "*labels:     " DEF_LABELS "  \n" \
                        "*labelfont:  -*-times-bold-r-normal-*-180-*\n" \
+                       "*bbox:       " DEF_BBOX     "\n" \
 
 
 
@@ -81,42 +83,42 @@ extern XtAppContext app;
 #define RIGHT 3
 
 typedef struct model_s {
-       char * name;
-       float node[24];
+  char * name;
+  float node[24];
 } model_t;
 
 typedef struct nodeang_s {
-       float cur_angle;
-       float dest_angle;
+  float cur_angle;
+  float dest_angle;
 } nodeang_t;
 
 typedef struct {
-       GLXContext * glx_context;
-
-       int node_list; /* name of the display list */
-       int is_cyclic;
-       int is_legal;
-       int last_turn;
-       int selected;
-       struct timeval last_iteration;
-       struct timeval last_morph;
-       int morphing;
-       nodeang_t node[24];
-       GLfloat roty;
-       GLfloat rotz;
-       int paused;
-       int dragging;
-       int m_count;
-       int m;
-       int cur_model;
-       int interactive;
-       GLfloat colour_t[3];
-       GLfloat colour_i[3];
-       GLfloat colour[3];
-       model_t * models;
-
-       XFontStruct * font;
-       GLuint font_list;
+  GLXContext * glx_context;
+
+  int node_list; /* name of the display list */
+  int is_cyclic;
+  int is_legal;
+  int last_turn;
+  int selected;
+  struct timeval last_iteration;
+  struct timeval last_morph;
+  int morphing;
+  nodeang_t node[24];
+  GLfloat roty;
+  GLfloat rotz;
+  int paused;
+  int dragging;
+  int m_count;
+  int m;
+  int cur_model;
+  int interactive;
+  GLfloat colour_t[3];
+  GLfloat colour_i[3];
+  GLfloat colour[3];
+  model_t * models;
+
+  XFontStruct * font;
+  GLuint font_list;
 } glsnake_configuration;
 
 static glsnake_configuration *glc = NULL;
@@ -130,6 +132,7 @@ static GLfloat yspin;
 static GLfloat zspin;
 static Bool scarycolour;
 static Bool labels;
+static Bool do_bbox;
 
 static XrmOptionDescRec opts[] = {
   { "-speed", ".speed", XrmoptionSepArg, 0 },
@@ -143,6 +146,10 @@ static XrmOptionDescRec opts[] = {
   { "+scarycolour", ".scarycolour", XrmoptionNoArg, "False" },
   { "-labels", ".labels", XrmoptionNoArg, "True" },
   { "+labels", ".labels", XrmoptionNoArg, "False" },
+#if 0
+  { "-bbox",   ".bbox",  XrmoptionNoArg, "True" },
+  { "+bbox",   ".bbox",  XrmoptionNoArg, "False" },
+#endif
 };
 
 static argtype vars[] = {
@@ -156,6 +163,7 @@ static argtype vars[] = {
 /*  {(caddr_t *) &interactive, "interactive", "Interactive", DEF_INTERACTIVE, t_Bool}, */
   {(caddr_t *) &scarycolour, "scarycolour", "Scary Colour", DEF_SCARYCOLOUR, t_Bool},
   {(caddr_t *) &labels, "labels", "Labels", DEF_LABELS, t_Bool},
+  {(caddr_t *) &do_bbox, "bbox",  "BBox",   DEF_BBOX,   t_Bool},
 };
 
 ModeSpecOpt sws_opts = {countof(opts), opts, countof(vars), vars, NULL};
@@ -163,76 +171,76 @@ ModeSpecOpt sws_opts = {countof(opts), opts, countof(vars), vars, NULL};
 /* prism models */
 #define VOFFSET 0.045
 float solid_prism_v[][3] = {
-       /* first corner, bottom left front */
-       { VOFFSET, VOFFSET, 1.0 },
-       { VOFFSET, 0.0, 1.0 - VOFFSET },
-       { 0.0, VOFFSET, 1.0 - VOFFSET },
-       /* second corner, rear */
-       { VOFFSET, VOFFSET, 0.00 },
-       { VOFFSET, 0.0, VOFFSET },
-       { 0.0, VOFFSET, VOFFSET },
-       /* third, right front */
-       { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 1.0 },
-       { 1.0 - VOFFSET / M_SQRT1_2, 0.0, 1.0 - VOFFSET },
-       { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, 1.0 - VOFFSET },
-       /* fourth, right rear */
-       { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 0.0 },
-       { 1.0 - VOFFSET / M_SQRT1_2, 0.0, VOFFSET },
-       { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, VOFFSET },
-       /* fifth, upper front */
-       { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 1.0 },
-       { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, 1.0 - VOFFSET },
-       { 0.0, 1.0 - VOFFSET / M_SQRT1_2, 1.0 - VOFFSET},
-       /* sixth, upper rear */
-       { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 0.0 },
-       { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, VOFFSET },
-       { 0.0, 1.0 - VOFFSET / M_SQRT1_2, VOFFSET }
+  /* first corner, bottom left front */
+  { VOFFSET, VOFFSET, 1.0 },
+  { VOFFSET, 0.0, 1.0 - VOFFSET },
+  { 0.0, VOFFSET, 1.0 - VOFFSET },
+  /* second corner, rear */
+  { VOFFSET, VOFFSET, 0.00 },
+  { VOFFSET, 0.0, VOFFSET },
+  { 0.0, VOFFSET, VOFFSET },
+  /* third, right front */
+  { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 1.0 },
+  { 1.0 - VOFFSET / M_SQRT1_2, 0.0, 1.0 - VOFFSET },
+  { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, 1.0 - VOFFSET },
+  /* fourth, right rear */
+  { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 0.0 },
+  { 1.0 - VOFFSET / M_SQRT1_2, 0.0, VOFFSET },
+  { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, VOFFSET },
+  /* fifth, upper front */
+  { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 1.0 },
+  { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, 1.0 - VOFFSET },
+  { 0.0, 1.0 - VOFFSET / M_SQRT1_2, 1.0 - VOFFSET},
+  /* sixth, upper rear */
+  { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 0.0 },
+  { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, VOFFSET },
+  { 0.0, 1.0 - VOFFSET / M_SQRT1_2, VOFFSET }
 };
 
 /* normals */
 float solid_prism_n[][3] = {
-       /* corners */
-       { -VOFFSET, -VOFFSET, VOFFSET },
-       { VOFFSET, -VOFFSET, VOFFSET },
-       { -VOFFSET, VOFFSET, VOFFSET },
-       { -VOFFSET, -VOFFSET, -VOFFSET },
-       { VOFFSET, -VOFFSET, -VOFFSET },
-       { -VOFFSET, VOFFSET, -VOFFSET },
-       /* edges */
-       { -VOFFSET, 0.0, VOFFSET },
-       { 0.0, -VOFFSET, VOFFSET },
-       { VOFFSET, VOFFSET, VOFFSET },
-       { -VOFFSET, 0.0, -VOFFSET },
-       { 0.0, -VOFFSET, -VOFFSET },
-       { VOFFSET, VOFFSET, -VOFFSET },
-       { -VOFFSET, -VOFFSET, 0.0 },
-       { VOFFSET, -VOFFSET, 0.0 },
-       { -VOFFSET, VOFFSET, 0.0 },
-       /* faces */
-       { 0.0, 0.0, 1.0 },
-       { 0.0, -1.0, 0.0 },
-       { M_SQRT1_2, M_SQRT1_2, 0.0 },
-       { -1.0, 0.0, 0.0 },
-       { 0.0, 0.0, -1.0 }
+  /* corners */
+  { -VOFFSET, -VOFFSET, VOFFSET },
+  { VOFFSET, -VOFFSET, VOFFSET },
+  { -VOFFSET, VOFFSET, VOFFSET },
+  { -VOFFSET, -VOFFSET, -VOFFSET },
+  { VOFFSET, -VOFFSET, -VOFFSET },
+  { -VOFFSET, VOFFSET, -VOFFSET },
+  /* edges */
+  { -VOFFSET, 0.0, VOFFSET },
+  { 0.0, -VOFFSET, VOFFSET },
+  { VOFFSET, VOFFSET, VOFFSET },
+  { -VOFFSET, 0.0, -VOFFSET },
+  { 0.0, -VOFFSET, -VOFFSET },
+  { VOFFSET, VOFFSET, -VOFFSET },
+  { -VOFFSET, -VOFFSET, 0.0 },
+  { VOFFSET, -VOFFSET, 0.0 },
+  { -VOFFSET, VOFFSET, 0.0 },
+  /* faces */
+  { 0.0, 0.0, 1.0 },
+  { 0.0, -1.0, 0.0 },
+  { M_SQRT1_2, M_SQRT1_2, 0.0 },
+  { -1.0, 0.0, 0.0 },
+  { 0.0, 0.0, -1.0 }
 };
 
 /* vertices */
 float wire_prism_v[][3] = {
-       { 0.0, 0.0, 1.0 },
-       { 1.0, 0.0, 1.0 },
-       { 0.0, 1.0, 1.0 },
-       { 0.0, 0.0, 0.0 },
-       { 1.0, 0.0, 0.0 },
-       { 0.0, 1.0, 0.0 }
+  { 0.0, 0.0, 1.0 },
+  { 1.0, 0.0, 1.0 },
+  { 0.0, 1.0, 1.0 },
+  { 0.0, 0.0, 0.0 },
+  { 1.0, 0.0, 0.0 },
+  { 0.0, 1.0, 0.0 }
 };
 
 /* normals */
 float wire_prism_n[][3] = {
-       { 0.0, 0.0, 1.0},
-       { 0.0,-1.0, 0.0},
-       { M_SQRT1_2, M_SQRT1_2, 0.0},
-       {-1.0, 0.0, 0.0},
-       { 0.0, 0.0,-1.0}
+  { 0.0, 0.0, 1.0},
+  { 0.0,-1.0, 0.0},
+  { M_SQRT1_2, M_SQRT1_2, 0.0},
+  {-1.0, 0.0, 0.0},
+  { 0.0, 0.0,-1.0}
 };
 
 /* default models */
@@ -242,40 +250,41 @@ float wire_prism_n[][3] = {
 #define R 270.0
 
 static model_t default_models[] = { 
-       { "Ball", 
-               { R, R, L, L, R, L, R, R, L, R, L, L, R, R, L, L, R, L, R, R, L, R, L }
-       },
-       { "Snow",
-               { R, R, R, R, L, L, L, L, R, R, R, R, L, L, L, L, R, R, R, R, L, L, L }
-       },
-       { "Propellor",
-               { Z, Z, Z, R, L, R, Z, L, Z, Z, Z, R, L, R, Z, L, Z, Z, Z, R, L, R, Z }
-       },
-       { "Flamingo",
-               { Z, P, Z, Z, Z, Z, Z, P, R, R, P, R, L, P, L, R, P, R, R, Z, Z, Z, P }
-       },
-       { "Cat",
-               { Z, P, P, Z, P, P, Z, L, Z, P, P, Z, P, P, Z, P, P, Z, Z, Z, Z, Z, Z }
-       },
-       { "Rooster",
-               { Z, Z, P, P, Z, L, Z, L, R, P, R, Z, P, P, Z, R, P, R, L, Z, L, Z, P }
-       }
+  { "Ball", 
+    { R, R, L, L, R, L, R, R, L, R, L, L, R, R, L, L, R, L, R, R, L, R, L }
+  },
+  { "Snow",
+    { R, R, R, R, L, L, L, L, R, R, R, R, L, L, L, L, R, R, R, R, L, L, L }
+  },
+  { "Propellor",
+    { Z, Z, Z, R, L, R, Z, L, Z, Z, Z, R, L, R, Z, L, Z, Z, Z, R, L, R, Z }
+  },
+  { "Flamingo",
+    { Z, P, Z, Z, Z, Z, Z, P, R, R, P, R, L, P, L, R, P, R, R, Z, Z, Z, P }
+  },
+  { "Cat",
+    { Z, P, P, Z, P, P, Z, L, Z, P, P, Z, P, P, Z, P, P, Z, Z, Z, Z, Z, Z }
+  },
+  { "Rooster",
+    { Z, Z, P, P, Z, L, Z, L, R, P, R, Z, P, P, Z, R, P, R, L, Z, L, Z, P }
+  }
 };
 
 /* add a model to the model list */
-model_t * add_model(model_t * models, char * name, int * rotations, int * count) {
-       int i;
-       
-       (*count)++;
-       models = realloc(models, sizeof(model_t) * (*count));
-       models[(*count)-1].name = strdup(name);
+model_t * add_model(model_t * models, char * name, int * rotations, int * count)
+{
+  int i;
+  
+  (*count)++;
+  models = realloc(models, sizeof(model_t) * (*count));
+  models[(*count)-1].name = strdup(name);
 #ifdef DEBUG
-       fprintf(stderr, "resized models to %d bytes for model %s\n", sizeof(model_t) * (*count), models[(*count)-1].name);
+  fprintf(stderr, "resized models to %d bytes for model %s\n", sizeof(model_t) * (*count), models[(*count)-1].name);
 #endif
-       for (i = 0; i < 24; i++) {
-               models[(*count)-1].node[i] = rotations[i] * 90.0;
-       }
-       return models;
+  for (i = 0; i < 24; i++) {
+    models[(*count)-1].node[i] = rotations[i] * 90.0;
+  }
+  return models;
 }
 
 /* filename is the name of the file to load
@@ -283,129 +292,131 @@ model_t * add_model(model_t * models, char * name, int * rotations, int * count)
  * returns a new pointer to models
  * count is number of models read
  */
-model_t * load_modelfile(char * filename, model_t * models, int * count) {
-       int c;
-       FILE * f;
-       char buffy[256];
-       int rotations[24];
-       int name = 1;
-       int rots = 0;
-
-       f = fopen(filename, "r");
-       if (f == NULL) {
-               int error_msg_len = strlen(filename) + 33 + 1;
-               char * error_msg = (char *) malloc(sizeof(char) * error_msg_len);
-               sprintf(error_msg, "Unable to open model data file \"%s\"", filename);
-               perror(error_msg);
-               free(error_msg);
-               return models;
-       }
-               
-       while ((c = getc(f)) != EOF) {
-               switch (c) {
-                       /* ignore comments */
-                       case '#':
-                               while (c != '\n')
-                                       c = getc(f);
-                               break;
-                       case ':':
-                               buffy[name-1] = '\0';
-                               name = 0;
-                               break;
-                       case '\n':
-                               if (rots > 0) {
+model_t * load_modelfile(char * filename, model_t * models, int * count)
+{
+  int c;
+  FILE * f;
+  char buffy[256];
+  int rotations[24];
+  int name = 1;
+  int rots = 0;
+
+  f = fopen(filename, "r");
+  if (f == NULL) {
+    int error_msg_len = strlen(filename) + 33 + 1;
+    char * error_msg = (char *) malloc(sizeof(char) * error_msg_len);
+    sprintf(error_msg, "Unable to open model data file \"%s\"", filename);
+    perror(error_msg);
+    free(error_msg);
+    return models;
+  }
+    
+  while ((c = getc(f)) != EOF) {
+    switch (c) {
+      /* ignore comments */
+      case '#':
+        while (c != '\n')
+          c = getc(f);
+        break;
+      case ':':
+        buffy[name-1] = '\0';
+        name = 0;
+        break;
+      case '\n':
+        if (rots > 0) {
 #ifdef DEBUG
-                                       /* print out the model we just read in */
-                                       int i;
-                                       printf("%s: ", buffy);
-                                       for (i = 0; i < rots; i++) {
-                                               switch (rotations[i]) {
-                                                       case LEFT:
-                                                               printf("L");
-                                                               break;
-                                                       case RIGHT:
-                                                               printf("R");
-                                                               break;
-                                                       case PIN:
-                                                               printf("P");
-                                                               break;
-                                                       case ZERO:
-                                                               printf("Z");
-                                                               break;
-                                               }
-                                       }
-                                       printf("\n");
+          /* print out the model we just read in */
+          int i;
+          printf("%s: ", buffy);
+          for (i = 0; i < rots; i++) {
+            switch (rotations[i]) {
+              case LEFT:
+                printf("L");
+                break;
+              case RIGHT:
+                printf("R");
+                break;
+              case PIN:
+                printf("P");
+                break;
+              case ZERO:
+                printf("Z");
+                break;
+            }
+          }
+          printf("\n");
 #endif
-                                       models = add_model(models, buffy, rotations, count);
-                               }
-                               name = 1;
-                               rots = 0;
-                               break;
-                       default:
-                               if (name) {
-                                       buffy[name-1] = c;
-                                       name++;
-                                       if (name > 255)
-                                               fprintf(stderr, "buffy overflow warning\n");
-                               } else {
-                                       switch (c) {
-                                               case '0':
-                                               case 'Z':
-                                                       rotations[rots] = ZERO;
-                                                       rots++;
-                                                       break;
-                                               case '1':
-                                               case 'L':
-                                                       rotations[rots] = LEFT;
-                                                       rots++;
-                                                       break;
-                                               case '2':
-                                               case 'P':
-                                                       rotations[rots] = PIN;
-                                                       rots++;
-                                                       break;
-                                               case '3':
-                                               case 'R':
-                                                       rotations[rots] = RIGHT;
-                                                       rots++;
-                                                       break;
-                                               default:
-                                                       break;
-                                       }
-                               }
-                               break;
-               }
-       }
-       return models;
+          models = add_model(models, buffy, rotations, count);
+        }
+        name = 1;
+        rots = 0;
+        break;
+      default:
+        if (name) {
+          buffy[name-1] = c;
+          name++;
+          if (name > 255)
+            fprintf(stderr, "buffy overflow warning\n");
+        } else {
+          switch (c) {
+            case '0':
+            case 'Z':
+              rotations[rots] = ZERO;
+              rots++;
+              break;
+            case '1':
+            case 'L':
+              rotations[rots] = LEFT;
+              rots++;
+              break;
+            case '2':
+            case 'P':
+              rotations[rots] = PIN;
+              rots++;
+              break;
+            case '3':
+            case 'R':
+              rotations[rots] = RIGHT;
+              rots++;
+              break;
+            default:
+              break;
+          }
+        }
+        break;
+    }
+  }
+  return models;
 }
 
-model_t * load_models(char * dirpath, model_t * models, int * count) {
-       char name[1024];
-       struct dirent * dp;
-       DIR * dfd;
-
-       if ((dfd = opendir(dirpath)) == NULL) {
-               if (strstr(dirpath, "data") == NULL)
-/*                     fprintf(stderr, "load_models: can't read %s/\n", dirpath); */
-               return models;
-       }
-       while ((dp = readdir(dfd)) != NULL) {
-               if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
-                       continue;
-               if (strlen(dirpath) + strlen(dp->d_name) + 2 > sizeof(name))
-                       fprintf(stderr, "load_models: name %s/%s too long\n", dirpath, dp->d_name);
-               else {
-                       sprintf(name, "%s/%s", dirpath, dp->d_name);
-                       if (strcmp(&name[(int) strlen(name) - 7], "glsnake") == 0) {
+model_t * load_models(char * dirpath, model_t * models, int * count)
+{
+  char name[1024];
+  struct dirent * dp;
+  DIR * dfd;
+
+  if ((dfd = opendir(dirpath)) == NULL) {
+    if (strstr(dirpath, "data") == NULL)
+/*      fprintf(stderr, "load_models: can't read %s/\n", dirpath); */
+    return models;
+  }
+  while ((dp = readdir(dfd)) != NULL) {
+    if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
+      continue;
+    if (strlen(dirpath) + strlen(dp->d_name) + 2 > sizeof(name))
+      fprintf(stderr, "load_models: name %s/%s too long\n", dirpath, dp->d_name);
+    else {
+      sprintf(name, "%s/%s", dirpath, dp->d_name);
+      if (strcmp(&name[(int) strlen(name) - 7], "glsnake") == 0) {
 #ifdef DEBUG
-                               fprintf(stderr, "load_models: opening %s\n", name);     
+        fprintf(stderr, "load_models: opening %s\n", name); 
 #endif
-                               models = load_modelfile(name, models, count);
-                       }
-               }
-       }
-       closedir(dfd);
-       return models;
+        models = load_modelfile(name, models, count);
+      }
+    }
+  }
+  closedir(dfd);
+  return models;
 }
 
 /* snake metrics */
@@ -414,284 +425,293 @@ model_t * load_models(char * dirpath, model_t * models, int * count) {
 #define Z_MASK 4
 #define GETSCALAR(vec,mask) ((vec)==(mask) ? 1 : ((vec)==-(mask) ? -1 : 0 ))
 
-int cross_product(int src_dir, int dest_dir) {
-       return X_MASK * (GETSCALAR(src_dir, Y_MASK) * GETSCALAR(dest_dir, Z_MASK) -
-                       GETSCALAR(src_dir, Z_MASK) * GETSCALAR(dest_dir, Y_MASK)) +
-               Y_MASK * (GETSCALAR(src_dir, Z_MASK) * GETSCALAR(dest_dir, X_MASK) -
-                       GETSCALAR(src_dir, X_MASK) * GETSCALAR(dest_dir, Z_MASK)) +
-               Z_MASK * (GETSCALAR(src_dir, X_MASK) * GETSCALAR(dest_dir, Y_MASK) -
-                       GETSCALAR(src_dir, Y_MASK) * GETSCALAR(dest_dir, X_MASK));
+int cross_product(int src_dir, int dest_dir)
+{
+  return X_MASK * (GETSCALAR(src_dir, Y_MASK) * GETSCALAR(dest_dir, Z_MASK) -
+      GETSCALAR(src_dir, Z_MASK) * GETSCALAR(dest_dir, Y_MASK)) +
+    Y_MASK * (GETSCALAR(src_dir, Z_MASK) * GETSCALAR(dest_dir, X_MASK) -
+      GETSCALAR(src_dir, X_MASK) * GETSCALAR(dest_dir, Z_MASK)) +
+    Z_MASK * (GETSCALAR(src_dir, X_MASK) * GETSCALAR(dest_dir, Y_MASK) -
+      GETSCALAR(src_dir, Y_MASK) * GETSCALAR(dest_dir, X_MASK));
 }
 
-void calc_snake_metrics(glsnake_configuration * bp) {
-       int src_dir, dest_dir;
-       int i, x, y, z;
-       int prev_src_dir = -Y_MASK;
-       int prev_dest_dir = Z_MASK;
-       int grid[25][25][25];
-
-       /* zero the grid */
-       memset(&grid, 0, sizeof(int) * 25*25*25);
-
-       bp->is_legal = 1;
-       x = y = z = 12;
-
-       /* trace path of snake and keep record for is_legal */
-       for (i = 0; i < 23; i++) {
-               /* establish new state variables */
-               src_dir = -prev_dest_dir;
-               x += GETSCALAR(prev_dest_dir, X_MASK);
-               y += GETSCALAR(prev_dest_dir, Y_MASK);
-               z += GETSCALAR(prev_dest_dir, Z_MASK);
-
-               switch ((int) bp->node[i].dest_angle) {
-                       case (int) (ZERO * 90.0):
-                               dest_dir = -prev_src_dir;
-                               break;
-                       case (int) (PIN * 90.0):
-                               dest_dir = prev_src_dir;
-                               break;
-                       case (int) (RIGHT * 90.):
-                       case (int) (LEFT * 90.0):
-                               dest_dir = cross_product(prev_src_dir, prev_dest_dir);
-                               if (bp->node[i].dest_angle == (int) (RIGHT * 90.0))
-                                       dest_dir = -dest_dir;
-                               break;
-                       default:
-                               /* prevent spurious "might be used uninitialised" warnings */
-                               dest_dir = 0;
-                               break;
-               }
-
-               if (grid[x][y][z] == 0)
-                       grid[x][y][z] = src_dir + dest_dir;
-               else if (grid[x][y][z] + src_dir + dest_dir == 0)
-                       grid[x][y][z] = 8;
-               else
-                       bp->is_legal = 0;
-
-               prev_src_dir = src_dir;
-               prev_dest_dir = dest_dir;
-       }
-
-       /* determine if the snake is cyclic */
-       bp->is_cyclic = (dest_dir == Y_MASK && x == 12 && y == 11 && x == 12);
-
-       /* determine last turn */
-       bp->last_turn = -1;
-       if (bp->is_cyclic) {
-               switch (src_dir) {
-                       case -Z_MASK:
-                               bp->last_turn = ZERO * 90.0;
-                               break;
-                       case Z_MASK:
-                               bp->last_turn = PIN * 90.0;
-                               break;
-                       case X_MASK:
-                               bp->last_turn = LEFT * 90.0;
-                               break;
-                       case -X_MASK:
-                               bp->last_turn = RIGHT * 90.0;
-                               break;
-               }
-       }
+void calc_snake_metrics(glsnake_configuration * bp)
+{
+  int src_dir, dest_dir;
+  int i, x, y, z;
+  int prev_src_dir = -Y_MASK;
+  int prev_dest_dir = Z_MASK;
+  int grid[25][25][25];
+
+  /* zero the grid */
+  memset(&grid, 0, sizeof(int) * 25*25*25);
+
+  bp->is_legal = 1;
+  x = y = z = 12;
+
+  /* trace path of snake and keep record for is_legal */
+  for (i = 0; i < 23; i++) {
+    /* establish new state variables */
+    src_dir = -prev_dest_dir;
+    x += GETSCALAR(prev_dest_dir, X_MASK);
+    y += GETSCALAR(prev_dest_dir, Y_MASK);
+    z += GETSCALAR(prev_dest_dir, Z_MASK);
+
+    switch ((int) bp->node[i].dest_angle) {
+      case (int) (ZERO * 90.0):
+        dest_dir = -prev_src_dir;
+        break;
+      case (int) (PIN * 90.0):
+        dest_dir = prev_src_dir;
+        break;
+      case (int) (RIGHT * 90.):
+      case (int) (LEFT * 90.0):
+        dest_dir = cross_product(prev_src_dir, prev_dest_dir);
+        if (bp->node[i].dest_angle == (int) (RIGHT * 90.0))
+          dest_dir = -dest_dir;
+        break;
+      default:
+        /* prevent spurious "might be used uninitialised" warnings */
+        dest_dir = 0;
+        break;
+    }
+
+    if (grid[x][y][z] == 0)
+      grid[x][y][z] = src_dir + dest_dir;
+    else if (grid[x][y][z] + src_dir + dest_dir == 0)
+      grid[x][y][z] = 8;
+    else
+      bp->is_legal = 0;
+
+    prev_src_dir = src_dir;
+    prev_dest_dir = dest_dir;
+  }
+
+  /* determine if the snake is cyclic */
+  bp->is_cyclic = (dest_dir == Y_MASK && x == 12 && y == 11 && x == 12);
+
+  /* determine last turn */
+  bp->last_turn = -1;
+  if (bp->is_cyclic) {
+    switch (src_dir) {
+      case -Z_MASK:
+        bp->last_turn = ZERO * 90.0;
+        break;
+      case Z_MASK:
+        bp->last_turn = PIN * 90.0;
+        break;
+      case X_MASK:
+        bp->last_turn = LEFT * 90.0;
+        break;
+      case -X_MASK:
+        bp->last_turn = RIGHT * 90.0;
+        break;
+    }
+  }
 }
 
-void set_colours(glsnake_configuration * bp, int immediate) {
-       /* set target colour */
-       if (!bp->is_legal) {
-               bp->colour_t[0] = 0.5;
-               bp->colour_t[1] = 0.5;
-               bp->colour_t[2] = 0.5;
-       } else if (bp->is_cyclic) {
-               bp->colour_t[0] = 0.4;
-               bp->colour_t[1] = 0.8;
-               bp->colour_t[2] = 0.2;
-       } else {
-               bp->colour_t[0] = 0.3;
-               bp->colour_t[1] = 0.1;
-               bp->colour_t[2] = 0.9;
-       }
-       if (immediate) {
-               bp->colour_i[0] = bp->colour_t[0] - bp->colour[0];
-               bp->colour_i[1] = bp->colour_t[1] - bp->colour[1];
-               bp->colour_i[2] = bp->colour_t[2] - bp->colour[2];
-       } else {
-               /* instead of 50.0, I should actually work out how many times this gets
-                * called during a morph */
-               bp->colour_i[0] = (bp->colour_t[0] - bp->colour[0]) / 50.0;
-               bp->colour_i[1] = (bp->colour_t[1] - bp->colour[1]) / 50.0;
-               bp->colour_i[2] = (bp->colour_t[2] - bp->colour[2]) / 50.0;
-       }
+void set_colours(glsnake_configuration * bp, int immediate)
+{
+  /* set target colour */
+  if (!bp->is_legal) {
+    bp->colour_t[0] = 0.5;
+    bp->colour_t[1] = 0.5;
+    bp->colour_t[2] = 0.5;
+  } else if (bp->is_cyclic) {
+    bp->colour_t[0] = 0.4;
+    bp->colour_t[1] = 0.8;
+    bp->colour_t[2] = 0.2;
+  } else {
+    bp->colour_t[0] = 0.3;
+    bp->colour_t[1] = 0.1;
+    bp->colour_t[2] = 0.9;
+  }
+  if (immediate) {
+    bp->colour_i[0] = bp->colour_t[0] - bp->colour[0];
+    bp->colour_i[1] = bp->colour_t[1] - bp->colour[1];
+    bp->colour_i[2] = bp->colour_t[2] - bp->colour[2];
+  } else {
+    /* instead of 50.0, I should actually work out how many times this gets
+     * called during a morph */
+    bp->colour_i[0] = (bp->colour_t[0] - bp->colour[0]) / 50.0;
+    bp->colour_i[1] = (bp->colour_t[1] - bp->colour[1]) / 50.0;
+    bp->colour_i[2] = (bp->colour_t[2] - bp->colour[2]) / 50.0;
+  }
 }
 
-void start_morph(int model_index, int immediate, glsnake_configuration * bp) {
-       int i;
-
-       for (i = 0; i < 23; i++) {
-               bp->node[i].dest_angle = bp->models[model_index].node[i];
-               if (immediate)
-                       bp->node[i].cur_angle = bp->models[model_index].node[i];
-       }
-       
-       calc_snake_metrics(bp);
-       set_colours(bp, 0);
-       bp->cur_model = model_index;
-       bp->morphing = 1;
+void start_morph(int model_index, int immediate, glsnake_configuration * bp)
+{
+  int i;
+
+  for (i = 0; i < 23; i++) {
+    bp->node[i].dest_angle = bp->models[model_index].node[i];
+    if (immediate)
+      bp->node[i].cur_angle = bp->models[model_index].node[i];
+  }
+  
+  calc_snake_metrics(bp);
+  set_colours(bp, 0);
+  bp->cur_model = model_index;
+  bp->morphing = 1;
 }
 
 /* convex hull */
 
 /* model labels */
-void draw_label(ModeInfo * mi) {
-       glsnake_configuration *bp = &glc[MI_SCREEN(mi)];
-       
-       glPushAttrib(GL_TRANSFORM_BIT | GL_ENABLE_BIT);
-       glDisable(GL_LIGHTING);
-       glDisable(GL_DEPTH_TEST);
-       glMatrixMode(GL_PROJECTION);
-       glPushMatrix();
-       glLoadIdentity();
-       glMatrixMode(GL_MODELVIEW);
-       glPushMatrix();
-       glLoadIdentity();
-       gluOrtho2D(0, mi->xgwa.width, 0, mi->xgwa.height);
-       glColor3f(1.0, 1.0, 0.0);
-       {
-               char * s;
-               int i, /* w, */ l;
-
-               if (bp->interactive)
-                       s = "interactive";
-               else
-                       s = bp->models[bp->cur_model].name;
-
-               l = strlen(s);
-               /*
-               w = 0;
-               for (i = 0; i < l; i++) {
-                       w += (bp->font->per_char 
-                                       ? bp->font->per_char[((int)s[i]) - bp->font->min_char_or_byte2].rbearing 
-                                       : bp->font->min_bounds.rbearing);
-               }
-               */
-               
-               glRasterPos2f(10, mi->xgwa.height - 10 - (bp->font->ascent + bp->font->descent));
-                               /* mi->xgwa.width - w, bp->font->descent + bp->font->ascent); */
-
-               /* fprintf(stderr, "afaf.width = %d, w = %d\n", mi->xgwa.width, w); */
-               
-               for (i = 0; i < l; i++)
-                       glCallList(bp->font_list + (int)s[i]);
-       }
-       glPopMatrix();
-       glMatrixMode(GL_PROJECTION);
-       glPopMatrix();
-       glPopAttrib();
+void draw_label(ModeInfo * mi)
+{
+  glsnake_configuration *bp = &glc[MI_SCREEN(mi)];
+  
+  glPushAttrib(GL_TRANSFORM_BIT | GL_ENABLE_BIT);
+  glDisable(GL_LIGHTING);
+  glDisable(GL_DEPTH_TEST);
+  glMatrixMode(GL_PROJECTION);
+  glPushMatrix();
+  glLoadIdentity();
+  glMatrixMode(GL_MODELVIEW);
+  glPushMatrix();
+  glLoadIdentity();
+  gluOrtho2D(0, mi->xgwa.width, 0, mi->xgwa.height);
+  glColor3f(1.0, 1.0, 0.0);
+  {
+    char * s;
+    int i, /* w, */ l;
+
+    if (bp->interactive)
+      s = "interactive";
+    else
+      s = bp->models[bp->cur_model].name;
+
+    l = strlen(s);
+    /*
+    w = 0;
+    for (i = 0; i < l; i++) {
+      w += (bp->font->per_char 
+          ? bp->font->per_char[((int)s[i]) - bp->font->min_char_or_byte2].rbearing 
+          : bp->font->min_bounds.rbearing);
+    }
+    */
+    
+    glRasterPos2f(10, mi->xgwa.height - 10 - (bp->font->ascent + bp->font->descent));
+        /* mi->xgwa.width - w, bp->font->descent + bp->font->ascent); */
+
+    /* fprintf(stderr, "afaf.width = %d, w = %d\n", mi->xgwa.width, w); */
+    
+    for (i = 0; i < l; i++)
+      glCallList(bp->font_list + (int)s[i]);
+  }
+  glPopMatrix();
+  glMatrixMode(GL_PROJECTION);
+  glPopMatrix();
+  glPopAttrib();
 }
 
 /* load the fonts -- this function borrowed from molecule.c */
-static void load_font(ModeInfo * mi, char * res, XFontStruct ** fontp, GLuint * dlistp) {
-       const char * font = get_string_resource(res, "Font");
-       XFontStruct * f;
-       Font id;
-       int first, last;
-
-       if (!font)
-               font = "-*-helvetica-medium-r-*-*-*-120-*";
-
-       f = XLoadQueryFont(mi->dpy, font);
-       if (!f)
-               f = XLoadQueryFont(mi->dpy, "fixed");
-
-       id = f->fid;
-       first = f->min_char_or_byte2;
-       last = f->max_char_or_byte2;
-       
-       clear_gl_error();
-       *dlistp = glGenLists((GLuint) last + 1);
-       check_gl_error("glGenLists");
-       glXUseXFont(id, first, last - first + 1, *dlistp + first);
-       check_gl_error("glXUseXFont");
-
-       *fontp = f;
+static void load_font(ModeInfo * mi, char * res, XFontStruct ** fontp, GLuint * dlistp)
+{
+  const char * font = get_string_resource(res, "Font");
+  XFontStruct * f;
+  Font id;
+  int first, last;
+
+  if (!font)
+    font = "-*-helvetica-medium-r-*-*-*-120-*";
+
+  f = XLoadQueryFont(mi->dpy, font);
+  if (!f)
+    f = XLoadQueryFont(mi->dpy, "fixed");
+
+  id = f->fid;
+  first = f->min_char_or_byte2;
+  last = f->max_char_or_byte2;
+  
+  clear_gl_error();
+  *dlistp = glGenLists((GLuint) last + 1);
+  check_gl_error("glGenLists");
+  glXUseXFont(id, first, last - first + 1, *dlistp + first);
+  check_gl_error("glXUseXFont");
+
+  *fontp = f;
 }
 
 
 
 /* window management */
-void glsnake_reshape(ModeInfo *mi, int w, int h) {
-       glViewport (0, 0, (GLint) w, (GLint) h);
-       glMatrixMode(GL_PROJECTION);
-       glLoadIdentity();
-       gluPerspective(25.0, w/(GLfloat)h, 1.0, 100.0 );
-       glMatrixMode(GL_MODELVIEW);
-       glLoadIdentity();
+void glsnake_reshape(ModeInfo *mi, int w, int h)
+{
+  glViewport (0, 0, (GLint) w, (GLint) h);
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluPerspective(25.0, w/(GLfloat)h, 1.0, 100.0 );
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
 }
 
-static void gl_init(ModeInfo *mi) {
-       /* glsnake_configuration *bp = &glc[MI_SCREEN(mi)]; */
-       int wire = MI_IS_WIREFRAME(mi);
-       float light_pos[][3] = {{0.0,0.0,20.0},{0.0,20.0,0.0}};
-       float light_dir[][3] = {{0.0,0.0,-20.0},{0.0,-20.0,0.0}};
-
-       glClearColor(0.0, 0.0, 0.0, 0.0);
-       glEnable(GL_DEPTH_TEST);
-       glShadeModel(GL_SMOOTH);
-       glCullFace(GL_BACK);
-       glEnable(GL_CULL_FACE);
-       glEnable(GL_NORMALIZE);
-
-       if (!wire) {
-               glColor3f(1.0, 1.0, 1.0);
-               glLightfv(GL_LIGHT0, GL_POSITION, light_pos[0]);
-               glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_dir[0]);
-               glLightfv(GL_LIGHT1, GL_POSITION, light_pos[1]);
-               glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, light_dir[1]);
-               glEnable(GL_LIGHTING);
-               glEnable(GL_LIGHT0);
-               glEnable(GL_LIGHT1);
-               glEnable(GL_COLOR_MATERIAL);
-       }
+static void gl_init(ModeInfo *mi)
+{
+  /* glsnake_configuration *bp = &glc[MI_SCREEN(mi)]; */
+  int wire = MI_IS_WIREFRAME(mi);
+  float light_pos[][3] = {{0.0,0.0,20.0},{0.0,20.0,0.0}};
+  float light_dir[][3] = {{0.0,0.0,-20.0},{0.0,-20.0,0.0}};
+
+  glClearColor(0.0, 0.0, 0.0, 0.0);
+  glEnable(GL_DEPTH_TEST);
+  glShadeModel(GL_SMOOTH);
+  glCullFace(GL_BACK);
+  glEnable(GL_CULL_FACE);
+  glEnable(GL_NORMALIZE);
+
+  if (!wire) {
+    glColor3f(1.0, 1.0, 1.0);
+    glLightfv(GL_LIGHT0, GL_POSITION, light_pos[0]);
+    glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_dir[0]);
+    glLightfv(GL_LIGHT1, GL_POSITION, light_pos[1]);
+    glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, light_dir[1]);
+    glEnable(GL_LIGHTING);
+    glEnable(GL_LIGHT0);
+    glEnable(GL_LIGHT1);
+    glEnable(GL_COLOR_MATERIAL);
+  }
 }
 
 /* lifted from lament.c */
 #define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n))))
 #define RANDSIGN() ((random() & 1) ? 1 : -1)
 
-void glsnake_init(ModeInfo *mi) {
-       glsnake_configuration * bp;
-       int wire = MI_IS_WIREFRAME(mi);
-
-       if (!glc) {
-               glc = (glsnake_configuration *) calloc(MI_NUM_SCREENS(mi), sizeof(glsnake_configuration));
-               if (!glc) {
-                       fprintf(stderr, "%s: out of memory\n", progname);
-                       exit(1);
-               }
-               bp = &glc[MI_SCREEN(mi)];
-       }
-
-       bp = &glc[MI_SCREEN(mi)];
-
-       if ((bp->glx_context = init_GL(mi)) != NULL) {
-               gl_init(mi);
-               glsnake_reshape(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
-       }
-
-       /* initialise config variables */
-       memset(&bp->node, 0, sizeof(nodeang_t) * 24);
-       bp->m_count = sizeof(default_models) / sizeof(model_t); /* overwrite this in a bit */
-       bp->selected = 11;
-       bp->is_cyclic = 0;
-       bp->is_legal = 1;
-       bp->last_turn = -1;
-       bp->roty = 0.0;
-       bp->rotz = 0.0;
-       bp->morphing = 0;
-       bp->paused = 0;
-       bp->dragging = 0;
-       bp->interactive = 0;
+void glsnake_init(ModeInfo *mi)
+{
+  glsnake_configuration * bp;
+  int wire = MI_IS_WIREFRAME(mi);
+
+  if (!glc) {
+    glc = (glsnake_configuration *) calloc(MI_NUM_SCREENS(mi), sizeof(glsnake_configuration));
+    if (!glc) {
+      fprintf(stderr, "%s: out of memory\n", progname);
+      exit(1);
+    }
+    bp = &glc[MI_SCREEN(mi)];
+  }
+
+  bp = &glc[MI_SCREEN(mi)];
+
+  if ((bp->glx_context = init_GL(mi)) != NULL) {
+    gl_init(mi);
+    glsnake_reshape(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+  }
+
+  /* initialise config variables */
+  memset(&bp->node, 0, sizeof(nodeang_t) * 24);
+  bp->m_count = sizeof(default_models) / sizeof(model_t); /* overwrite this in a bit */
+  bp->selected = 11;
+  bp->is_cyclic = 0;
+  bp->is_legal = 1;
+  bp->last_turn = -1;
+  bp->roty = 0.0;
+  bp->rotz = 0.0;
+  bp->morphing = 0;
+  bp->paused = 0;
+  bp->dragging = 0;
+  bp->interactive = 0;
 
         {
 # ifdef GETTIMEOFDAY_TWO_ARGS
@@ -702,193 +722,194 @@ void glsnake_init(ModeInfo *mi) {
 # endif
         }
 
-       memcpy(&bp->last_morph, &(bp->last_iteration),
+  memcpy(&bp->last_morph, &(bp->last_iteration),
                sizeof(bp->last_morph));
-       /* srand((unsigned int) bp->last_iteration.time); */
-
-       /* load the model files */
-       /* first copy the defaults to bp->m_count */
-       bp->models = (model_t *) malloc(sizeof(model_t) * bp->m_count);
-       memcpy(bp->models, default_models, bp->m_count * sizeof(model_t));
-       /* then add on models from the Debian model file location */
-       bp->models = load_models("/usr/share/glsnake", bp->models, &(bp->m_count));
-
-       bp->m = bp->cur_model = RAND(bp->m_count);
-       start_morph(bp->cur_model, 1, bp);
-
-       calc_snake_metrics(bp);
-       set_colours(bp, 1);
-
-       /* set up a font for the labels */
-       if (labels)
-               load_font(mi, "labelfont", &bp->font, &bp->font_list);
-       
-       bp->node_list = glGenLists(1);
-       glNewList(bp->node_list, GL_COMPILE);
-       if (!wire) {
-               /* corners */
-               glBegin(GL_TRIANGLES);
-               glNormal3fv(solid_prism_n[0]);
-               glVertex3fv(solid_prism_v[0]);
-               glVertex3fv(solid_prism_v[2]);
-               glVertex3fv(solid_prism_v[1]);
+  /* srand((unsigned int) bp->last_iteration.time); */
+
+  /* load the model files */
+  /* first copy the defaults to bp->m_count */
+  bp->models = (model_t *) malloc(sizeof(model_t) * bp->m_count);
+  memcpy(bp->models, default_models, bp->m_count * sizeof(model_t));
+  /* then add on models from the Debian model file location */
+  bp->models = load_models("/usr/share/glsnake", bp->models, &(bp->m_count));
+
+  bp->m = bp->cur_model = RAND(bp->m_count);
+  start_morph(bp->cur_model, 1, bp);
+
+  calc_snake_metrics(bp);
+  set_colours(bp, 1);
+
+  /* set up a font for the labels */
+  if (labels)
+    load_font(mi, "labelfont", &bp->font, &bp->font_list);
+  
+  bp->node_list = glGenLists(1);
+  glNewList(bp->node_list, GL_COMPILE);
+  if (!wire) {
+    /* corners */
+    glBegin(GL_TRIANGLES);
+    glNormal3fv(solid_prism_n[0]);
+    glVertex3fv(solid_prism_v[0]);
+    glVertex3fv(solid_prism_v[2]);
+    glVertex3fv(solid_prism_v[1]);
     
-               glNormal3fv(solid_prism_n[1]);
-               glVertex3fv(solid_prism_v[6]);
-               glVertex3fv(solid_prism_v[7]);
-               glVertex3fv(solid_prism_v[8]);
-
-               glNormal3fv(solid_prism_n[2]);
-               glVertex3fv(solid_prism_v[12]);
-               glVertex3fv(solid_prism_v[13]);
-               glVertex3fv(solid_prism_v[14]);
+    glNormal3fv(solid_prism_n[1]);
+    glVertex3fv(solid_prism_v[6]);
+    glVertex3fv(solid_prism_v[7]);
+    glVertex3fv(solid_prism_v[8]);
+
+    glNormal3fv(solid_prism_n[2]);
+    glVertex3fv(solid_prism_v[12]);
+    glVertex3fv(solid_prism_v[13]);
+    glVertex3fv(solid_prism_v[14]);
     
-               glNormal3fv(solid_prism_n[3]);
-               glVertex3fv(solid_prism_v[3]);
-               glVertex3fv(solid_prism_v[4]);
-               glVertex3fv(solid_prism_v[5]);
-       
-               glNormal3fv(solid_prism_n[4]);
-               glVertex3fv(solid_prism_v[9]);
-               glVertex3fv(solid_prism_v[11]);
-               glVertex3fv(solid_prism_v[10]);
-
-               glNormal3fv(solid_prism_n[5]);
-               glVertex3fv(solid_prism_v[16]);
-               glVertex3fv(solid_prism_v[15]);
-               glVertex3fv(solid_prism_v[17]);
-               glEnd();
-
-               /* edges */
-               glBegin(GL_QUADS);
-               glNormal3fv(solid_prism_n[6]);
-               glVertex3fv(solid_prism_v[0]);
-               glVertex3fv(solid_prism_v[12]);
-               glVertex3fv(solid_prism_v[14]);
-               glVertex3fv(solid_prism_v[2]);
-       
-               glNormal3fv(solid_prism_n[7]);
-               glVertex3fv(solid_prism_v[0]);
-               glVertex3fv(solid_prism_v[1]);
-               glVertex3fv(solid_prism_v[7]);
-               glVertex3fv(solid_prism_v[6]);
-       
-               glNormal3fv(solid_prism_n[8]);
-               glVertex3fv(solid_prism_v[6]);
-               glVertex3fv(solid_prism_v[8]);
-               glVertex3fv(solid_prism_v[13]);
-               glVertex3fv(solid_prism_v[12]);
-       
-               glNormal3fv(solid_prism_n[9]);
-               glVertex3fv(solid_prism_v[3]);
-               glVertex3fv(solid_prism_v[5]);
-               glVertex3fv(solid_prism_v[17]);
-               glVertex3fv(solid_prism_v[15]);
-       
-               glNormal3fv(solid_prism_n[10]);
-               glVertex3fv(solid_prism_v[3]);
-               glVertex3fv(solid_prism_v[9]);
-               glVertex3fv(solid_prism_v[10]);
-               glVertex3fv(solid_prism_v[4]);
-       
-               glNormal3fv(solid_prism_n[11]);
-               glVertex3fv(solid_prism_v[15]);
-               glVertex3fv(solid_prism_v[16]);
-               glVertex3fv(solid_prism_v[11]);
-               glVertex3fv(solid_prism_v[9]);
-       
-               glNormal3fv(solid_prism_n[12]);
-               glVertex3fv(solid_prism_v[1]);
-               glVertex3fv(solid_prism_v[2]);
-               glVertex3fv(solid_prism_v[5]);
-               glVertex3fv(solid_prism_v[4]);
-       
-               glNormal3fv(solid_prism_n[13]);
-               glVertex3fv(solid_prism_v[8]);
-               glVertex3fv(solid_prism_v[7]);
-               glVertex3fv(solid_prism_v[10]);
-               glVertex3fv(solid_prism_v[11]);
-       
-               glNormal3fv(solid_prism_n[14]);
-               glVertex3fv(solid_prism_v[13]);
-               glVertex3fv(solid_prism_v[16]);
-               glVertex3fv(solid_prism_v[17]);
-               glVertex3fv(solid_prism_v[14]);
-               glEnd();
-       
-               /* faces */
-               glBegin(GL_TRIANGLES);
-               glNormal3fv(solid_prism_n[15]);
-               glVertex3fv(solid_prism_v[0]);
-               glVertex3fv(solid_prism_v[6]);
-               glVertex3fv(solid_prism_v[12]);
-       
-               glNormal3fv(solid_prism_n[19]);
-               glVertex3fv(solid_prism_v[3]);
-               glVertex3fv(solid_prism_v[15]);
-               glVertex3fv(solid_prism_v[9]);
-               glEnd();
-       
-               glBegin(GL_QUADS);
-               glNormal3fv(solid_prism_n[16]);
-               glVertex3fv(solid_prism_v[1]);
-               glVertex3fv(solid_prism_v[4]);
-               glVertex3fv(solid_prism_v[10]);
-               glVertex3fv(solid_prism_v[7]);
-       
-               glNormal3fv(solid_prism_n[17]);
-               glVertex3fv(solid_prism_v[8]);
-               glVertex3fv(solid_prism_v[11]);
-               glVertex3fv(solid_prism_v[16]);
-               glVertex3fv(solid_prism_v[13]);
-       
-               glNormal3fv(solid_prism_n[18]);
-               glVertex3fv(solid_prism_v[2]);
-               glVertex3fv(solid_prism_v[14]);
-               glVertex3fv(solid_prism_v[17]);
-               glVertex3fv(solid_prism_v[5]);
-               glEnd();
-       } else {
-               /* build wire display list */
-               glBegin(GL_LINE_STRIP);
-               glVertex3fv(wire_prism_v[0]);
-               glVertex3fv(wire_prism_v[1]);
-               glVertex3fv(wire_prism_v[2]);
-               glVertex3fv(wire_prism_v[0]);
-               glVertex3fv(wire_prism_v[3]);
-               glVertex3fv(wire_prism_v[4]);
-               glVertex3fv(wire_prism_v[5]);
-               glVertex3fv(wire_prism_v[3]);
-               glEnd();
-       
-               glBegin(GL_LINES);
-               glVertex3fv(wire_prism_v[1]);
-               glVertex3fv(wire_prism_v[4]);
-               glVertex3fv(wire_prism_v[2]);
-               glVertex3fv(wire_prism_v[5]);
-               glEnd();
-       }
-       glEndList();
+    glNormal3fv(solid_prism_n[3]);
+    glVertex3fv(solid_prism_v[3]);
+    glVertex3fv(solid_prism_v[4]);
+    glVertex3fv(solid_prism_v[5]);
+  
+    glNormal3fv(solid_prism_n[4]);
+    glVertex3fv(solid_prism_v[9]);
+    glVertex3fv(solid_prism_v[11]);
+    glVertex3fv(solid_prism_v[10]);
+
+    glNormal3fv(solid_prism_n[5]);
+    glVertex3fv(solid_prism_v[16]);
+    glVertex3fv(solid_prism_v[15]);
+    glVertex3fv(solid_prism_v[17]);
+    glEnd();
+
+    /* edges */
+    glBegin(GL_QUADS);
+    glNormal3fv(solid_prism_n[6]);
+    glVertex3fv(solid_prism_v[0]);
+    glVertex3fv(solid_prism_v[12]);
+    glVertex3fv(solid_prism_v[14]);
+    glVertex3fv(solid_prism_v[2]);
+  
+    glNormal3fv(solid_prism_n[7]);
+    glVertex3fv(solid_prism_v[0]);
+    glVertex3fv(solid_prism_v[1]);
+    glVertex3fv(solid_prism_v[7]);
+    glVertex3fv(solid_prism_v[6]);
+  
+    glNormal3fv(solid_prism_n[8]);
+    glVertex3fv(solid_prism_v[6]);
+    glVertex3fv(solid_prism_v[8]);
+    glVertex3fv(solid_prism_v[13]);
+    glVertex3fv(solid_prism_v[12]);
+  
+    glNormal3fv(solid_prism_n[9]);
+    glVertex3fv(solid_prism_v[3]);
+    glVertex3fv(solid_prism_v[5]);
+    glVertex3fv(solid_prism_v[17]);
+    glVertex3fv(solid_prism_v[15]);
+  
+    glNormal3fv(solid_prism_n[10]);
+    glVertex3fv(solid_prism_v[3]);
+    glVertex3fv(solid_prism_v[9]);
+    glVertex3fv(solid_prism_v[10]);
+    glVertex3fv(solid_prism_v[4]);
+  
+    glNormal3fv(solid_prism_n[11]);
+    glVertex3fv(solid_prism_v[15]);
+    glVertex3fv(solid_prism_v[16]);
+    glVertex3fv(solid_prism_v[11]);
+    glVertex3fv(solid_prism_v[9]);
+  
+    glNormal3fv(solid_prism_n[12]);
+    glVertex3fv(solid_prism_v[1]);
+    glVertex3fv(solid_prism_v[2]);
+    glVertex3fv(solid_prism_v[5]);
+    glVertex3fv(solid_prism_v[4]);
+  
+    glNormal3fv(solid_prism_n[13]);
+    glVertex3fv(solid_prism_v[8]);
+    glVertex3fv(solid_prism_v[7]);
+    glVertex3fv(solid_prism_v[10]);
+    glVertex3fv(solid_prism_v[11]);
+  
+    glNormal3fv(solid_prism_n[14]);
+    glVertex3fv(solid_prism_v[13]);
+    glVertex3fv(solid_prism_v[16]);
+    glVertex3fv(solid_prism_v[17]);
+    glVertex3fv(solid_prism_v[14]);
+    glEnd();
+  
+    /* faces */
+    glBegin(GL_TRIANGLES);
+    glNormal3fv(solid_prism_n[15]);
+    glVertex3fv(solid_prism_v[0]);
+    glVertex3fv(solid_prism_v[6]);
+    glVertex3fv(solid_prism_v[12]);
+  
+    glNormal3fv(solid_prism_n[19]);
+    glVertex3fv(solid_prism_v[3]);
+    glVertex3fv(solid_prism_v[15]);
+    glVertex3fv(solid_prism_v[9]);
+    glEnd();
+  
+    glBegin(GL_QUADS);
+    glNormal3fv(solid_prism_n[16]);
+    glVertex3fv(solid_prism_v[1]);
+    glVertex3fv(solid_prism_v[4]);
+    glVertex3fv(solid_prism_v[10]);
+    glVertex3fv(solid_prism_v[7]);
+  
+    glNormal3fv(solid_prism_n[17]);
+    glVertex3fv(solid_prism_v[8]);
+    glVertex3fv(solid_prism_v[11]);
+    glVertex3fv(solid_prism_v[16]);
+    glVertex3fv(solid_prism_v[13]);
+  
+    glNormal3fv(solid_prism_n[18]);
+    glVertex3fv(solid_prism_v[2]);
+    glVertex3fv(solid_prism_v[14]);
+    glVertex3fv(solid_prism_v[17]);
+    glVertex3fv(solid_prism_v[5]);
+    glEnd();
+  } else {
+    /* build wire display list */
+    glBegin(GL_LINE_STRIP);
+    glVertex3fv(wire_prism_v[0]);
+    glVertex3fv(wire_prism_v[1]);
+    glVertex3fv(wire_prism_v[2]);
+    glVertex3fv(wire_prism_v[0]);
+    glVertex3fv(wire_prism_v[3]);
+    glVertex3fv(wire_prism_v[4]);
+    glVertex3fv(wire_prism_v[5]);
+    glVertex3fv(wire_prism_v[3]);
+    glEnd();
+  
+    glBegin(GL_LINES);
+    glVertex3fv(wire_prism_v[1]);
+    glVertex3fv(wire_prism_v[4]);
+    glVertex3fv(wire_prism_v[2]);
+    glVertex3fv(wire_prism_v[5]);
+    glEnd();
+  }
+  glEndList();
 }
 
 /* "jwz?  no way man, he's my idle" -- Jaq, 2001.
  * I forget the context :( */
-void glsnake_idol(glsnake_configuration * bp) {
-       /* time since last iteration */
-       long iter_msec;
-       /* time since the beginning of last morph */
-       long morf_msec;
-       float iter_angle_max;
-       int i;
-       struct timeval current_time;
-       int still_morphing;
-
-       /* Do nothing to the model if we are paused */
-       if (bp->paused) {
-               /* Avoid busy waiting when nothing is changing */
-               usleep(1);
-               return;
-       }
+void glsnake_idol(glsnake_configuration * bp)
+{
+  /* time since last iteration */
+  long iter_msec;
+  /* time since the beginning of last morph */
+  long morf_msec;
+  float iter_angle_max;
+  int i;
+  struct timeval current_time;
+  int still_morphing;
+
+  /* Do nothing to the model if we are paused */
+  if (bp->paused) {
+    /* Avoid busy waiting when nothing is changing */
+    usleep(1);
+    return;
+  }
 
         {
 # ifdef GETTIMEOFDAY_TWO_ARGS
@@ -899,171 +920,293 @@ void glsnake_idol(glsnake_configuration * bp) {
 # endif
         }
 
-       /* <spiv> Well, ftime gives time with millisecond resolution.
-        * <Jaq> if current time is exactly equal to last iteration, 
-        *       then don't do this block
-        * <spiv> (or worse, perhaps... who knows what the OS will do)
-        * <spiv> So if no discernable amount of time has passed:
-        * <spiv>   a) There's no point updating the screen, because
-        *             it would be the same
-        * <spiv>   b) The code will divide by zero
-        */
-       iter_msec = ((long) current_time.tv_usec - bp->last_iteration.tv_usec)/1000L + 
-                   ((long) current_time.tv_sec - bp->last_iteration.tv_sec) * 1000L;
-       if (iter_msec) {
-               /* save the current time */
-               memcpy(&bp->last_iteration, &current_time,
+  /* <spiv> Well, ftime gives time with millisecond resolution.
+   * <Jaq> if current time is exactly equal to last iteration, 
+   *       then don't do this block
+   * <spiv> (or worse, perhaps... who knows what the OS will do)
+   * <spiv> So if no discernable amount of time has passed:
+   * <spiv>   a) There's no point updating the screen, because
+   *             it would be the same
+   * <spiv>   b) The code will divide by zero
+   */
+  iter_msec = ((long) current_time.tv_usec - bp->last_iteration.tv_usec)/1000L + 
+        ((long) current_time.tv_sec - bp->last_iteration.tv_sec) * 1000L;
+  if (iter_msec) {
+    /* save the current time */
+    memcpy(&bp->last_iteration, &current_time,
                        sizeof(bp->last_iteration));
-               
-               /* work out if we have to switch models */
-               morf_msec = (bp->last_iteration.tv_usec - bp->last_morph.tv_usec)/1000L +
-                       ((long) (bp->last_iteration.tv_sec - bp->last_morph.tv_sec) * 1000L);
+    
+    /* work out if we have to switch models */
+    morf_msec = (bp->last_iteration.tv_usec - bp->last_morph.tv_usec)/1000L +
+      ((long) (bp->last_iteration.tv_sec - bp->last_morph.tv_sec) * 1000L);
 
-               if ((morf_msec > statictime) && !bp->interactive) {
-                       memcpy(&bp->last_morph, &(bp->last_iteration),
+    if ((morf_msec > statictime) && !bp->interactive) {
+      memcpy(&bp->last_morph, &(bp->last_iteration),
                                sizeof(bp->last_morph));
-                       start_morph(RAND(bp->m_count), 0, bp);
-               }
-
-               if (bp->interactive && !bp->morphing) {
-                       usleep(1);
-                       return;
-               }
-
-               if (!bp->dragging && !bp->interactive) {
-                       bp->roty += 360/((1000/yspin)/iter_msec);
-                       bp->rotz += 360/((1000/zspin)/iter_msec);
-               }
-
-               /* work out the maximum angle for this iteration */
-               iter_angle_max = 90.0 * (velocity/1000.0) * iter_msec;
-
-               still_morphing = 0;
-               for (i = 0; i < 24; i++) {
-                       float cur_angle = bp->node[i].cur_angle;
-                       float dest_angle = bp->node[i].dest_angle;
-                       if (cur_angle != dest_angle) {
-                               still_morphing = 1;
-                               if (fabs(cur_angle - dest_angle) <= iter_angle_max)
-                                       bp->node[i].cur_angle = dest_angle;
-                               else if (fmod(cur_angle - dest_angle + 360, 360) > 180)
-                                       bp->node[i].cur_angle = fmod(cur_angle + iter_angle_max, 360);
-                               else
-                                       bp->node[i].cur_angle = fmod(cur_angle + 360 - iter_angle_max, 360);
-                       }
-               }
-
-               if (!still_morphing)
-                       bp->morphing = 0;
-
-               /* colour cycling */
-               if (fabs(bp->colour[0] - bp->colour_t[0]) <= fabs(bp->colour_i[0]))
-                       bp->colour[0] = bp->colour_t[0];
-               else
-                       bp->colour[0] += bp->colour_i[0];
-               if (fabs(bp->colour[1] - bp->colour_t[1]) <= fabs(bp->colour_i[1]))
-                       bp->colour[1] = bp->colour_t[1];
-               else
-                       bp->colour[1] += bp->colour_i[1];
-               if (fabs(bp->colour[2] - bp->colour_t[2]) <= fabs(bp->colour_i[2]))
-                       bp->colour[2] = bp->colour_t[2];
-               else
-                       bp->colour[2] += bp->colour_i[2];
-       } else {
-               /* We are going too fast, so we may as well let the 
-                * cpu relax a little by sleeping for a millisecond. */
-               usleep(1);
-       }
+      start_morph(RAND(bp->m_count), 0, bp);
+    }
+
+    if (bp->interactive && !bp->morphing) {
+      usleep(1);
+      return;
+    }
+
+    if (!bp->dragging && !bp->interactive) {
+      bp->roty += 360/((1000/yspin)/iter_msec);
+      bp->rotz += 360/((1000/zspin)/iter_msec);
+    }
+
+    /* work out the maximum angle for this iteration */
+    iter_angle_max = 90.0 * (velocity/1000.0) * iter_msec;
+
+    still_morphing = 0;
+    for (i = 0; i < 24; i++) {
+      float cur_angle = bp->node[i].cur_angle;
+      float dest_angle = bp->node[i].dest_angle;
+      if (cur_angle != dest_angle) {
+        still_morphing = 1;
+        if (fabs(cur_angle - dest_angle) <= iter_angle_max)
+          bp->node[i].cur_angle = dest_angle;
+        else if (fmod(cur_angle - dest_angle + 360, 360) > 180)
+          bp->node[i].cur_angle = fmod(cur_angle + iter_angle_max, 360);
+        else
+          bp->node[i].cur_angle = fmod(cur_angle + 360 - iter_angle_max, 360);
+      }
+    }
+
+    if (!still_morphing)
+      bp->morphing = 0;
+
+    /* colour cycling */
+    if (fabs(bp->colour[0] - bp->colour_t[0]) <= fabs(bp->colour_i[0]))
+      bp->colour[0] = bp->colour_t[0];
+    else
+      bp->colour[0] += bp->colour_i[0];
+    if (fabs(bp->colour[1] - bp->colour_t[1]) <= fabs(bp->colour_i[1]))
+      bp->colour[1] = bp->colour_t[1];
+    else
+      bp->colour[1] += bp->colour_i[1];
+    if (fabs(bp->colour[2] - bp->colour_t[2]) <= fabs(bp->colour_i[2]))
+      bp->colour[2] = bp->colour_t[2];
+    else
+      bp->colour[2] += bp->colour_i[2];
+  } else {
+    /* We are going too fast, so we may as well let the 
+     * cpu relax a little by sleeping for a millisecond. */
+    usleep(1);
+  }
+}
+
+static void
+snake_bounding_box (ModeInfo *mi,
+                    GLfloat *x1, GLfloat *y1, GLfloat *z1,
+                    GLfloat *x2, GLfloat *y2, GLfloat *z2)
+{
+  glsnake_configuration *bp = &glc[MI_SCREEN(mi)];
+  int i;
+  GLdouble identity[16] = { 1, 0, 0, 0,
+                            0, 1, 0, 0,
+                            0, 0, 1, 0,
+                            0, 0, 0, 1 };
+  GLint vp[4] = { 0, 0, 1, 1 };
+  *x1 = *x2 = 0;
+  *y1 = *y2 = 0;
+  *z1 = *z2 = 0;
+
+  glPushMatrix();
+  glLoadIdentity();
+  for (i = 0; i < 24; i++)
+    {
+      GLdouble model[16];
+      GLdouble x, y, z;
+      GLfloat ang = bp->node[i].cur_angle;
+
+      glGetDoublev (GL_MODELVIEW_MATRIX, model);
+      gluProject (0, 0, 0, model, identity, vp, &x, &y, &z);
+fprintf (stderr, "%2d: %5.2f %5.2f %5.2f\n", i, (float)x, (float)y, (float)z);
+
+      if      (x < *x1) *x1 = x;
+      else if (x > *x2) *x2 = x;
+      if      (y < *y1) *y1 = y;
+      else if (y > *y2) *y2 = y;
+      if      (z < *z1) *z1 = z;
+      else if (z > *z2) *z2 = z;
+
+      glTranslatef(0.5, 0.5, 0.5);
+      glRotatef(90, 0.0, 0.0, -1.0);
+      glTranslatef(1.0 + explode, 0.0, 0.0);
+      glRotatef(180 + ang, 1.0, 0.0, 0.0);
+      glTranslatef(-0.5, -0.5, -0.5);
+    }
+fprintf(stderr, "\n");
+  glPopMatrix();
+
+#if 0
+  *x1 -= 1;
+  *y1 -= 1;
+  *z1 -= 1;
+  *x2 += 1;
+  *y2 += 1;
+  *z2 += 1;
+#endif
+}
+
+
+static void
+draw_bounding_box (ModeInfo *mi)
+{
+  static GLfloat c1[4] = { 0.4, 0.4, 0.4, 1.0 };
+  static GLfloat c2[4] = { 1.0, 0.0, 0.0, 1.0 };
+  int wire = MI_IS_WIREFRAME(mi);
+  GLfloat x1, y1, z1, x2, y2, z2;
+  snake_bounding_box (mi, &x1, &y1, &z1, &x2, &y2, &z2);
+
+  glColor3f (c1[0], c1[1], c1[2]);
+/*  glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, c1);*/
+  glFrontFace(GL_CCW);
+
+  glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
+  glNormal3f(0, 1, 0);
+  glVertex3f(x1, y1, z1); glVertex3f(x1, y1, z2);
+  glVertex3f(x2, y1, z2); glVertex3f(x2, y1, z1);
+  glEnd();
+  glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
+  glNormal3f(0, -1, 0);
+  glVertex3f(x2, y2, z1); glVertex3f(x2, y2, z2);
+  glVertex3f(x1, y2, z2); glVertex3f(x1, y2, z1);
+  glEnd();
+  glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
+  glNormal3f(0, 0, 1);
+  glVertex3f(x1, y1, z1); glVertex3f(x2, y1, z1);
+  glVertex3f(x2, y2, z1); glVertex3f(x1, y2, z1);
+  glEnd();
+  glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
+  glNormal3f(0, 0, -1);
+  glVertex3f(x1, y2, z2); glVertex3f(x2, y2, z2);
+  glVertex3f(x2, y1, z2); glVertex3f(x1, y1, z2);
+  glEnd();
+  glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
+  glNormal3f(1, 0, 0);
+  glVertex3f(x1, y2, z1); glVertex3f(x1, y2, z2);
+  glVertex3f(x1, y1, z2); glVertex3f(x1, y1, z1);
+  glEnd();
+  glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
+  glNormal3f(-1, 0, 0);
+  glVertex3f(x2, y1, z1); glVertex3f(x2, y1, z2);
+  glVertex3f(x2, y2, z2); glVertex3f(x2, y2, z1);
+  glEnd();
+
+  glPushAttrib (GL_LIGHTING);
+  glDisable (GL_LIGHTING);
+
+  glColor3f (c2[0], c2[1], c2[2]);
+  glBegin(GL_LINES);
+  if (x1 > 0) x1 = 0; if (x2 < 0) x2 = 0;
+  if (y1 > 0) y1 = 0; if (y2 < 0) y2 = 0;
+  if (z1 > 0) z1 = 0; if (z2 < 0) z2 = 0;
+  glVertex3f(x1, 0,  0);  glVertex3f(x2, 0,  0); 
+  glVertex3f(0 , y1, 0);  glVertex3f(0,  y2, 0); 
+  glVertex3f(0,  0,  z1); glVertex3f(0,  0,  z2); 
+  glEnd();
+
+  glPopAttrib();
 }
 
-void glsnake_draw(ModeInfo *mi) {
-       glsnake_configuration *bp = &glc[MI_SCREEN(mi)];
-       Display *dpy = MI_DISPLAY(mi);
-       Window window = MI_WINDOW(mi);
-
-       int i;
-       float ang;
-
-       if (!bp->glx_context)
-       return;
-
-       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
-       glMatrixMode(GL_MODELVIEW);
-       glLoadIdentity();
-       gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
-
-       /* rotate and translate into snake space */
-       glRotatef(45.0, -5.0, 0.0, 1.0);
-       glTranslatef(-0.5, 0.0, 0.5);
-
-       /* rotate the 0th junction */
-       glTranslatef(0.5, 0.0, 0.5);
-       /* glMultMatrix(rotation); -- quaternion rotation */
-       glRotatef(bp->roty, 0.0, 1.0, 0.0);
-       glRotatef(bp->rotz, 0.0, 0.0, 1.0);
-       glTranslated(-0.5, 0.0, -0.5);
-
-       /* translate middle node to centre */
-       for (i = 11; i >= 0; i--) {
-               ang = bp->node[i].cur_angle;
-               glTranslatef(0.5, 0.5, 0.5);
-               glRotatef(180+ang, -1.0, 0.0, 0.0);
-               glTranslatef(-1.0 - explode, 0.0, 0.0);
-               glRotatef(90, 0.0, 0.0, 1.0);
-               glTranslatef(-0.5, -0.5, -0.5);
-       }
-
-       /* now draw each node along the snake */
-       for (i = 0; i < 24; i++) {
-               glPushMatrix();
-
-               /* choose a colour for this node */
-               if (bp->interactive && (i == bp->selected || i == bp->selected+1))
-                       glColor3f(1.0, 1.0, 0.0);
-               else {
-                       if (i % 2) {
-                               if (scarycolour)
-                                       glColor3f(0.6, 0.0, 0.9);
-                               else
-                                       glColor3fv(bp->colour);
-                       } else {
-                               if (scarycolour)
-                                       glColor3f(0.2, 0.9, 1.0);
-                               else
-                                       glColor3f(1.0, 1.0, 1.0);
-                       }
-               }
-
-               /* draw the node */
-               glCallList(bp->node_list);
-
-               /* now work out where to draw the next one */
-
-               /* interpolate between models */
-               ang = bp->node[i].cur_angle;
-
-               glTranslatef(0.5, 0.5, 0.5);
-               glRotatef(90, 0.0, 0.0, -1.0);
-               glTranslatef(1.0 + explode, 0.0, 0.0);
-               glRotatef(180 + ang, 1.0, 0.0, 0.0);
-               glTranslatef(-0.5, -0.5, -0.5);
-       }
-
-       /* clear up the matrix stack */
-       for (i = 0; i < 24; i++)
-               glPopMatrix();
-
-       if (labels)
-               draw_label(mi);
-       
-       if (mi->fps_p)
-               do_fps (mi);
-
-       glsnake_idol(bp);
-       
-       glFlush();
-       glXSwapBuffers(dpy, window);
+
+void glsnake_draw(ModeInfo *mi)
+{
+  glsnake_configuration *bp = &glc[MI_SCREEN(mi)];
+  Display *dpy = MI_DISPLAY(mi);
+  Window window = MI_WINDOW(mi);
+
+  int i;
+  float ang;
+
+  if (!bp->glx_context)
+      return;
+
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
+
+  /* rotate and translate into snake space */
+  glRotatef(45.0, -5.0, 0.0, 1.0);
+  glTranslatef(-0.5, 0.0, 0.5);
+
+  /* rotate the 0th junction */
+  glTranslatef(0.5, 0.0, 0.5);
+  /* glMultMatrix(rotation); -- quaternion rotation */
+  glRotatef(bp->roty, 0.0, 1.0, 0.0);
+  glRotatef(bp->rotz, 0.0, 0.0, 1.0);
+  glTranslated(-0.5, 0.0, -0.5);
+
+  /* translate middle node to centre */
+  for (i = 11; i >= 0; i--) {
+    ang = bp->node[i].cur_angle;
+    glTranslatef(0.5, 0.5, 0.5);
+    glRotatef(180+ang, -1.0, 0.0, 0.0);
+    glTranslatef(-1.0 - explode, 0.0, 0.0);
+    glRotatef(90, 0.0, 0.0, 1.0);
+    glTranslatef(-0.5, -0.5, -0.5);
+  }
+
+  /* now draw each node along the snake */
+  glPushMatrix();
+  for (i = 0; i < 24; i++) {
+
+    /* choose a colour for this node */
+    if (bp->interactive && (i == bp->selected || i == bp->selected+1))
+      glColor3f(1.0, 1.0, 0.0);
+    else {
+      if (i % 2) {
+        if (scarycolour)
+          glColor3f(0.6, 0.0, 0.9);
+        else
+          glColor3fv(bp->colour);
+      } else {
+        if (scarycolour)
+          glColor3f(0.2, 0.9, 1.0);
+        else
+          glColor3f(1.0, 1.0, 1.0);
+      }
+    }
+
+#if 0 /* #### */ 
+    if (i == 0) glColor3f(0.0, 1.0, 1.0);
+#endif
+
+    /* draw the node */
+    glCallList(bp->node_list);
+
+    /* now work out where to draw the next one */
+
+    /* interpolate between models */
+    ang = bp->node[i].cur_angle;
+
+    glTranslatef(0.5, 0.5, 0.5);
+    glRotatef(90, 0.0, 0.0, -1.0);
+    glTranslatef(1.0 + explode, 0.0, 0.0);
+    glRotatef(180 + ang, 1.0, 0.0, 0.0);
+    glTranslatef(-0.5, -0.5, -0.5);
+  }
+
+  glPopMatrix();
+
+  if (do_bbox)
+    draw_bounding_box (mi);
+
+  if (labels)
+    draw_label(mi);
+  
+  if (mi->fps_p)
+    do_fps (mi);
+
+  glsnake_idol(bp);
+  
+  glFlush();
+  glXSwapBuffers(dpy, window);
 }
 
 #endif /* USE_GL */