home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 109 / EnigmaAmiga109CD.iso / software / sviluppo / mesa-glut / test / glut / bigtest.c < prev    next >
C/C++ Source or Header  |  1998-10-23  |  58KB  |  2,597 lines

  1.  
  2. /**
  3.  * My first GLUT prog.
  4.  * Uses most GLUT calls to prove it all works.
  5.  * G Edwards, 30 Aug 95.
  6.  *
  7.  * Notes:
  8.  * Display lists are not shared between windows, and there doesn't seem to be
  9.  *  any provision for this in GLUT. See glxCreateContext.
  10.  *
  11.  * The windows are internally indexed 0,1,2,3,4,5,6. The actual window ids
  12.  * returned by glut are held in winId[0], ...
  13.  *
  14.  * Todo:
  15.  *
  16.  * Could reorder the windows so 0,1,2,3,4,5,6 are the gfx, 7,8 text.
  17.  *
  18.  * 30 Aug 95  GJE  Created. Version 1.00
  19.  * 05 Sep 95  GJE  Version 1.01. 
  20.  * 07 Sep 95  GJE  Version 1.02. More or less complete. All possible GLUT
  21.  *                 calls used, except dials/buttons/tablet/spaceball stuff.
  22.  * 15 Sep 95  GJE  Add "trackball" code.
  23.  *
  24.  *  Calls not used yet: these callbacks are registered but inactive.
  25.  *
  26.  *  glutSpaceball<xxx>Func
  27.  *  glutButtonBoxFunc
  28.  *  glutDialsFunc
  29.  *  glutTabletMotionFunc
  30.  *  glutTabletButtonFunc
  31.  *
  32.  * Tested on:
  33.  *  R3K Indigo Starter
  34.  *  R4K Indigo Elan
  35.  *  R4K Indy XZ
  36.  *  R4K Indy XL
  37.  *  R4K Indigo2 Extreme
  38.  */
  39.  
  40. #include <GL/glut.h>
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #include <math.h>
  45.  
  46. /* Controls */
  47.  
  48. #define VERSION    "1.00"
  49. #define DATE       "16Sep95"
  50. #define DELAY      1000 /* delay for timer test */
  51. #define MENUDELAY  200  /* hack to fix glutMenuStateFunc bug */
  52. #define MAXWIN     9    /* max no. of windows */
  53.  
  54. unsigned int AUTODELAY = 1500;   /* delay in demo mode  */
  55.  
  56. #define VERSIONLONG "Version " VERSION "/" DATE ", compiled " __DATE__ ", " __TIME__ ", file " __FILE__
  57.  
  58. int pos[MAXWIN][2] =
  59. {
  60.   {50, 150},            /* win 0  */
  61.   {450, 150},           /* win 1  */
  62.   {50, 600},            /* win 2  */
  63.   {450, 600},           /* win 3  */
  64.   {10, 10},             /* subwin 4 (relative to parent win 0) */
  65.   {300, 400},           /* help win 5  */
  66.   {850, 150},           /* cmap win 6  */
  67.   {850, 600},           /* cmap win 7  */
  68.   {250, 450}            /* text win 8  */
  69. };
  70.  
  71. int size[MAXWIN][2] =
  72. {
  73.   {350, 350},           /* win 0  */
  74.   {350, 350},           /* win 1  */
  75.   {350, 350},           /* win 2  */
  76.   {350, 350},           /* win 3  */
  77.   {200, 200},           /* subwin 4  */
  78.   {700, 300},           /* help win 5  */
  79.   {350, 350},           /* cmap win 6  */
  80.   {350, 350},           /* cmap win 7  */
  81.   {800, 450}            /* text win 8  */
  82. };
  83.  
  84. /* Macros */
  85.  
  86. #define PR     if(debug)printf
  87.  
  88. /* #define GLNEWLIST(a, b)  glNewList(a, b), fprintf(stderr,
  89.    "creating list %d \n", a); */
  90. /* #define GLCALLLIST(a)    glCallList(a), fprintf(stderr,
  91.    "calling list %d \n", a); */
  92. /* #define GLUTSETWINDOW(x) glutSetWindow(x), fprintf(stderr,
  93.    "gsw at %d\n", __LINE__) */
  94.  
  95. /* Globals */
  96.  
  97. int winId[MAXWIN] =
  98. {0};                    /* table of glut window id's  */
  99. GLboolean winVis[MAXWIN] =
  100. {GL_FALSE};                /* is window visible  */
  101.  
  102. GLboolean text[MAXWIN] =
  103. {GL_FALSE};                /* is text on  */
  104. GLboolean winFreeze[MAXWIN] =
  105. {GL_FALSE};                /* user requested menuFreeze  */
  106. GLboolean menuFreeze = GL_FALSE;  /* menuFreeze while menus posted  */
  107. GLboolean timerOn = GL_FALSE;  /* timer active  */
  108. GLboolean animation = GL_TRUE;  /* idle func animation on  */
  109. GLboolean debug = GL_FALSE;  /* dump all events  */
  110. GLboolean showKeys = GL_FALSE;  /* dump key events  */
  111. GLboolean demoMode = GL_FALSE;  /* run automatic demo  */
  112. GLboolean backdrop = GL_FALSE;  /* use backdrop polygon  */
  113. GLboolean passive = GL_FALSE;  /* report passive motions  */
  114. GLboolean leftDown = GL_FALSE;  /* left button down ?  */
  115. GLboolean middleDown = GL_FALSE;  /* middle button down ?  */
  116.  
  117. int displayMode = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH;
  118. int currentShape = 0;   /* current glut shape  */
  119. int scrollLine = 0, scrollCol = 0;  /* help scrolling params  */
  120. int lineWidth = 1;      /* line width  */
  121. int angle = 0;      /* global rotation angle  */
  122. char *textPtr[1000] =
  123. {0};                    /* pointers to text window text  */
  124. int textCount = 0, helpCount = 0;  /* text list indexes  */
  125. float scaleFactor = 0.0;  /* window size scale factor  */
  126.  
  127. #ifdef ALPHA
  128. #undef ALPHA  /* Avoid problems with DEC's ALPHA machines. */
  129. #endif
  130.  
  131. int menu1, menu2, menu3, menu4, menu5, menu6 = 0, menu7, menu8;
  132. enum {
  133.   RGBA, INDEX, SINGLE, DOUBLEBUFFER, DEPTH, ACCUM, ALPHA, STENCIL, MULTISAMPLE,
  134.   STEREO, MODES
  135. };
  136. char *modeNames[] =
  137. {"RGBA", "INDEX", "SINGLE", "DOUBLE", "DEPTH", "ACCUM",
  138.   "ALPHA", "STENCIL", "MULTISAMPLE", "STEREO"};
  139. int glutMode[] =
  140. {GLUT_RGBA, GLUT_INDEX, GLUT_SINGLE, GLUT_DOUBLE, GLUT_DEPTH,
  141.   GLUT_ACCUM, GLUT_ALPHA, GLUT_STENCIL, GLUT_MULTISAMPLE, GLUT_STEREO};
  142. int modes[MODES] =
  143. {0};
  144. GLboolean menuButton[3] =
  145. {0, 0, 1};
  146. enum {
  147.   MOUSEBUTTON, MOUSEMOTION, APPLY, RESET
  148. };
  149.  
  150. /* Prototypes */
  151.  
  152. void gfxInit(int);
  153. void drawScene(void);
  154. void idleFunc(void);
  155. void reshapeFunc(int width, int height);
  156. void visible(int state);
  157. void keyFunc(unsigned char key, int x, int y);
  158. void mouseFunc(int button, int state, int x, int y);
  159. void motionFunc(int x, int y);
  160. void passiveMotionFunc(int x, int y);
  161. void entryFunc(int state);
  162. void specialFunc(int key, int x, int y);
  163. void menuStateFunc(int state);
  164. void timerFunc(int value);
  165. #if 0
  166. void delayedReinstateMenuStateCallback(int value);
  167. #endif
  168. void menuFunc(int value);
  169. void showText(void);
  170. void textString(int x, int y, char *str, void *font);
  171. void strokeString(int x, int y, char *str, void *font);
  172. void makeMenus(void);
  173. int idToIndex(int id);
  174. void setInitDisplayMode(void);
  175. void createMenu6(void);
  176. void removeCallbacks(void);
  177. void addCallbacks(void);
  178. void dumpIds(void);
  179. void updateHelp(void);
  180. void updateAll(void);
  181. void killWindow(int index);
  182. void makeWindow(int index);
  183. void warning(char *msg);
  184. void autoDemo(int);
  185. void positionWindow(int index);
  186. void reshapeWindow(int index);
  187. void iconifyWindow(int index);
  188. void showWindow(int index);
  189. void hideWindow(int index);
  190. void pushWindow(int index);
  191. void popWindow(int index);
  192. void attachMenus(void);
  193. void killAllWindows(void);
  194. void makeAllWindows(void);
  195. void updateText(void);
  196. void updateScrollWindow(int index, char **ptr);
  197. void redefineShapes(int shape);
  198. GLboolean match(char *, char *);
  199. void checkArgs(int argc, char *argv[]);
  200. void scaleWindows(float);
  201. void commandLineHelp(void);
  202. void trackBall(int mode, int button, int state, int x, int y);
  203.  
  204. void spaceballMotionCB(int, int, int);
  205. void spaceballRotateCB(int, int, int);
  206. void spaceballButtonCB(int, int);
  207. void buttonBoxCB(int, int);
  208. void dialsCB(int, int);
  209. void tabletMotionCB(int, int);
  210. void tabletButtonCB(int, int, int, int);
  211.  
  212. /* strdup is actually not a standard ANSI C or POSIX routine
  213.    so implement a private one.  OpenVMS does not have a strdup; Linux's
  214.    standard libc doesn't declare strdup by default (unless BSD or SVID
  215.    interfaces are requested). */
  216. static char *
  217. stralloc(const char *string)
  218. {
  219.   char *copy;
  220.  
  221.   copy = malloc(strlen(string) + 1);
  222.   if (copy == NULL)
  223.     return NULL;
  224.   strcpy(copy, string);
  225.   return copy;
  226. }
  227.  
  228. /* main */
  229.  
  230. int
  231. main(int argc, char **argv)
  232. {
  233.  
  234. /* General init */
  235.  
  236.   glutInit(&argc, argv);
  237.  
  238. /* Check args */
  239.  
  240.   checkArgs(argc, argv);
  241.  
  242. /* Scale window position/size if needed. Ignore aspect ratios. */
  243.  
  244.   if (scaleFactor > 0.0)
  245.     scaleWindows(scaleFactor);
  246.   else
  247.     scaleWindows(glutGet(GLUT_SCREEN_WIDTH) / 1280.0);
  248.  
  249. /* Set initial display mode */
  250.  
  251.   modes[RGBA] = 1;
  252.   modes[DOUBLEBUFFER] = 1;
  253.   modes[DEPTH] = 1;
  254.   setInitDisplayMode();
  255.  
  256. /* Set up menus */
  257.  
  258.   makeMenus();
  259.  
  260. /* Make some windows */
  261.  
  262.   makeWindow(0);
  263.   makeWindow(1);
  264.  
  265. /* Global callbacks */
  266.  
  267.   glutIdleFunc(idleFunc);
  268.   glutMenuStateFunc(menuStateFunc);
  269.  
  270. /* Start demo if needed */
  271.  
  272.   if (demoMode)
  273.     autoDemo(-2);
  274.  
  275. /* Fall into event loop */
  276.  
  277.   glutMainLoop();
  278.   return 0;             /* ANSI C requires main to return int. */
  279. }
  280.  
  281. /* gfxInit - Init opengl for each window */
  282.  
  283. void
  284. gfxInit(int index)
  285. {
  286.   GLfloat grey10[] =
  287.   {0.10, 0.10, 0.10, 1.0};
  288.   GLfloat grey20[] =
  289.   {0.2, 0.2, 0.2, 1.0};
  290.   GLfloat black[] =
  291.   {0.0, 0.0, 0.0, 0.0};
  292.   GLfloat diffuse0[] =
  293.   {1.0, 0.0, 0.0, 1.0};
  294.   GLfloat diffuse1[] =
  295.   {0.0, 1.0, 0.0, 1.0};
  296.   GLfloat diffuse2[] =
  297.   {1.0, 1.0, 0.0, 1.0};
  298.   GLfloat diffuse3[] =
  299.   {0.0, 1.0, 1.0, 1.0};
  300.   GLfloat diffuse4[] =
  301.   {1.0, 0.0, 1.0, 1.0};
  302.  
  303. #define XX  3
  304. #define YY  3
  305. #define ZZ  -2.5
  306.  
  307.   float vertex[][3] =
  308.   {
  309.     {-XX, -YY, ZZ},
  310.     {+XX, -YY, ZZ},
  311.     {+XX, +YY, ZZ},
  312.     {-XX, +YY, ZZ}
  313.   };
  314.  
  315. /* warning: This func mixes RGBA and CMAP calls in an ugly
  316.    fashion */
  317.  
  318.   redefineShapes(currentShape);  /* set up display lists  */
  319.   glutSetWindow(winId[index]);  /* hack - redefineShapes
  320.                                    changes glut win */
  321.  
  322. /* Shaded backdrop square (RGB or CMAP) */
  323.  
  324.   glNewList(100, GL_COMPILE);
  325.   glPushAttrib(GL_LIGHTING);
  326.   glDisable(GL_LIGHTING);
  327.   glBegin(GL_POLYGON);
  328.  
  329.   glColor4fv(black);
  330.   glIndexi(0);
  331.   glVertex3fv(vertex[0]);
  332.  
  333.   glColor4fv(grey10);
  334.   glIndexi(3);
  335.   glVertex3fv(vertex[1]);
  336.  
  337.   glColor4fv(grey20);
  338.   glIndexi(4);
  339.   glVertex3fv(vertex[2]);
  340.  
  341.   glColor4fv(grey10);
  342.   glIndexi(7);
  343.   glVertex3fv(vertex[3]);
  344.  
  345.   glEnd();
  346.   glPopAttrib();
  347.   glIndexi(9);
  348.   glEndList();
  349.  
  350. /* Set proj+view */
  351.  
  352.   glMatrixMode(GL_PROJECTION);
  353.   glLoadIdentity();
  354.   gluPerspective(40.0, 1.0, 1.0, 20.0);
  355.   glMatrixMode(GL_MODELVIEW);
  356.   glLoadIdentity();
  357.   gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.);
  358.   glTranslatef(0.0, 0.0, -1.0);
  359.  
  360.   if (index == 6 || index == 7)
  361.     goto colorindex;
  362.  
  363. /* Set basic material, lighting for RGB windows */
  364.  
  365.   if (index == 0)
  366.     glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse0);
  367.   else if (index == 1)
  368.     glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse1);
  369.   else if (index == 2)
  370.     glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse2);
  371.   else if (index == 3)
  372.     glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse3);
  373.   else if (index == 4)
  374.     glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse4);
  375.  
  376.   glEnable(GL_LIGHTING);
  377.   glEnable(GL_LIGHT0);
  378.   glEnable(GL_DEPTH_TEST);
  379.  
  380.   if (index == 4)
  381.     glClearColor(0.15, 0.15, 0.15, 1);
  382.   else
  383.     glClearColor(0.1, 0.1, 0.1, 1.0);
  384.  
  385.   return;
  386.  
  387. /* Set GL basics for CMAP windows 6,7 */
  388.  
  389. colorindex:
  390.  
  391.   glEnable(GL_DEPTH_TEST);
  392.   if (glutGet(GLUT_WINDOW_COLORMAP_SIZE) < 16)
  393.     warning("Color map size too small for color index window");
  394.  
  395. /* Try to reuse an existing color map */
  396.  
  397.   if ((index == 6) && (winId[7] != 0)) {
  398.     glutCopyColormap(winId[7]);
  399.   } else if ((index == 7) && (winId[6] != 0)) {
  400.     glutCopyColormap(winId[6]);
  401.   } else {
  402.     glutSetColor(8, 0.1, 0.1, 0.1);
  403.     glutSetColor(9, 1.0, 0.5, 0.0);
  404.     glutSetColor(10, 1.0, 0.6, 0.8);
  405.   }
  406.   glClearIndex(8);
  407.   glIndexi(index + 3);
  408.  
  409. }
  410.  
  411. /* makeMenus - Create popup menus */
  412.  
  413. void
  414. makeMenus(void)
  415. {
  416.  
  417. /* General control / debug */
  418.  
  419.   menu2 = glutCreateMenu(menuFunc);
  420.   glutAddMenuEntry("toggle auto demo mode (a)", 312);
  421.   glutAddMenuEntry("toggle freezing in menus", 300);
  422.   glutAddMenuEntry("toggle text per window (t)", 301);
  423.   glutAddMenuEntry("toggle global timer", 302);
  424.   glutAddMenuEntry("toggle global animation", 303);
  425.   glutAddMenuEntry("toggle per window animation", 304);
  426.   glutAddMenuEntry("toggle debug prints (D)", 305);
  427.   glutAddMenuEntry("toggle shaded backdrop", 307);
  428.   glutAddMenuEntry("toggle passive motion callback", 308);
  429.   glutAddMenuEntry("increase line width (l)", 310);
  430.   glutAddMenuEntry("decrease line width  (L)", 311);
  431.  
  432. /* Shapes */
  433.  
  434.   menu3 = glutCreateMenu(menuFunc);
  435.   glutAddMenuEntry("sphere", 200);
  436.   glutAddMenuEntry("cube", 201);
  437.   glutAddMenuEntry("cone", 202);
  438.   glutAddMenuEntry("torus", 203);
  439.   glutAddMenuEntry("dodecahedron", 204);
  440.   glutAddMenuEntry("octahedron", 205);
  441.   glutAddMenuEntry("tetrahedron", 206);
  442.   glutAddMenuEntry("icosahedron", 207);
  443.   glutAddMenuEntry("teapot", 208);
  444.  
  445. /* Open/close windows */
  446.  
  447.   menu4 = glutCreateMenu(menuFunc);
  448.   glutAddMenuEntry("open all windows", 450);
  449.   glutAddMenuEntry("close all windows", 451);
  450.   glutAddMenuEntry(" ", 9999);
  451.   glutAddMenuEntry("create win 0", 400);
  452.   glutAddMenuEntry("create win 1", 401);
  453.   glutAddMenuEntry("create win 2", 402);
  454.   glutAddMenuEntry("create win 3", 403);
  455.   glutAddMenuEntry("create sub window", 404);
  456.   glutAddMenuEntry("create color index win 6", 406);
  457.   glutAddMenuEntry("create color index win 7", 407);
  458.   glutAddMenuEntry(" ", 9999);
  459.   glutAddMenuEntry("destroy win 0", 410);
  460.   glutAddMenuEntry("destroy win 1", 411);
  461.   glutAddMenuEntry("destroy win 2", 412);
  462.   glutAddMenuEntry("destroy win 3", 413);
  463.   glutAddMenuEntry("destroy sub window", 414);
  464.   glutAddMenuEntry("destroy color index win 6", 416);
  465.   glutAddMenuEntry("destroy color index win 7", 417);
  466.  
  467. /* Window manager stuff */
  468.  
  469.   menu5 = glutCreateMenu(menuFunc);
  470.   glutAddMenuEntry("move current win", 430);
  471.   glutAddMenuEntry("resize current win", 431);
  472.   glutAddMenuEntry("iconify current win", 432);
  473.   glutAddMenuEntry("show current win", 433);
  474.   glutAddMenuEntry("hide current win", 434);
  475.   glutAddMenuEntry("push current win", 435);
  476.   glutAddMenuEntry("pop current win", 436);
  477.   glutAddMenuEntry(" ", 9999);
  478.   glutAddMenuEntry("move win 1", 420);
  479.   glutAddMenuEntry("resize win 1", 421);
  480.   glutAddMenuEntry("iconify win 1", 422);
  481.   glutAddMenuEntry("show win 1", 423);
  482.   glutAddMenuEntry("hide win 1", 424);
  483.   glutAddMenuEntry("push win 1", 425);
  484.   glutAddMenuEntry("pop win 1", 426);
  485.  
  486. /* Gfx modes */
  487.  
  488.   createMenu6();        /* build dynamically  */
  489.  
  490. /* Texty reports */
  491.  
  492.   menu7 = glutCreateMenu(menuFunc);
  493.   glutAddMenuEntry("report current win modes", 700);
  494.   glutAddMenuEntry("report current device data", 701);
  495.   glutAddMenuEntry("check OpenGL extensions", 702);
  496.   glutAddMenuEntry("dump internal data (d)", 703);
  497.  
  498. /* Play with menus */
  499.  
  500.   menu8 = glutCreateMenu(menuFunc);
  501.   glutAddMenuEntry("toggle menus on left button", 805);
  502.   glutAddMenuEntry("toggle menus on middle button", 806);
  503.   glutAddMenuEntry("toggle menus on right button", 807);
  504.   glutAddMenuEntry("---------------------------", 9999);
  505.   glutAddMenuEntry("add plain items", 800);
  506.   glutAddMenuEntry("add submenu items", 801);
  507.   glutAddMenuEntry("change new entries to plain items", 802);
  508.   glutAddMenuEntry("change new entries to submenus", 803);
  509.   glutAddMenuEntry("remove all new items", 804);
  510.   glutAddMenuEntry("---------------------------", 9999);
  511.  
  512. /* Main menu */
  513.  
  514.   menu1 = glutCreateMenu(menuFunc);
  515.   glutAddSubMenu("control", menu2);
  516.   glutAddSubMenu("shapes", menu3);
  517.   glutAddSubMenu("windows", menu4);
  518.   glutAddSubMenu("window ops", menu5);
  519.   glutAddSubMenu("gfx modes", menu6);
  520.   glutAddSubMenu("reports", menu7);
  521.   glutAddSubMenu("menus", menu8);
  522.   glutAddMenuEntry("help (h)", 101);
  523.   glutAddMenuEntry("quit (esc)", 100);
  524. }
  525.  
  526. /* createMenu6 - Dynamically rebuild menu of display modes to
  527.    show current choices */
  528.  
  529. void
  530. createMenu6(void)
  531. {
  532.   char str[100];
  533.   int i;
  534.  
  535.   if (menu6 != 0)
  536.     glutDestroyMenu(menu6);
  537.   menu6 = glutCreateMenu(menuFunc);
  538.  
  539.   for (i = 0; i < MODES; i++) {
  540.     sprintf(str, "%srequest %s", (modes[i] ? "+ " : "   "), modeNames[i]);
  541.     glutAddMenuEntry(str, 602 + i);
  542.   }
  543. }
  544.  
  545. /* menuFunc - Process return codes from popup menus */
  546.  
  547. void
  548. menuFunc(int value)
  549. {
  550.   static int initItems = 10;
  551.   int items, m;
  552.  
  553.   if (initItems == 0) {
  554.     glutSetMenu(menu8);
  555.     initItems = glutGet(GLUT_MENU_NUM_ITEMS);
  556.   }
  557.   PR("Menu returned value %d \n", value);
  558.  
  559.   switch (value) {
  560.  
  561. /* GLUT shapes */
  562.  
  563.   case 200:
  564.   case 201:
  565.   case 202:
  566.   case 203:
  567.   case 204:
  568.   case 205:
  569.   case 206:
  570.   case 207:
  571.   case 208:
  572.     redefineShapes(value - 200);
  573.     break;
  574.  
  575. /* Overall controls */
  576.  
  577.   case 300:
  578.     menuFreeze = !menuFreeze;
  579.     break;
  580.  
  581.   case 301:
  582.     text[idToIndex(glutGetWindow())] = !(text[idToIndex(glutGetWindow())]);
  583.     break;
  584.  
  585.   case 302:
  586.     timerOn = !timerOn;
  587.     if (timerOn)
  588.       glutTimerFunc(DELAY, timerFunc, 1);
  589.     break;
  590.  
  591.   case 303:
  592.     animation = !animation;
  593.     if (animation)
  594.       glutIdleFunc(idleFunc);
  595.     else
  596.       glutIdleFunc(NULL);
  597.     break;
  598.  
  599.   case 304:
  600.     winFreeze[idToIndex(glutGetWindow())] = !(winFreeze[idToIndex(
  601.           glutGetWindow())]);
  602.     break;
  603.  
  604.   case 305:
  605.     debug = !debug;
  606.     break;
  607.  
  608.   case 307:
  609.     backdrop = !backdrop;
  610.     break;
  611.  
  612.   case 308:
  613.     passive = !passive;
  614.     if (passive)
  615.       glutPassiveMotionFunc(passiveMotionFunc);
  616.     else
  617.       glutPassiveMotionFunc(NULL);
  618.     break;
  619.  
  620.   case 310:
  621.     lineWidth += 1;
  622.     updateAll();
  623.     break;
  624.  
  625.   case 311:
  626.     lineWidth -= 1;
  627.     if (lineWidth < 1)
  628.       lineWidth = 1;
  629.     updateAll();
  630.     break;
  631.  
  632.   case 312:
  633.     demoMode = !demoMode;
  634.     if (demoMode)
  635.       autoDemo(-2);
  636.     break;
  637.  
  638. /* Window create/destroy. */
  639.  
  640. /* Creates */
  641.  
  642.   case 400:
  643.     makeWindow(0);
  644.     break;
  645.  
  646.   case 401:
  647.     makeWindow(1);
  648.     break;
  649.  
  650.   case 402:
  651.     makeWindow(2);
  652.     break;
  653.  
  654.   case 403:
  655.     makeWindow(3);
  656.     break;
  657.  
  658.   case 404:
  659.     makeWindow(4);
  660.     break;
  661.  
  662.   case 406:
  663.     makeWindow(6);
  664.     break;
  665.  
  666.   case 407:
  667.     makeWindow(7);
  668.     break;
  669.  
  670. /* Destroys */
  671.  
  672.   case 410:
  673.     killWindow(0);
  674.     break;
  675.  
  676.   case 411:
  677.     killWindow(1);
  678.     break;
  679.  
  680.   case 412:
  681.     killWindow(2);
  682.     break;
  683.  
  684.   case 413:
  685.     killWindow(3);
  686.     break;
  687.  
  688.   case 414:
  689.     killWindow(4);
  690.     break;
  691.  
  692.   case 416:
  693.     killWindow(6);
  694.     break;
  695.  
  696.   case 417:
  697.     killWindow(7);
  698.     break;
  699.  
  700.   case 450:
  701.     makeAllWindows();
  702.     break;
  703.  
  704.   case 451:
  705.     killAllWindows();
  706.     break;
  707.  
  708. /* Window movements etc. */
  709.  
  710.   case 420:
  711.     positionWindow(1);
  712.     break;
  713.  
  714.   case 421:
  715.     reshapeWindow(1);
  716.     break;
  717.  
  718.   case 422:
  719.     iconifyWindow(1);
  720.     break;
  721.  
  722.   case 423:
  723.     showWindow(1);
  724.     break;
  725.  
  726.   case 424:
  727.     hideWindow(1);
  728.     break;
  729.  
  730.   case 425:
  731.     pushWindow(1);
  732.     break;
  733.  
  734.   case 426:
  735.     popWindow(1);
  736.     break;
  737.  
  738.   case 430:
  739.     positionWindow(idToIndex(glutGetWindow()));
  740.     break;
  741.  
  742.   case 431:
  743.     reshapeWindow(idToIndex(glutGetWindow()));
  744.     break;
  745.  
  746.   case 432:
  747.     iconifyWindow(idToIndex(glutGetWindow()));
  748.     break;
  749.  
  750.   case 433:
  751.     showWindow(idToIndex(glutGetWindow()));
  752.     break;
  753.  
  754.   case 434:
  755.     hideWindow(idToIndex(glutGetWindow()));
  756.     break;
  757.  
  758.   case 435:
  759.     pushWindow(idToIndex(glutGetWindow()));
  760.     break;
  761.  
  762.   case 436:
  763.     popWindow(idToIndex(glutGetWindow()));
  764.     break;
  765.  
  766. /* Test gfx modes. */
  767.  
  768.   case 600:
  769.     makeWindow(3);
  770.     break;
  771.  
  772.   case 601:
  773.     killWindow(3);
  774.     break;
  775.  
  776.   case 602:
  777.   case 603:
  778.   case 604:
  779.   case 605:
  780.   case 606:
  781.   case 607:
  782.   case 608:
  783.   case 609:
  784.   case 610:
  785.   case 611:
  786.     modes[value - 602] = !modes[value - 602];
  787.     setInitDisplayMode();
  788.     break;
  789.  
  790. /* Text reports */
  791.  
  792. /* This is pretty ugly. */
  793.  
  794. #define INDENT 30
  795. #define REPORTSTART(text)                          \
  796.         printf("\n" text "\n");                    \
  797.         textPtr[0] = (char *)malloc(strlen(text)+1); \
  798.     strcpy(textPtr[0], text);                  \
  799.         textCount = 1;
  800.  
  801. #define REPORTEND                                  \
  802.         scrollLine = 0;                            \
  803.         textPtr[textCount] = NULL;                 \
  804.         makeWindow(8);                             \
  805.         updateText();
  806.  
  807. #define GLUTGET(name)                              \
  808.        {                                           \
  809.           char str[100], str2[100];                \
  810.           int s, len;                              \
  811.           sprintf(str, # name);                    \
  812.           len = (int) strlen(# name);              \
  813.           for(s = 0 ; s < INDENT-len; s++)         \
  814.             strcat(str, " ");                      \
  815.           sprintf(str2, ": %d\n",glutGet(name));   \
  816.       strcat(str, str2);                       \
  817.       printf(str);                             \
  818.       textPtr[textCount] = stralloc(str);      \
  819.        textCount++;                             \
  820.        }
  821.  
  822.   case 700:
  823.  
  824.     printf("XXXXXX glutGetWindow = %d\n", glutGetWindow());
  825.     REPORTSTART("glutGet():");
  826.  
  827.     GLUTGET(GLUT_WINDOW_X);
  828.     GLUTGET(GLUT_WINDOW_Y);
  829.     GLUTGET(GLUT_WINDOW_WIDTH);
  830.     GLUTGET(GLUT_WINDOW_HEIGHT);
  831.     GLUTGET(GLUT_WINDOW_BUFFER_SIZE);
  832.     GLUTGET(GLUT_WINDOW_STENCIL_SIZE);
  833.     GLUTGET(GLUT_WINDOW_DEPTH_SIZE);
  834.     GLUTGET(GLUT_WINDOW_RED_SIZE);
  835.     GLUTGET(GLUT_WINDOW_GREEN_SIZE);
  836.     GLUTGET(GLUT_WINDOW_BLUE_SIZE);
  837.     GLUTGET(GLUT_WINDOW_ALPHA_SIZE);
  838.     GLUTGET(GLUT_WINDOW_ACCUM_RED_SIZE);
  839.     GLUTGET(GLUT_WINDOW_ACCUM_GREEN_SIZE);
  840.     GLUTGET(GLUT_WINDOW_ACCUM_BLUE_SIZE);
  841.     GLUTGET(GLUT_WINDOW_ACCUM_ALPHA_SIZE);
  842.     GLUTGET(GLUT_WINDOW_DOUBLEBUFFER);
  843.     GLUTGET(GLUT_WINDOW_RGBA);
  844.     GLUTGET(GLUT_WINDOW_PARENT);
  845.     GLUTGET(GLUT_WINDOW_NUM_CHILDREN);
  846.     GLUTGET(GLUT_WINDOW_COLORMAP_SIZE);
  847.     GLUTGET(GLUT_WINDOW_NUM_SAMPLES);
  848.     GLUTGET(GLUT_STEREO);
  849.     GLUTGET(GLUT_SCREEN_WIDTH);
  850.     GLUTGET(GLUT_SCREEN_HEIGHT);
  851.     GLUTGET(GLUT_SCREEN_HEIGHT_MM);
  852.     GLUTGET(GLUT_SCREEN_WIDTH_MM);
  853.     GLUTGET(GLUT_MENU_NUM_ITEMS);
  854.     GLUTGET(GLUT_DISPLAY_MODE_POSSIBLE);
  855.     GLUTGET(GLUT_INIT_DISPLAY_MODE);
  856.     GLUTGET(GLUT_INIT_WINDOW_X);
  857.     GLUTGET(GLUT_INIT_WINDOW_Y);
  858.     GLUTGET(GLUT_INIT_WINDOW_WIDTH);
  859.     GLUTGET(GLUT_INIT_WINDOW_HEIGHT);
  860.     GLUTGET(GLUT_ELAPSED_TIME);
  861.  
  862.     REPORTEND;
  863.     break;
  864.  
  865. #define GLUTDEVGET(name)                         \
  866.         {                                        \
  867.           char str[100], str2[100];              \
  868.           int len, s;                            \
  869.           sprintf(str, # name);                  \
  870.           len = (int) strlen(# name);            \
  871.           for(s = 0 ; s < INDENT-len; s++)       \
  872.             strcat(str, " ");                    \
  873.           sprintf(str2, ": %d\n",                \
  874.          glutDeviceGet(name));               \
  875.       strcat(str, str2);                     \
  876.       printf(str);                           \
  877.       textPtr[textCount] = stralloc(str);    \
  878.        textCount++;                           \
  879.     }
  880.  
  881.   case 701:
  882.     REPORTSTART("glutDeviceGet():");
  883.  
  884.     GLUTDEVGET(GLUT_HAS_KEYBOARD);
  885.     GLUTDEVGET(GLUT_HAS_MOUSE);
  886.     GLUTDEVGET(GLUT_HAS_SPACEBALL);
  887.     GLUTDEVGET(GLUT_HAS_DIAL_AND_BUTTON_BOX);
  888.     GLUTDEVGET(GLUT_HAS_TABLET);
  889.     GLUTDEVGET(GLUT_NUM_MOUSE_BUTTONS);
  890.     GLUTDEVGET(GLUT_NUM_SPACEBALL_BUTTONS);
  891.     GLUTDEVGET(GLUT_NUM_BUTTON_BOX_BUTTONS);
  892.     GLUTDEVGET(GLUT_NUM_DIALS);
  893.     GLUTDEVGET(GLUT_NUM_TABLET_BUTTONS);
  894.  
  895.     REPORTEND;
  896.     break;
  897.  
  898. #define EXTCHECK(name)                           \
  899.         {                                        \
  900.           char str[100], str2[100];              \
  901.           int len, s;                            \
  902.           sprintf(str, # name);                  \
  903.           len = (int) strlen(# name);            \
  904.           for(s = 0 ; s < INDENT-len; s++)       \
  905.             strcat(str, " ");                    \
  906.           sprintf(str2, ": %s\n",                \
  907.          glutExtensionSupported(# name)?     \
  908.            "yes": "no");                     \
  909.       strcat(str, str2);                     \
  910.       printf(str);                           \
  911.       textPtr[textCount] = stralloc(str);    \
  912.        textCount++;                           \
  913.         }
  914.  
  915.   case 702:
  916.     REPORTSTART("glutExtensionSupported():");
  917.  
  918.     EXTCHECK(GL_EXT_abgr);
  919.     EXTCHECK(GL_EXT_blend_color);
  920.     EXTCHECK(GL_EXT_blend_minmax);
  921.     EXTCHECK(GL_EXT_blend_logic_op);
  922.     EXTCHECK(GL_EXT_blend_subtract);
  923.     EXTCHECK(GL_EXT_polygon_offset);
  924.     EXTCHECK(GL_EXT_texture);
  925.     EXTCHECK(GL_EXT_guaranteed_to_fail);
  926.     EXTCHECK(GLX_SGI_swap_control);
  927.     EXTCHECK(GLX_SGI_video_sync);
  928.     EXTCHECK(GLX_SGIS_multi_sample);
  929.  
  930.     REPORTEND;
  931.     break;
  932.  
  933.   case 703:
  934.     dumpIds();
  935.     break;
  936.  
  937. /* Mess around with menus */
  938.  
  939.   case 800:
  940.     if (glutGetMenu() != menu8)  /* just a test  */
  941.       printf("glutGetMenu() returned unexpected value\n");
  942.     glutAddMenuEntry("help", 101);
  943.     glutAddMenuEntry("help", 101);
  944.     glutAddMenuEntry("help", 101);
  945.     glutAddMenuEntry("help", 101);
  946.     glutAddMenuEntry("help", 101);
  947.     break;
  948.  
  949.   case 801:
  950.     glutAddSubMenu("shapes", menu3);
  951.     glutAddSubMenu("shapes", menu3);
  952.     glutAddSubMenu("shapes (a long string to break menus with)", menu3);
  953.     glutAddSubMenu("shapes", menu3);
  954.     glutAddSubMenu("shapes", menu3);
  955.     break;
  956.  
  957.   case 802:
  958.     items = glutGet(GLUT_MENU_NUM_ITEMS);
  959.     for (m = initItems + 1; m <= items; m++) {
  960.       glutChangeToMenuEntry(m, "help", 101);
  961.     }
  962.     break;
  963.  
  964.   case 803:
  965.     items = glutGet(GLUT_MENU_NUM_ITEMS);
  966.     for (m = initItems + 1; m <= items; m++) {
  967.       glutChangeToSubMenu(m, "shapes", menu3);
  968.     }
  969.     break;
  970.  
  971.   case 804:
  972.     items = glutGet(GLUT_MENU_NUM_ITEMS);
  973.     /* reverse order so renumbering not aproblem  */
  974.     for (m = items; m >= initItems + 1; m--) {
  975.       glutRemoveMenuItem(m);
  976.     }
  977.     break;
  978.  
  979.   case 805:
  980.     menuButton[0] = !menuButton[0];
  981.     attachMenus();
  982.     break;
  983.  
  984.   case 806:
  985.     menuButton[1] = !menuButton[1];
  986.     attachMenus();
  987.     break;
  988.  
  989.   case 807:
  990.     menuButton[2] = !menuButton[2];
  991.     attachMenus();
  992.     break;
  993.  
  994. /* Direct menu items.  */
  995.  
  996.   case 100:
  997.     exit(0);
  998.     break;
  999.  
  1000.   case 101:
  1001.     if (winId[5] == 0)
  1002.       makeWindow(5);
  1003.     else
  1004.       killWindow(5);
  1005.     break;
  1006.  
  1007.   case 9999:
  1008.     break;
  1009.  
  1010.   default:
  1011.     fprintf(stderr, "\007Unhandled case %d in menu callback\n", value);
  1012.   }
  1013.  
  1014. }
  1015.  
  1016. /* redefineShapes - Remake the shapes display lists */
  1017.  
  1018. void
  1019. redefineShapes(int shape)
  1020. {
  1021.   int i;
  1022.  
  1023. #define C3                \
  1024.         switch(i)        \
  1025.      {                \
  1026.          case 0:      \
  1027.          case 3:      \
  1028.            C1;        \
  1029.            break;     \
  1030.                       \
  1031.          case 1:      \
  1032.          case 2:      \
  1033.          case 4:      \
  1034.          case 6:      \
  1035.          case 7:      \
  1036.            C2;        \
  1037.            break;     \
  1038.      }                \
  1039.      currentShape = shape
  1040.  
  1041.   for (i = 0; i < MAXWIN; i++) {
  1042.     if (winId[i]) {
  1043.       glutSetWindow(winId[i]);
  1044.       if (glIsList(i + 1))
  1045.         glDeleteLists(i + 1, 1);
  1046.       glNewList(i + 1, GL_COMPILE);
  1047.  
  1048.       switch (shape) {
  1049.  
  1050. #undef  C1
  1051. #define C1  glutSolidSphere(1.5, 10, 10)
  1052. #undef  C2
  1053. #define C2  glutWireSphere(1.5, 10, 10)
  1054.  
  1055.       case 0:
  1056.         C3;
  1057.         break;
  1058.  
  1059. #undef  C1
  1060. #define C1 glutSolidCube(2)
  1061. #undef  C2
  1062. #define C2 glutWireCube(2)
  1063.  
  1064.       case 1:
  1065.         C3;
  1066.         break;
  1067.  
  1068. #undef  C1
  1069. #define C1 glutSolidCone(1.5, 1.75, 10, 10);
  1070. #undef  C2
  1071. #define C2 glutWireCone(1.5, 1.75, 10, 10);
  1072.  
  1073.       case 2:
  1074.         C3;
  1075.         break;
  1076.  
  1077. #undef  C1
  1078. #define C1 glutSolidTorus(0.5, 1.1, 10, 10)
  1079. #undef  C2
  1080. #define C2 glutWireTorus(0.5, 1.1, 10, 10)
  1081.  
  1082.       case 3:
  1083.         C3;
  1084.         break;
  1085.  
  1086. #undef  C1
  1087. #define C1 glScalef(.8, .8, .8);glutSolidDodecahedron()
  1088. #undef  C2
  1089. #define C2 glScalef(.8, .8, .8);glutWireDodecahedron()
  1090.  
  1091.       case 4:
  1092.         C3;
  1093.         break;
  1094.  
  1095. #undef  C1
  1096. #define C1 glScalef(1.5, 1.5, 1.5);glutSolidOctahedron()
  1097. #undef  C2
  1098. #define C2 glScalef(1.5, 1.5, 1.5);glutWireOctahedron()
  1099.  
  1100.       case 5:
  1101.         C3;
  1102.         break;
  1103.  
  1104. #undef  C1
  1105. #define C1 glScalef(1.8, 1.8, 1.8);glutSolidTetrahedron()
  1106. #undef  C2
  1107. #define C2 glScalef(1.8, 1.8, 1.8);glutWireTetrahedron()
  1108.  
  1109.       case 6:
  1110.         C3;
  1111.         break;
  1112.  
  1113. #undef  C1
  1114. #define C1 glScalef(1.5, 1.5, 1.5);glutSolidIcosahedron()
  1115. #undef  C2
  1116. #define C2 glScalef(1.5, 1.5, 1.5);glutWireIcosahedron()
  1117.  
  1118.       case 7:
  1119.         C3;
  1120.         break;
  1121.  
  1122. #undef  C1
  1123. #define C1 glutSolidTeapot(1.5);
  1124. #undef  C2
  1125. #define C2 glutWireTeapot(1.5);
  1126.  
  1127.       case 8:
  1128.         C3;
  1129.         break;
  1130.       }
  1131.       glEndList();
  1132.     }
  1133.   }
  1134. }
  1135.  
  1136. /* positionWindow - Shift a window */
  1137.  
  1138. void
  1139. positionWindow(int index)
  1140. {
  1141.   int x, y;
  1142.  
  1143.   if (winId[index] == 0)
  1144.     return;
  1145.  
  1146.   glutSetWindow(winId[index]);
  1147.   x = glutGet(GLUT_WINDOW_X);
  1148.   y = glutGet(GLUT_WINDOW_Y);
  1149.   glutPositionWindow(x + 50, y + 50);
  1150. }
  1151.  
  1152. /* reshapeWindow - Change window size a little */
  1153.  
  1154. void
  1155. reshapeWindow(int index)
  1156. {
  1157.   int x, y;
  1158.  
  1159.   if (winId[index] == 0)
  1160.     return;
  1161.   glutSetWindow(winId[index]);
  1162.   x = glutGet(GLUT_WINDOW_WIDTH);
  1163.   y = glutGet(GLUT_WINDOW_HEIGHT);
  1164. /* glutReshapeWindow(x * (index % 2? 0.8: 1.2), y * (index % 2? 
  1165.  
  1166.    1.2: 0.8)); */
  1167.   glutReshapeWindow((int) (x * 1.0), (int) (y * 0.8));
  1168. }
  1169.  
  1170. /* iconifyWindow - Iconify a window */
  1171.  
  1172. void
  1173. iconifyWindow(int index)
  1174. {
  1175.   if (winId[index] == 0)
  1176.     return;
  1177.   glutSetWindow(winId[index]);
  1178.   glutIconifyWindow();
  1179. }
  1180.  
  1181. /* showWindow - Show a window (map or uniconify it) */
  1182.  
  1183. void
  1184. showWindow(int index)
  1185. {
  1186.   if (winId[index] == 0)
  1187.     return;
  1188.   glutSetWindow(winId[index]);
  1189.   glutShowWindow();
  1190. }
  1191.  
  1192. /* hideWindow - Hide a window (unmap it) */
  1193.  
  1194. void
  1195. hideWindow(int index)
  1196. {
  1197.   if (winId[index] == 0)
  1198.     return;
  1199.   glutSetWindow(winId[index]);
  1200.   glutHideWindow();
  1201. }
  1202.  
  1203. /* pushWindow - Push a window */
  1204.  
  1205. void
  1206. pushWindow(int index)
  1207. {
  1208.   if (winId[index] == 0)
  1209.     return;
  1210.   glutSetWindow(winId[index]);
  1211.   glutPushWindow();
  1212. }
  1213.  
  1214. /* popWindow - Pop a window */
  1215.  
  1216. void
  1217. popWindow(int index)
  1218. {
  1219.   if (winId[index] == 0)
  1220.     return;
  1221.   glutSetWindow(winId[index]);
  1222.   glutPopWindow();
  1223. }
  1224.  
  1225. /* drawScene - Draw callback, triggered by expose events etc.
  1226.    in GLUT. */
  1227.  
  1228. void
  1229. drawScene(void)
  1230. {
  1231.   int winIndex;
  1232.  
  1233.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  1234.  
  1235.   winIndex = idToIndex(glutGetWindow());
  1236.   /* printf("drawScene for index %d, id %d\n", winIndex,
  1237.      glutGetWindow());  */
  1238.  
  1239.   glPushMatrix();
  1240.   glLineWidth(lineWidth);
  1241.   if (backdrop)
  1242.     glCallList(100);
  1243.  
  1244.   /* Left button spinning  */
  1245.  
  1246.   trackBall(APPLY, 0, 0, 0, 0);
  1247.  
  1248.   /* Apply continuous spinning  */
  1249.  
  1250.   glRotatef(angle, 0, 1, 0);
  1251.  
  1252.   glCallList(winIndex + 1);
  1253.   glPopMatrix();
  1254.  
  1255.   if (text[winIndex])
  1256.     showText();
  1257.  
  1258.   glutSwapBuffers();
  1259. }
  1260.  
  1261. /* showText - Render some text in the current GLUT window */
  1262.  
  1263. void
  1264. showText(void)
  1265. {
  1266.   glMatrixMode(GL_PROJECTION);
  1267.   glPushMatrix();
  1268.   glLoadIdentity();
  1269.   gluOrtho2D(0, 100, 0, 100);
  1270.   glMatrixMode(GL_MODELVIEW);
  1271.   glPushMatrix();
  1272.   glLoadIdentity();
  1273.  
  1274.   glColor3f(1.0, 1.0, 1.0);
  1275.   glIndexi(7);
  1276.  
  1277.   glDisable(GL_DEPTH_TEST);
  1278.   glDisable(GL_LIGHTING);
  1279.  
  1280.   glLineWidth(lineWidth);
  1281.  
  1282.   textString(1, 1, "GLUT_BITMAP_8_BY_13", GLUT_BITMAP_8_BY_13);
  1283.   textString(1, 5, "GLUT_BITMAP_9_BY_15", GLUT_BITMAP_9_BY_15);
  1284.   textString(1, 10, "GLUT_BITMAP_TIMES_ROMAN_10", GLUT_BITMAP_TIMES_ROMAN_10);
  1285.   textString(1, 15, "GLUT_BITMAP_TIMES_ROMAN_24", GLUT_BITMAP_TIMES_ROMAN_24);
  1286.  
  1287.   strokeString(1, 25, "GLUT_STROKE_ROMAN", GLUT_STROKE_ROMAN);
  1288.   strokeString(1, 35, "GLUT_STROKE_MONO_ROMAN", GLUT_STROKE_MONO_ROMAN);
  1289.  
  1290.   glEnable(GL_DEPTH_TEST);
  1291.   glEnable(GL_LIGHTING);
  1292.  
  1293.   glMatrixMode(GL_PROJECTION);
  1294.   glPopMatrix();
  1295.   glMatrixMode(GL_MODELVIEW);
  1296.   glPopMatrix();
  1297.  
  1298. }
  1299.  
  1300. /* textString - Bitmap font string */
  1301.  
  1302. void
  1303. textString(int x, int y, char *msg, void *font)
  1304. {
  1305.   glRasterPos2f(x, y);
  1306.   while (*msg) {
  1307.     glutBitmapCharacter(font, *msg);
  1308.     msg++;
  1309.   }
  1310. }
  1311.  
  1312. /* strokeString - Stroke font string */
  1313.  
  1314. void
  1315. strokeString(int x, int y, char *msg, void *font)
  1316. {
  1317.   glPushMatrix();
  1318.   glTranslatef(x, y, 0);
  1319.   glScalef(.04, .04, .04);
  1320.   while (*msg) {
  1321.     glutStrokeCharacter(font, *msg);
  1322.     msg++;
  1323.   }
  1324.   glPopMatrix();
  1325. }
  1326.  
  1327. /* idleFunc - GLUT idle func callback - animates windows */
  1328.  
  1329. void
  1330. idleFunc(void)
  1331. {
  1332.   int i;
  1333.  
  1334.   if (!leftDown && !middleDown)
  1335.     angle += 1;
  1336.     angle = angle % 360;
  1337.  
  1338.   for (i = 0; i < MAXWIN; i++) {
  1339.     if (winId[i] && winVis[i] && !winFreeze[i]) {
  1340.       glutSetWindow(winId[i]);
  1341.       glutPostRedisplay();
  1342.     }
  1343.   }
  1344. }
  1345.  
  1346. /* reshapeFunc - Reshape callback. */
  1347.  
  1348. void
  1349. reshapeFunc(int width, int height)
  1350. {
  1351.   int winId;
  1352.   float aspect;
  1353.  
  1354.   winId = glutGetWindow();
  1355.   PR("reshape callback for window id %d \n", winId);
  1356.  
  1357.   glViewport(0, 0, width, height);
  1358.   aspect = (float) width / height;
  1359.  
  1360.   glMatrixMode(GL_PROJECTION);
  1361.   glLoadIdentity();
  1362.   gluPerspective(40.0, aspect, 1.0, 20.0);
  1363.   glMatrixMode(GL_MODELVIEW);
  1364. }
  1365.  
  1366. /* visible - Visibility callback. Turn off rendering in
  1367.    invisible windows */
  1368.  
  1369. void
  1370. visible(int state)
  1371. {
  1372.   int winId;
  1373.   static GLboolean someVisible = GL_TRUE;
  1374.  
  1375.   winId = glutGetWindow();
  1376.   /* printf("visible: state = %d \n", state);  */
  1377.  
  1378.   if (state == GLUT_VISIBLE) {
  1379.     PR("Window id %d visible \n", winId);
  1380.     winVis[idToIndex(winId)] = GL_TRUE;
  1381.   } else {
  1382.     PR("Window %d not visible \n", winId);
  1383.     winVis[idToIndex(winId)] = GL_FALSE;
  1384.   }
  1385.  
  1386.   if ((winVis[0] == GL_FALSE) && (winVis[1] == GL_FALSE) && (winVis[2] == GL_FALSE)
  1387.     && (winVis[3] == GL_FALSE) && (winVis[6] == GL_FALSE) && (winVis[7] ==
  1388.       GL_FALSE)) {
  1389.     glutIdleFunc(NULL);
  1390.     PR("All windows not visible; idle func disabled\n");
  1391.     someVisible = GL_FALSE;
  1392.   } else {
  1393.     if (!someVisible) {
  1394.       PR("Some windows now visible; idle func enabled\n");
  1395.       someVisible = GL_TRUE;
  1396.       if (animation)
  1397.         glutIdleFunc(idleFunc);
  1398.     }
  1399.   }
  1400. }
  1401.  
  1402. /* keyFunc - Ascii key callback */
  1403.  
  1404. /* ARGSUSED1 */
  1405. void
  1406. keyFunc(unsigned char key, int x, int y)
  1407. {
  1408.   int i, ii;
  1409.  
  1410.   if (debug || showKeys)
  1411.     printf("Ascii key '%c' 0x%02x\n", key, key);
  1412.  
  1413.   switch (key) {
  1414.   case 0x1b:
  1415.     exit(0);
  1416.     break;
  1417.  
  1418.   case 'a':
  1419.     demoMode = !demoMode;
  1420.     if (demoMode)
  1421.       autoDemo(-2);
  1422.     break;
  1423.  
  1424.   case 's':
  1425.     AUTODELAY = AUTODELAY * 0.666;
  1426.     break;
  1427.  
  1428.   case 'S':
  1429.     AUTODELAY = AUTODELAY * 1.5;
  1430.     break;
  1431.  
  1432.   case 'q':
  1433.     killWindow(idToIndex(glutGetWindow()));
  1434.     break;
  1435.  
  1436.   case 'k':
  1437.     showKeys = !showKeys;
  1438.     break;
  1439.  
  1440.   case 'p':
  1441.     demoMode = !demoMode;
  1442.     if (demoMode)
  1443.       autoDemo(-999);
  1444.     break;
  1445.  
  1446.   case 'D':
  1447.     debug = !debug;
  1448.     break;
  1449.  
  1450.   case 'd':
  1451.     dumpIds();
  1452.     break;
  1453.  
  1454.   case 'h':
  1455.     if (winId[5] == 0)
  1456.       makeWindow(5);
  1457.     else
  1458.       killWindow(5);
  1459.     break;
  1460.  
  1461.   case 't':
  1462.     ii = idToIndex(glutGetWindow());
  1463.     text[ii] = !text[ii];
  1464.     break;
  1465.  
  1466.   case 'r':
  1467.     trackBall(RESET, 0, 0, 0, 0);
  1468.     break;
  1469.  
  1470.   case 'l':
  1471.     lineWidth += 1;
  1472.     updateAll();
  1473.     break;
  1474.  
  1475.   case 'L':
  1476.     lineWidth -= 1;
  1477.     if (lineWidth < 1)
  1478.       lineWidth = 1;
  1479.     updateAll();
  1480.     break;
  1481.  
  1482.   case '0':
  1483.   case '1':
  1484.   case '2':
  1485.   case '3':
  1486.   case '4':
  1487.   case '6':
  1488.     i = key - '0';
  1489.     winVis[i] = !winVis[i];
  1490.     break;
  1491.  
  1492.   case ')':
  1493.     makeWindow(0);
  1494.     break;
  1495.  
  1496.   case '!':
  1497.     makeWindow(1);
  1498.     break;
  1499.  
  1500.   case '@':
  1501.     makeWindow(2);
  1502.     break;
  1503.  
  1504.   case '#':
  1505.     makeWindow(3);
  1506.     break;
  1507.  
  1508.   }
  1509. }
  1510.  
  1511. /* specialFunc - Special keys callback (F keys, cursor keys
  1512.    etc. */
  1513.  
  1514. /* ARGSUSED1 */
  1515. void
  1516. specialFunc(int key, int x, int y)
  1517. {
  1518.   if (debug || showKeys)
  1519.     printf("Special key %d\n", key);
  1520.  
  1521.   switch (key) {
  1522.   case GLUT_KEY_PAGE_DOWN:
  1523.     scrollLine += 10;
  1524.     updateHelp();
  1525.     updateText();
  1526.     break;
  1527.  
  1528.   case GLUT_KEY_PAGE_UP:
  1529.     scrollLine -= 10;
  1530.     updateHelp();
  1531.     updateText();
  1532.     break;
  1533.  
  1534.   case GLUT_KEY_DOWN:
  1535.     scrollLine += 1;
  1536.     updateHelp();
  1537.     updateText();
  1538.     break;
  1539.  
  1540.   case GLUT_KEY_UP:
  1541.     scrollLine -= 1;
  1542.     updateHelp();
  1543.     updateText();
  1544.     break;
  1545.  
  1546.   case GLUT_KEY_HOME:
  1547.     scrollLine = 0;
  1548.     updateHelp();
  1549.     updateText();
  1550.     break;
  1551.  
  1552.   case GLUT_KEY_END:
  1553.     scrollLine = 9999;
  1554.     updateHelp();
  1555.     updateText();
  1556.     break;
  1557.  
  1558.   case GLUT_KEY_RIGHT:
  1559.     scrollCol -= 1;
  1560.     updateHelp();
  1561.     updateText();
  1562.     break;
  1563.  
  1564.   case GLUT_KEY_LEFT:
  1565.     scrollCol += 1;
  1566.     updateHelp();
  1567.     updateText();
  1568.     break;
  1569.   }
  1570. }
  1571.  
  1572. /* mouseFunc - Mouse button callback */
  1573.  
  1574. void
  1575. mouseFunc(int button, int state, int x, int y)
  1576. {
  1577.   PR("Mouse button %d, state %d, at pos %d, %d\n", button, state, x, y);
  1578.  
  1579.   trackBall(MOUSEBUTTON, button, state, x, y);
  1580. }
  1581.  
  1582. /* motionFunc - Mouse movement (with a button down) callback */
  1583.  
  1584. void
  1585. motionFunc(int x, int y)
  1586. {
  1587.   PR("Mouse motion at %d, %d\n", x, y);
  1588.  
  1589.   trackBall(MOUSEMOTION, 0, 0, x, y);
  1590.  
  1591.   glutPostRedisplay();
  1592. }
  1593.  
  1594. /* passiveMotionFunc - Mouse movement (with no button down)
  1595.    callback */
  1596.  
  1597. void
  1598. passiveMotionFunc(int x, int y)
  1599. {
  1600.   printf("Mouse motion at %d, %d\n", x, y);
  1601. }
  1602.  
  1603. /* entryFunc - Window entry event callback */
  1604.  
  1605. void
  1606. entryFunc(int state)
  1607. {
  1608.   int winId = glutGetWindow();
  1609.   PR("Entry event: window id %d (index %d), state %d \n", winId, idToIndex(
  1610.       winId), state);
  1611. }
  1612.  
  1613. /* menuStateFunc - Callback to tell us when menus are popped
  1614.    up/down. */
  1615.  
  1616. int menu_state = GLUT_MENU_NOT_IN_USE;
  1617.  
  1618. void
  1619. menuStateFunc(int state)
  1620. {
  1621.   printf("menu stated = %d\n", state);
  1622.   menu_state = state;
  1623.  
  1624.   if (glutGetWindow() == 0) {
  1625.     PR("menuStateFunc: window invalid\n");
  1626.     return;
  1627.   }
  1628.   PR("Menus are%sin use\n", state == GLUT_MENU_IN_USE ? " " : " not ");
  1629.  
  1630.   if ((state == GLUT_MENU_IN_USE) && menuFreeze)
  1631.     glutIdleFunc(NULL);
  1632.   else if (animation)
  1633.     glutIdleFunc(idleFunc);
  1634. }
  1635.  
  1636. /* timerFunc - General test of global timer */
  1637.  
  1638. void
  1639. timerFunc(int value)
  1640. {
  1641.   printf("timer callback: value %d\n", value);
  1642.   if (timerOn) {
  1643.     glutTimerFunc(DELAY, timerFunc, 1);
  1644.   }
  1645. }
  1646.  
  1647. #if 0
  1648. /* delayedReinstateMenuStateCallback - Hack to reinstate
  1649.    MenuStateCallback after a while.  */
  1650.  
  1651. void
  1652. delayedReinstateMenuStateCallback(int state)
  1653. {
  1654.   glutMenuStateFunc(menuStateFunc);
  1655. }
  1656.  
  1657. #endif
  1658.  
  1659. /* setInitDisplayMode - update display modes from display mode
  1660.    menu */
  1661.  
  1662. void
  1663. setInitDisplayMode(void)
  1664. {
  1665.   int i;
  1666.  
  1667.   displayMode = 0;
  1668.  
  1669.   for (i = 0; i < MODES; i++) {
  1670.     if (modes[i]) {
  1671.       /* printf("Requesting %s \n", modeNames[i]);  */
  1672.       displayMode |= glutMode[i];
  1673.     }
  1674.   }
  1675.  
  1676.   glutInitDisplayMode(displayMode);
  1677.  
  1678.   createMenu6();
  1679.   if (!glutGet(GLUT_DISPLAY_MODE_POSSIBLE))
  1680.     warning("This display mode not supported\n");
  1681. }
  1682.  
  1683. /* makeWindow - Create one of the windows */
  1684.  
  1685. void
  1686. makeWindow(int index)
  1687. {
  1688.   char str[99];
  1689.  
  1690.   if (winId[index] != 0) {
  1691.     /* warning("Attempt to create window which is already
  1692.        created");  */
  1693.     return;
  1694.   }
  1695.   switch (index) {
  1696.  
  1697.   case 0:              /* ordinary RGB windows  */
  1698.   case 1:
  1699.   case 2:
  1700.   case 3:
  1701.  
  1702.     setInitDisplayMode();
  1703.     glutInitWindowPosition(pos[index][0], pos[index][1]);
  1704.     glutInitWindowSize(size[index][0], size[index][1]);
  1705.     winId[index] = glutCreateWindow(" ");
  1706.     PR("Window %d id = %d \n", index, winId[index]);
  1707.     gfxInit(index);
  1708.  
  1709.     addCallbacks();
  1710.  
  1711.     sprintf(str, "window %d (RGB)", index);
  1712.     glutSetWindowTitle(str);
  1713.     sprintf(str, "icon %d", index);
  1714.     glutSetIconTitle(str);
  1715.     glutSetMenu(menu1);
  1716.     glutAttachMenu(GLUT_RIGHT_BUTTON);
  1717.     break;
  1718.  
  1719.   case 4:              /* subwindow  */
  1720.  
  1721.     setInitDisplayMode();
  1722.     winId[index] = glutCreateSubWindow(winId[0], pos[index][0], pos[index]
  1723.       [1], size[index][0], size[index][1]);
  1724.     PR("Window %d id = %d \n", index, winId[index]);
  1725.     gfxInit(index);
  1726.     glutDisplayFunc(drawScene);
  1727.     glutVisibilityFunc(visible);
  1728.     glutReshapeFunc(reshapeFunc);
  1729.  
  1730.     break;
  1731.  
  1732.   case 5:              /* help window  */
  1733.   case 8:              /* text window  */
  1734.     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  1735.     glutInitWindowPosition(pos[index][0], pos[index][1]);
  1736.     glutInitWindowSize(size[index][0], size[index][1]);
  1737.     winId[index] = glutCreateWindow(" ");
  1738.     PR("Window %d id = %d \n", index, winId[index]);
  1739.  
  1740.     /* addCallbacks();  */
  1741.     glutKeyboardFunc(keyFunc);
  1742.     glutSpecialFunc(specialFunc);
  1743.  
  1744.     glClearColor(0.15, 0.15, 0.15, 1.0);
  1745.     glColor3f(1, 1, 1);
  1746.     glMatrixMode(GL_PROJECTION);
  1747.     glLoadIdentity();
  1748.     gluOrtho2D(0, 300, 0, 100);
  1749.     glMatrixMode(GL_MODELVIEW);
  1750.     glLoadIdentity();
  1751.  
  1752.     if (index == 5) {
  1753.       glutDisplayFunc(updateHelp);
  1754.       glutSetWindowTitle("help (RGB) win 5");
  1755.       glutSetIconTitle("help");
  1756.     } else {
  1757.       glutDisplayFunc(updateText);
  1758.       glutSetWindowTitle("text (RGB) win 8");
  1759.       glutSetIconTitle("text");
  1760.     }
  1761.     glutSetMenu(menu1);
  1762.     glutAttachMenu(GLUT_RIGHT_BUTTON);
  1763.     break;
  1764.  
  1765.   case 6:              /* color index window  */
  1766.   case 7:              /* color index window  */
  1767.  
  1768.     glutInitDisplayMode(GLUT_DOUBLE | GLUT_INDEX | GLUT_DEPTH);
  1769.     glutInitWindowPosition(pos[index][0], pos[index][1]);
  1770.     glutInitWindowSize(size[index][0], size[index][1]);
  1771.     winId[index] = glutCreateWindow(" ");
  1772.     PR("Window %d id = %d \n", index, winId[index]);
  1773.  
  1774.     gfxInit(index);
  1775.  
  1776.     addCallbacks();
  1777.  
  1778.     sprintf(str, "window %d (color index)", index);
  1779.     glutSetWindowTitle(str);
  1780.     sprintf(str, "icon %d", index);
  1781.     glutSetIconTitle(str);
  1782.     glutSetMenu(menu1);
  1783.     glutAttachMenu(GLUT_RIGHT_BUTTON);
  1784.     break;
  1785.  
  1786.   }
  1787. }
  1788.  
  1789. /* killWindow - Kill one of the main windows */
  1790.  
  1791. void
  1792. killWindow(int index)
  1793. {
  1794.   int i;
  1795.  
  1796.   if (winId[index] == 0) {
  1797.     /* fprintf(stderr, "Attempt to kill invalid window in
  1798.        killWindow\n");  */
  1799.     return;
  1800.   }
  1801.   PR("Killing win %d\n", index);
  1802.   glutSetWindow(winId[index]);
  1803.  
  1804.   /* Disable all callbacks for safety, although
  1805.      glutDestroyWindow  should do this.  */
  1806.  
  1807.   removeCallbacks();
  1808.  
  1809.   glutDestroyWindow(winId[index]);
  1810.   winId[index] = 0;
  1811.   winVis[index] = GL_FALSE;
  1812.  
  1813. #if 0
  1814.   /* If we reinstate the menu state func here, prog breaks.  So
  1815.      reinstate it a little later.  */
  1816.   glutTimerFunc(MENUDELAY, delayedReinstateMenuStateCallback, 1);
  1817. #endif
  1818.  
  1819.   if (index == 5) {     /* help  */
  1820.     scrollLine = 0;
  1821.     scrollCol = 0;
  1822.   }
  1823.   if (index == 8) {     /* text window  */
  1824.     for (i = 0; textPtr[i] != NULL; i++) {
  1825.       free(textPtr[i]); /* free the text strings  */
  1826.       textPtr[i] = NULL;
  1827.     }
  1828.   }
  1829. }
  1830.  
  1831. /* addCallbacks - Add some standard callbacks after creating a
  1832.    window */
  1833.  
  1834. void
  1835. addCallbacks(void)
  1836. {
  1837.   glutDisplayFunc(drawScene);
  1838.   glutVisibilityFunc(visible);
  1839.   glutReshapeFunc(reshapeFunc);
  1840.   glutKeyboardFunc(keyFunc);
  1841.   glutSpecialFunc(specialFunc);
  1842.   glutMouseFunc(mouseFunc);
  1843.   glutMotionFunc(motionFunc);
  1844.   glutEntryFunc(entryFunc);
  1845.  
  1846. /* Callbacks for exotic input devices. Must get my dials &
  1847.    buttons back. */
  1848.  
  1849.   glutSpaceballMotionFunc(spaceballMotionCB);
  1850.   glutSpaceballRotateFunc(spaceballRotateCB);
  1851.   glutSpaceballButtonFunc(spaceballButtonCB);
  1852.  
  1853.   glutButtonBoxFunc(buttonBoxCB);
  1854.   glutDialsFunc(dialsCB);
  1855.  
  1856.   glutTabletMotionFunc(tabletMotionCB);
  1857.   glutTabletButtonFunc(tabletButtonCB);
  1858. }
  1859.  
  1860. /* removeCallbacks - Remove all callbacks before destroying a
  1861.    window. GLUT probably does this  anyway but we'll be safe. */
  1862.  
  1863. void
  1864. removeCallbacks(void)
  1865. {
  1866.   glutVisibilityFunc(NULL);
  1867.   glutReshapeFunc(NULL);
  1868.   glutKeyboardFunc(NULL);
  1869.   glutSpecialFunc(NULL);
  1870.   glutMouseFunc(NULL);
  1871.   glutMotionFunc(NULL);
  1872.   glutEntryFunc(NULL);
  1873. }
  1874.  
  1875. /* updateHelp - Update the help window after user scrolls. */
  1876.  
  1877. void
  1878. updateHelp(void)
  1879. {
  1880.   static char *helpPtr[] =
  1881.   {
  1882.     "(Use PGUP, PGDN, HOME, END, arrows to scroll help text)          ",
  1883.     "                                                                ",
  1884.     "A demo program for GLUT.                                        ",
  1885.     "G Edwards, Aug 95                                               ",
  1886.     "Exercises 99% of GLUT calls                                     ",
  1887.     VERSIONLONG,
  1888.     "                                                                ",
  1889.     "This text uses GLUT_STROKE_MONO_ROMAN font, a built-in vector font.",
  1890.     "(Try resizing the help window).                                 ",
  1891.     "                                                                ",
  1892.     "Keys:                                                           ",
  1893.     " esc   quit                                                     ",
  1894.     " t     toggle text on/off in each window                        ",
  1895.     " h     toggle help                                              ",
  1896.     " q     quit current window                                      ",
  1897.     " a     auto demo                                                ",
  1898.     " p     pause/unpause demo                                       ",
  1899.     " l     increase line width (gfx & stroke text)                  ",
  1900.     " L     decrease line width (gfx & stroke text)                  ",
  1901.     " r     reset transforms                                         ",
  1902.     " k     show keyboard events                                     ",
  1903.     " D     show all events                                          ",
  1904.     "                                                                ",
  1905.     "Mouse:                                                          ",
  1906.     " Left button:    rotate                                         ",
  1907.     " Middle button:  pan                                            ",
  1908.     " Left + middle:  zoom                                           ",
  1909.     NULL};
  1910.  
  1911.   updateScrollWindow(5, helpPtr);
  1912. }
  1913.  
  1914. /* updateText - Update a text window */
  1915.  
  1916. void
  1917. updateText(void)
  1918. {
  1919.   int i;
  1920.  
  1921.   if (textPtr[0] == NULL) {
  1922.     for (i = 0; i < 20; i++) {
  1923.       textPtr[i] = (char *) malloc(50);
  1924.       strcpy(textPtr[i], "no current text");
  1925.     }
  1926.     textPtr[20] = NULL;
  1927.   }
  1928.   updateScrollWindow(8, textPtr);
  1929. }
  1930.  
  1931. /* updateScrollWindow */
  1932.  
  1933. void
  1934. updateScrollWindow(int index, char **ptr)
  1935. {
  1936.   int i, j, lines = 0;
  1937.  
  1938.   if (winId[index] == 0)
  1939.     return;
  1940.  
  1941.   glutSetWindow(winId[index]);
  1942.  
  1943.   for (i = 0; ptr[i] != NULL; i++)
  1944.     lines++;
  1945.  
  1946.   if (scrollLine < 0)
  1947.     scrollLine = 0;
  1948.   if (scrollLine > (lines - 5))
  1949.     scrollLine = lines - 5;
  1950.  
  1951.   glClear(GL_COLOR_BUFFER_BIT);
  1952.  
  1953.   glLineWidth(lineWidth);
  1954.  
  1955.   for (i = scrollLine, j = 1; ptr[i] != NULL; i++, j++)
  1956.     strokeString(scrollCol * 50, 100 - j * 6, ptr[i],
  1957.       GLUT_STROKE_MONO_ROMAN);
  1958.  
  1959.   glutSwapBuffers();
  1960.  
  1961. }
  1962.  
  1963. /* updateAll - Update all visible windows after soem global
  1964.    change, eg. line width */
  1965.  
  1966. void
  1967. updateAll(void)
  1968. {
  1969.   int i;
  1970.  
  1971.   if (winId[5] != 0)
  1972.     updateHelp();
  1973.  
  1974.   if (winId[8] != 0)
  1975.     updateText();
  1976.  
  1977.   for (i = 0; i < MAXWIN; i++)
  1978.     if (winId[i]) {
  1979.       glutSetWindow(winId[i]);
  1980.       glutPostRedisplay();
  1981.     }
  1982. }
  1983.  
  1984. /* idToIndex - Convert GLUT window id to our internal index */
  1985.  
  1986. int
  1987. idToIndex(int id)
  1988. {
  1989.   int i;
  1990.   for (i = 0; i < MAXWIN; i++) {
  1991.     if (winId[i] == id)
  1992.       return i;
  1993.   }
  1994.   fprintf(stderr, "error: id %d not found \n", id);
  1995.   return (-1);
  1996. }
  1997.  
  1998. /* warning - warning messages */
  1999.  
  2000. void
  2001. warning(char *msg)
  2002. {
  2003.   fprintf(stderr, "\007");
  2004.  
  2005.   if (debug) {
  2006.     fprintf(stderr, "%s", msg);
  2007.     if (msg[strlen(msg)] != '\n')
  2008.       fprintf(stderr, "%s", "\n");
  2009.   }
  2010. }
  2011.  
  2012. /* dumpIds - Debug: dump some internal data  */
  2013.  
  2014. void
  2015. dumpIds(void)
  2016. {
  2017.   int i, j;
  2018.  
  2019.   printf("\nInternal data:\n");
  2020.  
  2021.   for (i = 0; i < MAXWIN; i++)
  2022.     printf("Index %d, glut win id %d, visibility %d\n", i, winId[i],
  2023.       winVis[i]);
  2024.  
  2025.   for (i = 0; i < MAXWIN; i++) {
  2026.     if (winId[i])
  2027.       glutSetWindow(winId[i]);
  2028.     else {
  2029.       printf("index %d - no glut window\n", i);
  2030.       continue;
  2031.     }
  2032.  
  2033.     for (j = 1; j <= MAXWIN; j++)
  2034.       printf("Index %d, display list %d %s defined\n", i, j, glIsList(j) ?
  2035.         "is " : "not");
  2036.   }
  2037. }
  2038.  
  2039. /* autoDemo - Run auto demo/test This is a bit tricky. We need
  2040.    to start a timer sequence which progressively orders things
  2041.    to be done. The work really gets done when we return from
  2042.    our callback. Have to think about the event loop / callback
  2043.    design here. */
  2044.  
  2045. void
  2046. autoDemo(int value)
  2047. {
  2048.  
  2049. #define STEP(a, b)  \
  2050.     case a:         \
  2051.         action(a);  \
  2052.     glutTimerFunc(AUTODELAY * b, autoDemo, next(a); \
  2053.     break;
  2054.  
  2055.   static int index = 0;
  2056.   static int count = 0;
  2057.   static int restartValue = -2;
  2058.  
  2059.   if (value == -999)
  2060.     value = restartValue;
  2061.  
  2062.   restartValue = value;
  2063.  
  2064. #define AUTODELAY2 (unsigned int) (AUTODELAY*0.66)
  2065.  
  2066.   /* fprintf(stderr, "autoDemo: value %d \n", value);  */
  2067.  
  2068.   if (!demoMode)
  2069.     return;
  2070.  
  2071.   if (menu_state == GLUT_MENU_IN_USE) {
  2072.     glutTimerFunc(AUTODELAY / 2, autoDemo, value);
  2073.     return;
  2074.   }
  2075.   switch (value) {
  2076.  
  2077. /* Entry point; kill off existing windows. */
  2078.  
  2079.   case -2:
  2080.     killAllWindows();
  2081.     glutTimerFunc(AUTODELAY / 2, autoDemo, 1);
  2082.     break;
  2083.  
  2084. /* Start making windows */
  2085.  
  2086.   case -1:
  2087.     makeWindow(0);
  2088.     glutTimerFunc(AUTODELAY, autoDemo, 0);  /* skip case 0
  2089.                                                first time  */
  2090.     break;
  2091.  
  2092. /* Change shape & backdrop */
  2093.  
  2094.   case 0:
  2095.     currentShape = (currentShape + 1) % 9;
  2096.     redefineShapes(currentShape);
  2097.     count += 1;
  2098.     if (count % 2)
  2099.       backdrop = !backdrop;
  2100.     glutTimerFunc(AUTODELAY, autoDemo, 1);
  2101.     break;
  2102.  
  2103. /* Keep making windows */
  2104.  
  2105.   case 1:
  2106.     makeWindow(1);
  2107.     glutTimerFunc(AUTODELAY, autoDemo, 2);
  2108.     break;
  2109.  
  2110.   case 2:
  2111.     makeWindow(2);
  2112.     glutTimerFunc(AUTODELAY, autoDemo, 3);
  2113.     break;
  2114.  
  2115.   case 3:
  2116.     makeWindow(3);
  2117.     glutTimerFunc(AUTODELAY, autoDemo, 4);
  2118.     break;
  2119.  
  2120.   case 4:
  2121.     makeWindow(4);
  2122.     glutTimerFunc(AUTODELAY, autoDemo, 5);
  2123.     break;
  2124.  
  2125.   case 5:
  2126.     makeWindow(5);
  2127.     glutTimerFunc(AUTODELAY * 2, autoDemo, 51);
  2128.     break;
  2129.  
  2130.   case 51:
  2131.     makeWindow(6);
  2132.     glutTimerFunc(AUTODELAY * 2, autoDemo, 52);
  2133.     break;
  2134.  
  2135.   case 52:
  2136.     makeWindow(7);
  2137.     glutTimerFunc(AUTODELAY * 2, autoDemo, 53);
  2138.     break;
  2139.  
  2140. /* Kill last 3 windows, leave 4 up. */
  2141.  
  2142.   case 53:
  2143.     killWindow(7);
  2144.     glutTimerFunc(AUTODELAY, autoDemo, 54);
  2145.     break;
  2146.  
  2147.   case 54:
  2148.     killWindow(6);
  2149.     glutTimerFunc(AUTODELAY, autoDemo, 6);
  2150.     break;
  2151.  
  2152.   case 6:
  2153.     killWindow(5);
  2154.     glutTimerFunc(AUTODELAY, autoDemo, 7);
  2155.     break;
  2156.  
  2157.   case 7:
  2158.     killWindow(4);
  2159.     glutTimerFunc(AUTODELAY, autoDemo, 700);
  2160.     break;
  2161.  
  2162. /* Change shape again */
  2163.  
  2164.   case 700:
  2165.     currentShape = (currentShape + 1) % 9;
  2166.     redefineShapes(currentShape);
  2167.     glutTimerFunc(AUTODELAY, autoDemo, 701);
  2168.     break;
  2169.  
  2170. /* Cycle 4 main windows through various window ops.  */
  2171.  
  2172.   case 701:
  2173.     positionWindow(index);
  2174.     index = (index + 1) % 4;
  2175.     glutTimerFunc(AUTODELAY2, autoDemo, index > 0 ? 701 : 702);
  2176.     break;
  2177.  
  2178.   case 702:
  2179.     reshapeWindow(index);
  2180.     index = (index + 1) % 4;
  2181.     glutTimerFunc(AUTODELAY2, autoDemo, index > 0 ? 702 : 703);
  2182.     break;
  2183.  
  2184.   case 703:
  2185.     iconifyWindow(index);
  2186.     index = (index + 1) % 4;
  2187.     glutTimerFunc(AUTODELAY2, autoDemo, index > 0 ? 703 : 704);
  2188.     break;
  2189.  
  2190.   case 704:
  2191.     showWindow(index);
  2192.     index = (index + 1) % 4;
  2193.     glutTimerFunc(AUTODELAY2, autoDemo, index > 0 ? 704 : 705);
  2194.     break;
  2195.  
  2196.   case 705:
  2197.     hideWindow(index);
  2198.     index = (index + 1) % 4;
  2199.     glutTimerFunc(AUTODELAY2, autoDemo, index > 0 ? 705 : 706);
  2200.     break;
  2201.  
  2202.   case 706:
  2203.     showWindow(index);
  2204.     index = (index + 1) % 4;
  2205.     glutTimerFunc(AUTODELAY2, autoDemo, index > 0 ? 706 : 707);
  2206.     break;
  2207.  
  2208.   case 707:
  2209.     pushWindow(index);
  2210.     index = (index + 1) % 4;
  2211.     glutTimerFunc(AUTODELAY2, autoDemo, index > 0 ? 707 : 708);
  2212.     break;
  2213.  
  2214.   case 708:
  2215.     popWindow(index);
  2216.     index = (index + 1) % 4;
  2217.     glutTimerFunc(AUTODELAY2, autoDemo, index > 0 ? 708 : 8);
  2218.     break;
  2219.  
  2220. /* Kill all windows */
  2221.  
  2222.   case 8:
  2223.     killWindow(3);
  2224.     glutTimerFunc(AUTODELAY, autoDemo, 9);
  2225.     break;
  2226.  
  2227.   case 9:
  2228.     killWindow(2);
  2229.     glutTimerFunc(AUTODELAY, autoDemo, 10);
  2230.     break;
  2231.  
  2232.   case 10:
  2233.     killWindow(1);
  2234.     glutTimerFunc(AUTODELAY, autoDemo, 11);
  2235.     break;
  2236.  
  2237.   case 11:
  2238.     killWindow(0);
  2239.     glutTimerFunc(AUTODELAY, autoDemo, -1);  /* back to start  */
  2240.     break;
  2241.   }
  2242.  
  2243. }
  2244.  
  2245. /* attachMenus - Attach/detach menus to/from mouse buttons */
  2246.  
  2247. void
  2248. attachMenus(void)
  2249. {
  2250.   int i, b;
  2251.   int button[3] =
  2252.   {GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON, GLUT_RIGHT_BUTTON};
  2253.  
  2254.   for (i = 0; i < MAXWIN; i++) {
  2255.     if (winId[i] != 0) {
  2256.       for (b = 0; b < 3; b++) {
  2257.         glutSetWindow(winId[i]);
  2258.         glutSetMenu(menu1);
  2259.         if (menuButton[b])
  2260.           glutAttachMenu(button[b]);
  2261.         else
  2262.           glutDetachMenu(button[b]);
  2263.       }
  2264.     }
  2265.   }
  2266. }
  2267.  
  2268. /* killAllWindows - Kill all windows (except 0) */
  2269.  
  2270. void
  2271. killAllWindows(void)
  2272. {
  2273.   int w;
  2274.  
  2275.   for (w = 1; w < MAXWIN; w++)
  2276.     if (winId[w])
  2277.       killWindow(w);
  2278. }
  2279.  
  2280. /* makeAllWindows - Make all windows */
  2281.  
  2282. void
  2283. makeAllWindows(void)
  2284. {
  2285.   int w;
  2286.  
  2287.   for (w = 0; w < MAXWIN; w++)
  2288.     if (!winId[w])
  2289.       makeWindow(w);
  2290. }
  2291.  
  2292. /* checkArgs - Check command line args */
  2293.  
  2294. void
  2295. checkArgs(int argc, char *argv[])
  2296. {
  2297.   int argp;
  2298.   GLboolean quit = GL_FALSE;
  2299.   GLboolean error = GL_FALSE;
  2300.  
  2301. #define AA argv[argp]
  2302.  
  2303. #if 0
  2304. #define NEXT argp++;      \
  2305.         if(argp >= argc) \
  2306.         {                \
  2307.            Usage();      \
  2308.            Exit(1);      \
  2309.         }
  2310. #endif
  2311.  
  2312.   argp = 1;
  2313.   while (argp < argc) {
  2314.     if (match(AA, "-help")) {
  2315.       commandLineHelp();
  2316.       quit = GL_TRUE;
  2317.     } else if (match(AA, "-version")) {
  2318.       printf(VERSIONLONG "\n");
  2319.       quit = GL_TRUE;
  2320.     } else if (match(AA, "-auto")) {
  2321.       demoMode = GL_TRUE;
  2322.     } else if (match(AA, "-scale")) {
  2323.       argp++;
  2324.       scaleFactor = atof(argv[argp]);
  2325.     } else {
  2326.       fprintf(stderr, "Unknown arg: %s\n", AA);
  2327.       error = GL_TRUE;
  2328.       quit = GL_TRUE;
  2329.     }
  2330.     argp++;
  2331.   }
  2332.  
  2333.   if (error) {
  2334.     commandLineHelp();
  2335.     exit(1);
  2336.   }
  2337.   if (quit)
  2338.     exit(0);
  2339. }
  2340.  
  2341. /* commandLineHelp - Command line help */
  2342.  
  2343. void
  2344. commandLineHelp(void)
  2345. {
  2346.   printf("Usage:\n");
  2347.   printf(" -h[elp]            this stuff\n");
  2348.   printf(" -v[ersion]         show version\n");
  2349.   printf(" -a[uto]            start in auto demo mode\n");
  2350.   printf(" -s[cale] f         scale windows by f\n");
  2351.   printf("Standard GLUT args:\n");
  2352.   printf(" -iconic            start iconic\n");
  2353.   printf(" -display DISP      use display DISP\n");
  2354.   printf(" -direct            use direct rendering (default)\n");
  2355.   printf(" -indirect          use indirect rendering\n");
  2356.   printf(" -sync              use synchronous X protocol\n");
  2357.   printf(" -gldebug           check OpenGL errors\n");
  2358.   printf(" -geometry WxH+X+Y  standard X window spec (overridden here) \n");
  2359. }
  2360.  
  2361. /* match - Match a string (any unique substring). */
  2362.  
  2363. GLboolean
  2364. match(char *arg, char *t)
  2365. {
  2366.   if (strstr(t, arg))
  2367.     return GL_TRUE;
  2368.   else
  2369.     return GL_FALSE;
  2370. }
  2371.  
  2372. /* scaleWindows - Scale initial window sizes ansd positions */
  2373.  
  2374. void
  2375. scaleWindows(float scale)
  2376. {
  2377.   int i;
  2378.  
  2379.   for (i = 0; i < MAXWIN; i++) {
  2380.     pos[i][0] = pos[i][0] * scale;
  2381.     pos[i][1] = pos[i][1] * scale;
  2382.     size[i][0] = size[i][0] * scale;
  2383.     size[i][1] = size[i][1] * scale;
  2384.   }
  2385. }
  2386.  
  2387. /* trackBall - A simple trackball (not with proper rotations). */
  2388.  
  2389. /** A simple trackball with spin = left button
  2390.                            pan  = middle button
  2391.                            zoom = left + middle
  2392.    Doesn't have proper trackball rotation, ie axes which remain fixed in
  2393.    the scene. We should use the trackball code from 4Dgifts. */
  2394.  
  2395. #define STARTROTATE(x, y)     \
  2396. {                             \
  2397.     startMX = x;              \
  2398.     startMY = y;              \
  2399. }
  2400.  
  2401. #define STOPROTATE(x, y)      \
  2402. {                             \
  2403.     steadyXangle = varXangle; \
  2404.     steadyYangle = varYangle; \
  2405. }
  2406.  
  2407. #define STARTPAN(x, y)        \
  2408. {                             \
  2409.     startMX = x;              \
  2410.     startMY = y;              \
  2411. }
  2412.  
  2413. #define STOPPAN(x, y)         \
  2414. {                             \
  2415.     steadyX = varX;           \
  2416.     steadyY = varY;           \
  2417. }
  2418.  
  2419. #define STARTZOOM(x, y)       \
  2420. {                             \
  2421.     startMX = x;              \
  2422.     startMY = y;              \
  2423. }
  2424.  
  2425. #define STOPZOOM(x, y)        \
  2426. {                             \
  2427.     steadyZ = varZ;           \
  2428. }
  2429.  
  2430. static float
  2431. fixAngle(float angle)
  2432. {
  2433.   return angle - floor(angle / 360.0) * 360.0;
  2434. }
  2435.  
  2436. void
  2437. trackBall(int mode, int button, int state, int x, int y)
  2438. {
  2439.   static int startMX = 0, startMY = 0;  /* initial mouse pos  */
  2440.   static int deltaMX = 0, deltaMY = 0;  /* initial mouse pos  */
  2441.   static float steadyXangle = 0.0, steadyYangle = 0.0;
  2442.   static float varXangle = 0.0, varYangle = 0.0;
  2443.   static float steadyX = 0.0, steadyY = 0.0, steadyZ = 0.0;
  2444.   static float varX = 0.0, varY = 0.0, varZ = 0.0;
  2445.  
  2446.   switch (mode) {
  2447.  
  2448.   case RESET:
  2449.     steadyXangle = steadyYangle = steadyX = steadyY = steadyZ = 0.0;
  2450.     break;
  2451.  
  2452.   case MOUSEBUTTON:
  2453.  
  2454.     if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN && !middleDown) {
  2455.       STARTROTATE(x, y);
  2456.       leftDown = GL_TRUE;
  2457.     } else if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN &&
  2458.       middleDown) {
  2459.       STOPPAN(x, y);
  2460.       STARTZOOM(x, y);
  2461.       leftDown = GL_TRUE;
  2462.     } else if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN &&
  2463.       !leftDown) {
  2464.       STARTPAN(x, y);
  2465.       middleDown = GL_TRUE;
  2466.     } else if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN &&
  2467.       leftDown) {
  2468.       STOPROTATE(x, y);
  2469.       STARTZOOM(x, y);
  2470.       middleDown = GL_TRUE;
  2471.     } else if (state == GLUT_UP && button == GLUT_LEFT_BUTTON && !middleDown) {
  2472.       STOPROTATE(x, y);
  2473.       leftDown = GL_FALSE;
  2474.     } else if (state == GLUT_UP && button == GLUT_LEFT_BUTTON && middleDown) {
  2475.       STOPZOOM(x, y);
  2476.       STARTROTATE(x, y);
  2477.       leftDown = GL_FALSE;
  2478.     } else if (state == GLUT_UP && button == GLUT_MIDDLE_BUTTON && !leftDown) {
  2479.       STOPPAN(x, y);
  2480.       middleDown = GL_FALSE;
  2481.     } else if (state == GLUT_UP && button == GLUT_MIDDLE_BUTTON && leftDown) {
  2482.       STOPZOOM(x, y);
  2483.       STARTROTATE(x, y);
  2484.       middleDown = GL_FALSE;
  2485.     }
  2486.     break;
  2487.  
  2488.   case APPLY:
  2489.  
  2490.     if (leftDown && !middleDown) {
  2491.       glTranslatef(steadyX, steadyY, steadyZ);
  2492.       glRotatef(varXangle, 0, 1, 0);
  2493.       glRotatef(varYangle, 1, 0, 0);
  2494.     }
  2495.     /* Middle button pan  */
  2496.  
  2497.     else if (middleDown && !leftDown) {
  2498.       glTranslatef(varX, varY, steadyZ);
  2499.       glRotatef(steadyXangle, 0, 1, 0);
  2500.       glRotatef(steadyYangle, 1, 0, 0);
  2501.     }
  2502.     /* Left + middle zoom.  */
  2503.  
  2504.     else if (leftDown && middleDown) {
  2505.       glTranslatef(steadyX, steadyY, varZ);
  2506.       glRotatef(steadyXangle, 0, 1, 0);
  2507.       glRotatef(steadyYangle, 1, 0, 0);
  2508.     }
  2509.     /* Nothing down.  */
  2510.  
  2511.     else {
  2512.       glTranslatef(steadyX, steadyY, steadyZ);
  2513.       glRotatef(steadyXangle, 0, 1, 0);
  2514.       glRotatef(steadyYangle, 1, 0, 0);
  2515.     }
  2516.     break;
  2517.  
  2518.   case MOUSEMOTION:
  2519.  
  2520.     deltaMX = x - startMX;
  2521.     deltaMY = startMY - y;
  2522.  
  2523.     if (leftDown && !middleDown) {
  2524.       varXangle = fixAngle(steadyXangle + deltaMX);
  2525.       varYangle = fixAngle(steadyYangle + deltaMY);
  2526.     } else if (middleDown && !leftDown) {
  2527.       varX = steadyX + deltaMX / 100.0;
  2528.       varY = steadyY + deltaMY / 100.0;
  2529.     } else if (leftDown && middleDown) {
  2530.       varZ = steadyZ - deltaMY / 50.0;
  2531.     }
  2532.     break;
  2533.   }
  2534.  
  2535. }
  2536.  
  2537. /* Callbacks for exotic input devices. These have not been
  2538.    tested yet owing to the usual complete absence of such
  2539.    devices in the UK support group. */
  2540.  
  2541. /* spaceballMotionCB */
  2542.  
  2543. void
  2544. spaceballMotionCB(int x, int y, int z)
  2545. {
  2546.   printf("spaceballMotionCB: translations are X %d, Y %d, Z %d\n", x, y, z);
  2547. }
  2548.  
  2549. /* spaceballRotateCB */
  2550.  
  2551. void
  2552. spaceballRotateCB(int x, int y, int z)
  2553. {
  2554.   printf("spaceballRotateCB: rotations are X %d, Y %d, Z %d\n", x, y, z);
  2555. }
  2556.  
  2557. /* spaceballButtonCB */
  2558.  
  2559. void
  2560. spaceballButtonCB(int button, int state)
  2561. {
  2562.   printf("spaceballButtonCB: button %d, state %d\n", button, state);
  2563. }
  2564.  
  2565. /* buttonBoxCB */
  2566.  
  2567. void
  2568. buttonBoxCB(int button, int state)
  2569. {
  2570.   printf("buttonBoxCB: button %d, state %d\n", button, state);
  2571. }
  2572.  
  2573. /* dialsCB */
  2574.  
  2575. void
  2576. dialsCB(int dial, int value)
  2577. {
  2578.   printf("dialsCB: dial %d, value %d\n", dial, value);
  2579. }
  2580.  
  2581. /* tabletMotionCB */
  2582.  
  2583. void
  2584. tabletMotionCB(int x, int y)
  2585. {
  2586.   printf("tabletMotionCB: X %d, Y %d\n", x, y);
  2587. }
  2588.  
  2589. /* tabletButtonCB */
  2590.  
  2591. /* ARGSUSED2 */
  2592. void
  2593. tabletButtonCB(int button, int state, int dummy1, int dummy2)
  2594. {
  2595.   printf("tabletButtonCB: button %d, state %d\n", button, state);
  2596. }
  2597.