home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / IRIT / POLY3DS.ZIP / XGRPHGEN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-07  |  35.8 KB  |  1,051 lines

  1. /*****************************************************************************
  2. *   General routines to    handle the graphic calls.                 *
  3. * currently supported devices:                             *
  4. * Input: Keyboard, mouse.                             *
  5. * Output: X11 device.                                 *
  6. *                                         *
  7. * Written by:  Gershon Elber                Ver 0.1, Mar 1990.   *
  8. *****************************************************************************/
  9.  
  10. #ifndef __MSDOS__
  11.  
  12. #define FONT_NAME        "8x13"
  13. #define PROGRAM_NAME        "poly3d"
  14. #define DEFAULT_TRANS_WIDTH    200
  15. #define DEFAULT_TRANS_HEIGHT    500
  16. #define DEFAULT_VIEW_WIDTH    400
  17. #define DEFAULT_VIEW_HEIGHT    400
  18.  
  19. #include <X11/Xlib.h>
  20. #include <X11/Xutil.h>
  21. #include <X11/cursorfont.h>
  22.  
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <math.h>
  26. #include <ctype.h>
  27. #include "program.h"
  28. #include "xgraphic.h"
  29. #include "graphgng.h"
  30. #include "graphgnl.h"
  31. #include "viewobjg.h"
  32.  
  33. /* X global specific staff goes here: */
  34. static Display *XDisplay;
  35. static int XScreen;
  36. static Window XRoot;
  37. static Colormap XColorMap;
  38. static GC XTransGraphContext;
  39. static GC XViewGraphContext;
  40. static Visual *XVisual;
  41. static XImage *XImageBuffer;
  42. static Pixmap XIcon;
  43. static Cursor XCursor;
  44. static XColor BlackColor;
  45. static XFontStruct *XLoadedFont;
  46. static XColor
  47.     *TransCursorColor = NULL,
  48.     *ViewCursorColor = NULL;
  49. static unsigned long
  50.     TransBackGroundPixel,
  51.     TransBorderPixel,
  52.     TransTextPixel,
  53.     TransSubWinBackPixel,
  54.     TransSubWinBorderPixel,
  55.     ViewBackGroundPixel,
  56.     ViewBorderPixel,
  57.     ViewTextPixel;
  58. static int
  59.     XFontYOffsetToCenter = 0,
  60.     AbortKeyPressed = FALSE,
  61.     TransBorderWidth = 1,
  62.     TransSubWinBorderWidth = 1,
  63.     TransHasSize = FALSE,
  64.     TransHasPos = FALSE,
  65.     TransPosX = 0,
  66.     TransPosY = 0,
  67.     TransWidth = DEFAULT_TRANS_WIDTH,
  68.     TransHeight = DEFAULT_TRANS_HEIGHT,
  69.     ViewBorderWidth = 1,
  70.     ViewHasSize = FALSE,
  71.     ViewHasPos = FALSE,
  72.     ViewPosX = 0,
  73.     ViewPosY = 0,
  74.     ViewWidth = DEFAULT_VIEW_WIDTH,
  75.     ViewHeight = DEFAULT_VIEW_HEIGHT,
  76.     CurrentXPosition = 0,
  77.     CurrentYPosition = 0,
  78.     InGraphicMode = FALSE;
  79.  
  80.  
  81. /* X Colors to be used for viewed object (see also xgraphic.h): */
  82. int XViewColorDefs[MAX_COLOR + 1][3] =
  83. {
  84.     {     0,     0,     0 },  /* 0. BLACK */
  85.     {     0,     0, 43350 },  /* 1. BLUE */
  86.     {     0, 43350,     0 },  /* 2. GREEN */
  87.     {     0, 43350, 43350 },  /* 3. CYAN */
  88.     { 43350,     0,     0 },  /* 4. RED */
  89.     { 43350,     0, 43350 },  /* 5. MAGENTA */
  90.     { 43350, 43350,     0 },  /* 6. BROWN */
  91.     { 43350, 43350, 43350 },  /* 7. LIGHTGREY */
  92.     { 21675, 21675, 21675 },  /* 8. DARKGRAY */
  93.     { 21675, 21675, 65535 },  /* 9. LIGHTBLUE */
  94.     { 21675, 65535, 21675 },  /* 10. LIGHTGREEN */
  95.     { 21675, 65535, 65535 },  /* 11. LIGHTCYAN */
  96.     { 65535, 21675, 21675 },  /* 12. LIGHTRED */
  97.     { 65535, 21675, 65535 },  /* 13. LIGHTMAGENTA */
  98.     { 65535, 65535, 21675 },  /* 14. YELLOW */
  99.     { 65535, 65535, 65535 }   /* 15. WHITE */
  100. };
  101. XColor XViewColors[MAX_COLOR + 1];
  102.  
  103. /* X Viewing window staff goes here: */
  104. static Window ViewWndw;
  105.  
  106. /* X transformation window staff goes here: */
  107. static Window ObjScrTglWndw;
  108. static Window PersOrthoTglWndw, PersOrthoZWndw;
  109. static Window TransformWndw;
  110. static Window RotateXWndw, RotateYWndw, RotateZWndw;
  111. static Window TranslateXWndw, TranslateYWndw, TranslateZWndw;
  112. static Window ScaleWndw;
  113. static Window DepthCueWndw;
  114. static Window SavePSWndw;
  115. static Window SaveMatrixWndw;
  116. static Window ResetMatrixWndw;
  117. static Window QuitWndw;
  118.  
  119. /* Viewing state variables: */
  120. static int
  121.     ObjectSpaceState = FALSE,
  122.     PerspectiveState = FALSE,
  123.     DepthCueState = FALSE,
  124.     SubWindowWidthState2 = 1,
  125.     SubWindowHeightState2 = 1;
  126.  
  127. static int GGMapX(RealType x);
  128. static int GGMapY(RealType y);
  129. static void ReadXDefaults(void);
  130. static void SetTransformWindow(int argc, char **argv);
  131. static void RedrawTransformWindow(void);
  132. static Window SetTransformSubWindow(int SubTransPosX, int SubTransPosY,
  133.                     int SubTransWidth, int SubTransHeight);
  134. static void RedrawTransformSubWindow(Window Win,
  135.     int SubTransPosX, int SubTransPosY, int SubTransWidth, int SubTransHeight,
  136.     int DrawMiddleVertLine, char *DrawString);
  137. static void SetViewWindow(int argc, char **argv);
  138. static void DrawText(Window Win, char *Str, int PosX, int PosY,
  139.              unsigned long Color);
  140.  
  141. /****************************************************************************
  142. * Routine to map real -1..1 normalized coordinates to screen X size.        *
  143. ****************************************************************************/
  144. static int GGMapX(RealType x)
  145. {
  146.     return ((int) ((x + 1.0) * ViewWidth)) / 2;
  147. }
  148.  
  149. /****************************************************************************
  150. * Routine to map real -1..1 normalized coordinates to screen Y size.        *
  151. ****************************************************************************/
  152. static int GGMapY(RealType y)
  153. {
  154.     return ((int) ((1.0 - y) * ViewHeight)) / 2;
  155. }
  156.  
  157. /****************************************************************************
  158. * Routine to move to a normalized point    between    -1..1 on both axes :        *
  159. ****************************************************************************/
  160. void GGMyMove(RealType x, RealType y)
  161. {
  162.     CurrentXPosition = GGMapX(x);
  163.     CurrentYPosition = GGMapY(y);
  164. }
  165.  
  166. /****************************************************************************
  167. * Routine to draw to a normalized point    between    -1..1 on both axes :        *
  168. ****************************************************************************/
  169. void GGMyDraw(RealType x, RealType y)
  170. {
  171.     int NewX, NewY;
  172.  
  173.     XDrawLine(XDisplay, ViewWndw, XViewGraphContext,
  174.           CurrentXPosition, CurrentYPosition,
  175.           NewX = GGMapX(x), NewY = GGMapY(y));
  176.  
  177.     CurrentXPosition = NewX;
  178.     CurrentYPosition = NewY;
  179. }
  180.  
  181. /****************************************************************************
  182. * Routine to set line style.                            *
  183. ****************************************************************************/
  184. void GGMySetLineStyle(int Style)
  185. {
  186.     switch (Style) {
  187.     case FULL_LINE_STYLE:
  188.         XSetLineAttributes(XDisplay, XViewGraphContext,
  189.                    0, LineSolid, CapRound, JoinRound);
  190.         break;
  191.     case DOTTED_LINE_STYLE:
  192.         XSetLineAttributes(XDisplay, XViewGraphContext,
  193.                    0, LineOnOffDash, CapRound, JoinRound);
  194.         break;
  195.     }
  196. }
  197.  
  198. /****************************************************************************
  199. * Routine to draw to a normelized point    between    -1..1 on both axes :        *
  200. ****************************************************************************/
  201. void GGMySetColor(int color)
  202. {
  203.     XGCValues values;
  204.  
  205.     if (color > MAX_COLOR) color = WHITE;
  206.  
  207.     values.foreground = XViewColors[color].pixel;
  208.     XChangeGC(XDisplay, XViewGraphContext, GCForeground, &values);
  209. }
  210.  
  211. /****************************************************************************
  212. * Routine to reset all the system to starting condition    :            *
  213. ****************************************************************************/
  214. void GGInitGraph(int argc, char **argv)
  215. {
  216.     int i;
  217.     XGCValues values;
  218.  
  219.     /* Lets see if we can get access to the X server before we even start: */
  220.     if ((XDisplay = (Display *) XOpenDisplay(NULL)) == NULL) {
  221.     fprintf(stderr, "Failed to access X server, abored.\n");
  222.         MyExit(-1);
  223.     }
  224.     if ((XLoadedFont = XLoadQueryFont(XDisplay, FONT_NAME)) == NULL) {
  225.     fprintf(stderr, "Failed to load required X font \"%s\", aborted.\n",
  226.         FONT_NAME);
  227.     MyExit(-1);
  228.     }
  229.     XFontYOffsetToCenter = (XLoadedFont -> ascent - XLoadedFont -> descent + 1)
  230.                                     / 2;
  231.  
  232.     XScreen = DefaultScreen(XDisplay);
  233.     XRoot = RootWindow(XDisplay, XScreen);
  234.     XColorMap = DefaultColormap(XDisplay, XScreen);
  235.     XVisual = DefaultVisual(XDisplay, XScreen);
  236.     values.foreground = WhitePixel(XDisplay, XScreen);
  237.     values.background = BlackPixel(XDisplay, XScreen);
  238.     values.font = XLoadedFont -> fid;
  239.     XTransGraphContext = XCreateGC(XDisplay, XRoot,
  240.                   GCForeground | GCBackground | GCFont, &values);
  241.     XViewGraphContext = XCreateGC(XDisplay, XRoot,
  242.                   GCForeground | GCBackground, &values);
  243.     
  244.     ReadXDefaults();
  245.  
  246.     for (i=0; i<=MAX_COLOR; i++) {
  247.     XViewColors[i].red   = XViewColorDefs[i][0];
  248.     XViewColors[i].green = XViewColorDefs[i][1];
  249.     XViewColors[i].blue  = XViewColorDefs[i][2];
  250.  
  251.     /* If fails to allocate the color - take WHITE instead. */
  252.     if (!XAllocColor(XDisplay, XColorMap, &XViewColors[i]))
  253.         XViewColors[i].pixel = WhitePixel(XDisplay, XScreen);
  254.     }
  255.  
  256.     SetTransformWindow(argc, argv);
  257.     SetViewWindow(argc, argv);
  258.  
  259.     GraphicFlush();
  260.  
  261.     InGraphicMode = TRUE;
  262. }
  263.  
  264. /****************************************************************************
  265. * Routine to close and shutdown    graphic    mode :                    *
  266. ****************************************************************************/
  267. void GGCloseGraph(void)
  268. {
  269.     if (!InGraphicMode) return;
  270.  
  271.     XFreeGC(XDisplay, XViewGraphContext);
  272.     XFreeGC(XDisplay, XTransGraphContext);
  273.     XUnloadFont(XDisplay, XLoadedFont -> fid);
  274.     XCloseDisplay(XDisplay);
  275.  
  276.     InGraphicMode = FALSE;
  277. }
  278.  
  279. /****************************************************************************
  280. * Routine to draw a point on screen as marker +    with a title :            *
  281. ****************************************************************************/
  282. void GGDrawPoint(RealType p[], char title[], int PointColor)
  283. {
  284.     GGMySetColor(PointColor);
  285.     GGMyMove(p[1] + POINT_SIZE, p[2]);
  286.     GGMyDraw(p[1] - POINT_SIZE, p[2]);
  287.     GGMyMove(p[1], p[2] + POINT_SIZE);
  288.     GGMyDraw(p[1], p[2] - POINT_SIZE);
  289.  
  290.     GGXYPutStr(p[1] + POINT_TITLE, p[2] + POINT_TITLE, title);
  291. }
  292.  
  293. /*****************************************************************************
  294. * Routine to print an message on the given location:                 *
  295. *****************************************************************************/
  296. void GGXYPutStr(RealType x, RealType y, char *s)
  297. {
  298.     int Len = strlen(s),
  299.         Width = XTextWidth(XLoadedFont, s, Len),
  300.         PosX = GGMapX(x),
  301.         PosY = GGMapY(y);
  302.     XGCValues values;
  303.  
  304.     XDrawString(XDisplay, ViewWndw, XViewGraphContext, PosX - Width / 2,
  305.         PosY + XFontYOffsetToCenter, s, Len);
  306. }
  307.  
  308. /*****************************************************************************
  309. *   Routine to clear given window area.                         *
  310. * Note the viewport on exit is the window only!                     *
  311. *****************************************************************************/
  312. void GGClearWindow(RealType XMin, RealType YMin,
  313.            RealType XMax, RealType YMax, int WindowName)
  314. {
  315.     XClearWindow(XDisplay, ViewWndw);
  316. }
  317.  
  318. /*****************************************************************************
  319. *   Routine to clear all the screen.                         *
  320. *****************************************************************************/
  321. void GGClearAllScreen(void)
  322. {
  323.     XClearWindow(XDisplay, ViewWndw);
  324. }
  325.  
  326. /*****************************************************************************
  327. * Routine to make some sound with given Frequency, Time milliseconds:         *
  328. *****************************************************************************/
  329. void GGTone(int Frequency, int Duration)
  330. {
  331.     XBell(XDisplay, 0);
  332. }
  333.  
  334. /*****************************************************************************
  335. * Read Defaults from X data base.                         *
  336. *****************************************************************************/
  337. static void ReadXDefaults(void)
  338. {
  339.     int i;
  340.     XColor Color;
  341.     char *TransBackGroundColor = XGetDefault(XDisplay, PROGRAM_NAME,
  342.                                        "Trans.BackGround"),
  343.          *TransBorderColor = XGetDefault(XDisplay, PROGRAM_NAME,
  344.                               "Trans.BorderColor"),
  345.          *TransBorderWidthStr = XGetDefault(XDisplay, PROGRAM_NAME,
  346.                               "Trans.BorderWidth"),
  347.          *TransTextColor = XGetDefault(XDisplay, PROGRAM_NAME,
  348.                                 "Trans.TextColor"),
  349.          *TransSubWinBackColor = XGetDefault(XDisplay, PROGRAM_NAME,
  350.                             "Trans.SubWin.BackGround"),
  351.          *TransSubWinBorderColor = XGetDefault(XDisplay, PROGRAM_NAME,
  352.                            "Trans.SubWin.BorderColor"),
  353.          *TransSubWinBorderWidthStr = XGetDefault(XDisplay, PROGRAM_NAME,
  354.                            "Trans.SubWin.BorderWidth"),
  355.          *TransGeometry = XGetDefault(XDisplay, PROGRAM_NAME,
  356.                                  "Trans.Geometry"),
  357.          *TransCursorColorStr = XGetDefault(XDisplay, PROGRAM_NAME,
  358.                               "Trans.CursorColor"),
  359.          *ViewBackGroundColor = XGetDefault(XDisplay, PROGRAM_NAME,
  360.                                 "View.BackGround"),
  361.          *ViewTextColor = XGetDefault(XDisplay, PROGRAM_NAME,
  362.                                 "View.TextColor"),
  363.          *ViewBorderColor = XGetDefault(XDisplay, PROGRAM_NAME,
  364.                                "View.BorderColor"),
  365.          *ViewBorderWidthStr = XGetDefault(XDisplay, PROGRAM_NAME,
  366.                                "View.BorderWidth"),
  367.          *ViewGeometry = XGetDefault(XDisplay, PROGRAM_NAME,
  368.                                   "View.Geometry"),
  369.          *ViewCursorColorStr = XGetDefault(XDisplay, PROGRAM_NAME,
  370.                                "View.CursorColor");
  371.  
  372.     if (XParseColor(XDisplay, XColorMap, "Black", &BlackColor))
  373.     XAllocColor(XDisplay, XColorMap, &BlackColor);
  374.  
  375.     if (TransBackGroundColor != NULL &&
  376.     XParseColor(XDisplay, XColorMap, TransBackGroundColor, &Color) &&
  377.     XAllocColor(XDisplay, XColorMap, &Color))
  378.     TransBackGroundPixel = Color.pixel;
  379.     else
  380.     TransBackGroundPixel = BlackPixel(XDisplay, XScreen);
  381.  
  382.     if (TransBorderColor != NULL &&
  383.     XParseColor(XDisplay, XColorMap, TransBorderColor, &Color) &&
  384.     XAllocColor(XDisplay, XColorMap, &Color))
  385.     TransBorderPixel = Color.pixel;
  386.     else
  387.     TransBorderPixel = WhitePixel(XDisplay, XScreen);
  388.  
  389.     if (TransBorderWidthStr)
  390.     TransBorderWidth = atoi(TransBorderWidthStr);
  391.     else
  392.     TransBorderWidth = 1;
  393.  
  394.     if (TransTextColor != NULL &&
  395.     XParseColor(XDisplay, XColorMap, TransTextColor, &Color) &&
  396.     XAllocColor(XDisplay, XColorMap, &Color))
  397.     TransTextPixel = Color.pixel;
  398.     else
  399.     TransTextPixel = WhitePixel(XDisplay, XScreen);
  400.  
  401.     if (TransSubWinBackColor != NULL &&
  402.     XParseColor(XDisplay, XColorMap, TransSubWinBackColor, &Color) &&
  403.     XAllocColor(XDisplay, XColorMap, &Color))
  404.     TransSubWinBackPixel = Color.pixel;
  405.     else
  406.     TransSubWinBackPixel = BlackPixel(XDisplay, XScreen);
  407.  
  408.     if (TransSubWinBorderColor != NULL &&
  409.     XParseColor(XDisplay, XColorMap, TransSubWinBorderColor, &Color) &&
  410.     XAllocColor(XDisplay, XColorMap, &Color))
  411.     TransSubWinBorderPixel = Color.pixel;
  412.     else
  413.     TransSubWinBorderPixel = WhitePixel(XDisplay, XScreen);
  414.  
  415.     if (TransSubWinBorderWidthStr)
  416.     TransSubWinBorderWidth = atoi(TransSubWinBorderWidthStr);
  417.     else
  418.     TransSubWinBorderWidth = 1;
  419.  
  420.     if (TransGeometry)
  421.     {
  422.     i = XParseGeometry(TransGeometry, &TransPosX, &TransPosY,
  423.                                   &TransWidth, &TransHeight);
  424.     TransHasPos = i & XValue && i & YValue;
  425.     TransHasSize =  i & WidthValue && i & HeightValue;
  426.     }
  427.     else TransHasSize = TransHasPos = FALSE;
  428.  
  429.     if (TransCursorColorStr != NULL &&
  430.     XParseColor(XDisplay, XColorMap, TransCursorColorStr, &Color) &&
  431.     XAllocColor(XDisplay, XColorMap, &Color)) {
  432.     TransCursorColor = (XColor *) malloc(sizeof(XColor));
  433.     *TransCursorColor = Color;
  434.     }
  435.     else
  436.     TransCursorColor = NULL;
  437.  
  438.     if (ViewBackGroundColor &&
  439.     XParseColor(XDisplay, XColorMap, ViewBackGroundColor, &Color) &&
  440.     XAllocColor(XDisplay, XColorMap, &Color))
  441.     ViewBackGroundPixel = Color.pixel;
  442.     else
  443.     ViewBackGroundPixel = BlackPixel(XDisplay, XScreen);
  444.  
  445.     if (ViewBorderColor &&
  446.     XParseColor(XDisplay, XColorMap, ViewBorderColor, &Color) &&
  447.     XAllocColor(XDisplay, XColorMap, &Color))
  448.     ViewBorderPixel = Color.pixel;
  449.     else
  450.     ViewBorderPixel = WhitePixel(XDisplay, XScreen);
  451.  
  452.     if (ViewTextColor != NULL &&
  453.     XParseColor(XDisplay, XColorMap, ViewTextColor, &Color) &&
  454.     XAllocColor(XDisplay, XColorMap, &Color))
  455.     ViewTextPixel = Color.pixel;
  456.     else
  457.     ViewTextPixel = WhitePixel(XDisplay, XScreen);
  458.  
  459.     if (ViewBorderWidthStr)
  460.     ViewBorderWidth = atoi(ViewBorderWidthStr);
  461.     else
  462.     ViewBorderWidth = 1;
  463.  
  464.     if (ViewGeometry)
  465.     {
  466.     i = XParseGeometry(ViewGeometry, &ViewPosX, &ViewPosY,
  467.                                  &ViewWidth, &ViewHeight);
  468.     ViewHasPos = i & XValue && i & YValue;
  469.     ViewHasSize = i & WidthValue && i & HeightValue;
  470.     }
  471.     else ViewHasSize = ViewHasPos = FALSE;
  472.  
  473.     if (ViewCursorColorStr != NULL &&
  474.     XParseColor(XDisplay, XColorMap, ViewCursorColorStr, &Color) &&
  475.     XAllocColor(XDisplay, XColorMap, &Color)) {
  476.     ViewCursorColor = (XColor *) malloc(sizeof(XColor));
  477.     *ViewCursorColor = Color;
  478.     }
  479.     else
  480.     ViewCursorColor = NULL;
  481. }
  482.  
  483. /*****************************************************************************
  484. * Set up and draw a transformation window.                     *
  485. *****************************************************************************/
  486. static void SetTransformWindow(int argc, char **argv)
  487. {
  488.     int SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight;
  489.     long ValueMask;
  490.     XSizeHints Hints;
  491.     XSetWindowAttributes SetWinAttr;
  492.  
  493.     SetWinAttr.background_pixel = TransBackGroundPixel;
  494.     SetWinAttr.border_pixel = TransBorderPixel;
  495.     ValueMask = CWBackPixel | CWBorderPixel;
  496.  
  497.     Hints.flags = PMinSize | PMaxSize;
  498.     Hints.x = Hints.y = 1;
  499.     Hints.min_width = 100;
  500.     Hints.max_width = 1000;
  501.     Hints.min_height = 200;
  502.     Hints.max_height = 1000;
  503.     if (TransHasSize) {
  504.     Hints.flags |= PSize;
  505.     if (TransWidth < Hints.min_width) TransWidth = Hints.min_width;
  506.     if (TransWidth > Hints.max_width) TransWidth = Hints.max_width;
  507.     if (TransHeight < Hints.min_height) TransHeight = Hints.min_height;
  508.     if (TransHeight > Hints.max_height) TransHeight = Hints.max_height;
  509.     Hints.width = TransWidth;
  510.     Hints.height = TransHeight;
  511.     }
  512.     else {
  513.     Hints.flags |= PSize;
  514.     Hints.width = TransWidth = DEFAULT_TRANS_WIDTH;
  515.     Hints.height = TransHeight = DEFAULT_TRANS_HEIGHT;
  516.     }
  517.     if (TransHasPos) {
  518.     Hints.flags |= USPosition;
  519.     Hints.x = TransPosX;
  520.     Hints.y = TransPosY;
  521.     }
  522.  
  523.     TransformWndw = XCreateWindow(XDisplay, XRoot,
  524.                   TransPosX, TransPosY,
  525.                   TransWidth, TransHeight,
  526.                       1, 0, CopyFromParent, CopyFromParent,
  527.                       ValueMask, &SetWinAttr);
  528.  
  529.     XSetStandardProperties(XDisplay, TransformWndw,
  530.                PROGRAM_NAME, PROGRAM_NAME, None,
  531.                argv, argc,
  532.                &Hints);
  533.  
  534.     /* Set our own cursor: */
  535.     XCursor = XCreateFontCursor(XDisplay, XC_hand1);
  536.     XDefineCursor(XDisplay, TransformWndw, XCursor);
  537.     if (TransCursorColor != NULL)
  538.     XRecolorCursor(XDisplay, XCursor, TransCursorColor, &BlackColor);
  539.  
  540.     /* Now lets create the sub windows inside: */
  541.     SubTransPosX = MIN(TransWidth / 10, 20);
  542.     SubTransPosY =  TransHeight / 25;
  543.     SubTransWidth = TransWidth - SubTransPosX * 2;
  544.     SubTransHeight = TransHeight / 25;
  545.  
  546.     /* OBJECT/SCREEN space toggle: */
  547.     ObjScrTglWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  548.                       SubTransWidth, SubTransHeight);
  549.  
  550.     /* PERSPECTIVE/ORTHOGRPHIC toggle: */
  551.     PersOrthoTglWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  552.                          SubTransWidth, SubTransHeight);
  553.     PersOrthoZWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  554.                          SubTransWidth, SubTransHeight);
  555.  
  556.     /* ROTATE: */
  557.     RotateXWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  558.                     SubTransWidth, SubTransHeight);
  559.     RotateYWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  560.                     SubTransWidth, SubTransHeight);
  561.     RotateZWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  562.                     SubTransWidth, SubTransHeight);
  563.     /* TRANSLATE: */
  564.     TranslateXWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  565.                        SubTransWidth, SubTransHeight);
  566.     TranslateYWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  567.                        SubTransWidth, SubTransHeight);
  568.     TranslateZWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  569.                        SubTransWidth, SubTransHeight);
  570.     /* SCALE: */
  571.     ScaleWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  572.                       SubTransWidth, SubTransHeight);
  573.  
  574.     /* DEPTH CUE: */
  575.     DepthCueWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  576.                      SubTransWidth, SubTransHeight);
  577.  
  578.     /* SAVE PS: */
  579.     SavePSWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  580.                        SubTransWidth, SubTransHeight);
  581.  
  582.     /* SAVE MATRIX: */
  583.     SaveMatrixWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  584.                        SubTransWidth, SubTransHeight);
  585.  
  586.     /* RESET MATRIX: */
  587.     ResetMatrixWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  588.                         SubTransWidth, SubTransHeight);
  589.  
  590.     /* QUIT: */
  591.     QuitWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  592.                      SubTransWidth, SubTransHeight);
  593.  
  594.     XSelectInput(XDisplay, TransformWndw, ExposureMask);
  595.  
  596.     ObjectSpaceState = GlblTransformMode == TRANS_OBJECT;
  597.     PerspectiveState = GlblViewMode == VIEW_PERSPECTIVE;
  598.     DepthCueState = GlblDepthCue;
  599. }
  600.  
  601. /*****************************************************************************
  602. * Redraw a transformation window (after exposure or resize events).         *
  603. *****************************************************************************/
  604. static void RedrawTransformWindow(void)
  605. {
  606.     int SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight,
  607.         SizeChanged = FALSE;
  608.     long ValueMask;
  609.     XSizeHints Hints;
  610.     XWindowAttributes TransWindowAttr;
  611.     XSetWindowAttributes SetWinAttr;
  612.  
  613.     XClearWindow(XDisplay, TransformWndw);
  614.  
  615.     /* Get the window attributes, and see if it is the same size or not. */
  616.     XGetWindowAttributes(XDisplay, TransformWndw, &TransWindowAttr);
  617.     if (TransWindowAttr.width != TransWidth ||
  618.     TransWindowAttr.height != TransHeight)
  619.     {
  620.     SizeChanged = TRUE;
  621.     TransWidth = TransWindowAttr.width;
  622.     TransHeight = TransWindowAttr.height;
  623.     }
  624.  
  625.     /* Now lets update the sub windows inside: */
  626.     SubTransPosX = MIN(TransWidth / 10, 20);
  627.     SubTransPosY =  TransHeight / 28;
  628.     SubTransWidth = TransWidth - SubTransPosX * 2;
  629.     SubTransHeight = TransHeight / 28;
  630.  
  631.     /* OBJECT/SCREEN space toggle: */
  632.     RedrawTransformSubWindow(ObjScrTglWndw, SubTransPosX, SubTransPosY,
  633.                  SubTransWidth, SubTransHeight, FALSE,
  634.                  GlblTransformMode == TRANS_OBJECT ?
  635.                  "Object" : "Screen");
  636.     SubTransPosY += SubTransHeight * 2;
  637.  
  638.     /* PERSPECTIVE/ORTHOGRPHIC toggle: */
  639.     RedrawTransformSubWindow(PersOrthoTglWndw, SubTransPosX, SubTransPosY,
  640.                  SubTransWidth, SubTransHeight, FALSE,
  641.                  GlblViewMode == VIEW_ORTHOGRAPHIC ?
  642.                  "Orthographic" : "Perspective");
  643.     SubTransPosY += SubTransHeight;
  644.     RedrawTransformSubWindow(PersOrthoZWndw, SubTransPosX, SubTransPosY,
  645.                  SubTransWidth, SubTransHeight, TRUE, NULL);
  646.     SubTransPosY += SubTransHeight;
  647.     DrawText(TransformWndw, "Z", SubTransPosX / 2,
  648.          SubTransPosY - SubTransHeight / 4, TransTextPixel);
  649.     SubTransPosY += SubTransHeight;
  650.  
  651.     /* ROTATE: */
  652.     DrawText(TransformWndw, "Rotate", TransWidth / 2, SubTransPosY,
  653.          TransTextPixel);
  654.     SubTransPosY += SubTransHeight / 2;
  655.     RedrawTransformSubWindow(RotateXWndw, SubTransPosX, SubTransPosY,
  656.                  SubTransWidth, SubTransHeight, TRUE, NULL);
  657.     SubTransPosY += SubTransHeight;
  658.     DrawText(TransformWndw, "X", SubTransPosX / 2,
  659.          SubTransPosY - SubTransHeight / 4, TransTextPixel);
  660.     RedrawTransformSubWindow(RotateYWndw, SubTransPosX, SubTransPosY,
  661.                  SubTransWidth, SubTransHeight, TRUE, NULL);
  662.     SubTransPosY += SubTransHeight;
  663.     DrawText(TransformWndw, "Y", SubTransPosX / 2,
  664.          SubTransPosY - SubTransHeight / 4, TransTextPixel);
  665.     RedrawTransformSubWindow(RotateZWndw, SubTransPosX, SubTransPosY,
  666.                  SubTransWidth, SubTransHeight, TRUE, NULL);
  667.     SubTransPosY += SubTransHeight;
  668.     DrawText(TransformWndw, "Z", SubTransPosX / 2,
  669.          SubTransPosY - SubTransHeight / 4, TransTextPixel);
  670.  
  671.     /* TRANSLATE: */
  672.     SubTransPosY += SubTransHeight;
  673.     DrawText(TransformWndw, "Translate", TransWidth / 2, SubTransPosY,
  674.          TransTextPixel);
  675.     SubTransPosY += SubTransHeight / 2;
  676.     RedrawTransformSubWindow(TranslateXWndw, SubTransPosX, SubTransPosY,
  677.                  SubTransWidth, SubTransHeight, TRUE, NULL);
  678.     SubTransPosY += SubTransHeight;
  679.     DrawText(TransformWndw, "X", SubTransPosX / 2,
  680.          SubTransPosY - SubTransHeight / 4, TransTextPixel);
  681.     RedrawTransformSubWindow(TranslateYWndw, SubTransPosX, SubTransPosY,
  682.                  SubTransWidth, SubTransHeight, TRUE, NULL);
  683.     SubTransPosY += SubTransHeight;
  684.     DrawText(TransformWndw, "Y", SubTransPosX / 2,
  685.          SubTransPosY - SubTransHeight / 4, TransTextPixel);
  686.     RedrawTransformSubWindow(TranslateZWndw, SubTransPosX, SubTransPosY,
  687.                  SubTransWidth, SubTransHeight, TRUE, NULL);
  688.     SubTransPosY += SubTransHeight;
  689.     DrawText(TransformWndw, "Z", SubTransPosX / 2,
  690.          SubTransPosY - SubTransHeight / 4, TransTextPixel);
  691.  
  692.     /* SCALE: */
  693.     SubTransPosY += SubTransHeight;
  694.     DrawText(TransformWndw, "Scale", TransWidth / 2, SubTransPosY,
  695.          TransTextPixel);
  696.     SubTransPosY += SubTransHeight / 2;
  697.     RedrawTransformSubWindow(ScaleWndw, SubTransPosX, SubTransPosY,
  698.                  SubTransWidth, SubTransHeight, TRUE, NULL);
  699.  
  700.     /* DEPTH CUE: */
  701.     SubTransPosY += SubTransHeight * 2;
  702.     RedrawTransformSubWindow(DepthCueWndw, SubTransPosX, SubTransPosY,
  703.                  SubTransWidth, SubTransHeight, FALSE,
  704.                  GlblDepthCue ? "Depth Cue" : "No Depth Cue");
  705.  
  706.     /* SAVE PS: */
  707.     SubTransPosY += SubTransHeight * 2;
  708.     RedrawTransformSubWindow(SavePSWndw, SubTransPosX, SubTransPosY,
  709.                  SubTransWidth, SubTransHeight, FALSE,
  710.                  "Save PS");
  711.  
  712.     /* SAVE MATRIX: */
  713.     SubTransPosY += SubTransHeight * 2;
  714.     RedrawTransformSubWindow(SaveMatrixWndw, SubTransPosX, SubTransPosY,
  715.                  SubTransWidth, SubTransHeight, FALSE,
  716.                  "Save Matrix");
  717.  
  718.     /* RESET MATRIX: */
  719.     SubTransPosY += SubTransHeight * 2;
  720.     RedrawTransformSubWindow(ResetMatrixWndw, SubTransPosX, SubTransPosY,
  721.                  SubTransWidth, SubTransHeight, FALSE,
  722.                  "Reset Matrix");
  723.  
  724.     /* QUIT: */
  725.     SubTransPosY += SubTransHeight * 3;
  726.     RedrawTransformSubWindow(QuitWndw, SubTransPosX, SubTransPosY,
  727.                  SubTransWidth, SubTransHeight, FALSE, "Quit" );
  728.  
  729.     /* Save half of the window width so we can refer to the zero point on X */
  730.     /* axes, which is the vertical line in the middle of the window:        */
  731.     SubWindowWidthState2 = SubTransWidth / 2;
  732.     SubWindowHeightState2 = SubTransHeight / 2;
  733. }
  734.  
  735. /*****************************************************************************
  736. * Set up a transformation sub window.                         *
  737. *****************************************************************************/
  738. static Window SetTransformSubWindow(int SubTransPosX, int SubTransPosY,
  739.                     int SubTransWidth, int SubTransHeight)
  740. {
  741.     long ValueMask;
  742.     XSetWindowAttributes SetWinAttr;
  743.     Window Win;
  744.  
  745.     SetWinAttr.background_pixel = TransSubWinBackPixel;
  746.     SetWinAttr.border_pixel = TransSubWinBorderPixel;
  747.     SetWinAttr.bit_gravity = SetWinAttr.win_gravity = CenterGravity;
  748.     ValueMask = CWBackPixel | CWBorderPixel | CWBitGravity | CWWinGravity;
  749.  
  750.     Win = XCreateWindow(XDisplay, TransformWndw,
  751.             SubTransPosX, SubTransPosY,
  752.             SubTransWidth, SubTransHeight,
  753.             1, 0, CopyFromParent, CopyFromParent,
  754.             ValueMask, &SetWinAttr);
  755.  
  756.     XSelectInput(XDisplay, Win, ButtonPressMask | Button1MotionMask);
  757.  
  758.     XMapWindow(XDisplay, Win);
  759.  
  760.     return Win;
  761. }
  762.  
  763. /*****************************************************************************
  764. * Redraw a transformation sub window.                         *
  765. *****************************************************************************/
  766. static void RedrawTransformSubWindow(Window Win,
  767.     int SubTransPosX, int SubTransPosY, int SubTransWidth, int SubTransHeight,
  768.     int DrawMiddleVertLine, char *DrawString)
  769. {
  770.     XGCValues values;
  771.  
  772.     XMoveResizeWindow(XDisplay, Win, SubTransPosX, SubTransPosY,
  773.                                        SubTransWidth, SubTransHeight);
  774.     if (DrawMiddleVertLine) {
  775.     values.foreground = TransSubWinBorderPixel;
  776.     XChangeGC(XDisplay, XTransGraphContext, GCForeground, &values);
  777.  
  778.     XDrawLine(XDisplay, Win, XTransGraphContext,
  779.           SubTransWidth / 2, 0, SubTransWidth / 2, SubTransHeight);
  780.     }
  781.     if (DrawString != NULL) {
  782.     DrawText(Win, DrawString, SubTransWidth / 2, SubTransHeight / 2,
  783.          TransTextPixel);
  784.     }
  785. }
  786.  
  787. /*****************************************************************************
  788. * Set up a view window.                                 *
  789. *****************************************************************************/
  790. static void SetViewWindow(int argc, char **argv)
  791. {
  792.     long ValueMask;
  793.     XSizeHints Hints;
  794.     XSetWindowAttributes SetWinAttr;
  795.  
  796.     SetWinAttr.background_pixel = ViewBackGroundPixel;
  797.     SetWinAttr.border_pixel = ViewBorderPixel;
  798.     ValueMask = CWBackPixel | CWBorderPixel;
  799.  
  800.     Hints.flags = PMinSize | PMaxSize;
  801.     Hints.x = Hints.y = 1;
  802.     Hints.min_width = 50;
  803.     Hints.max_width = 1000;
  804.     Hints.min_height = 50;
  805.     Hints.max_height = 1000;
  806.     if (ViewHasSize) {
  807.     Hints.flags |= PSize;
  808.     if (ViewWidth < Hints.min_width) ViewWidth = Hints.min_width;
  809.     if (ViewWidth > Hints.max_width) ViewWidth = Hints.max_width;
  810.     if (ViewHeight < Hints.min_height) ViewHeight = Hints.min_height;
  811.     if (ViewHeight > Hints.max_height) ViewHeight = Hints.max_height;
  812.     Hints.width = ViewWidth;
  813.     Hints.height = ViewHeight;
  814.     }
  815.     else {
  816.     Hints.flags |= PSize;
  817.     Hints.width = ViewWidth = DEFAULT_VIEW_WIDTH;
  818.     Hints.height = ViewHeight = DEFAULT_VIEW_HEIGHT;
  819.     }
  820.     if (ViewHasPos) {
  821.     Hints.flags |= USPosition;
  822.     Hints.x = ViewPosX;
  823.     Hints.y = ViewPosY;
  824.     }
  825.  
  826.     ViewWndw = XCreateWindow(XDisplay, XRoot,
  827.                  ViewPosX, ViewPosY,
  828.                  ViewWidth, ViewHeight,
  829.                  1, 0, CopyFromParent, CopyFromParent,
  830.                  ValueMask, &SetWinAttr);
  831.  
  832.     XSetStandardProperties(XDisplay, ViewWndw,
  833.                PROGRAM_NAME, PROGRAM_NAME, None,
  834.                argv, argc,
  835.                &Hints);
  836.  
  837.     /* Set our own cursor: */
  838.     XCursor = XCreateFontCursor(XDisplay, XC_iron_cross);
  839.     XDefineCursor(XDisplay, ViewWndw, XCursor);
  840.     if (ViewCursorColor != NULL)
  841.     XRecolorCursor(XDisplay, XCursor, ViewCursorColor, &BlackColor);
  842.  
  843.     XSelectInput(XDisplay, ViewWndw, ExposureMask | ButtonPressMask);
  844.     
  845.     XMapWindow(XDisplay, ViewWndw);
  846. }
  847.  
  848. /******************************************************************************
  849. * Returns status of abort key if pressed, and reset it.                  *
  850. ******************************************************************************/
  851. int IsAbortKeyPressed(void)
  852. {
  853.     int RetVal = AbortKeyPressed;
  854.  
  855.     AbortKeyPressed = FALSE;
  856.  
  857.     return RetVal;
  858. }
  859.  
  860. /******************************************************************************
  861. * Flush output of graphic command.                          *
  862. ******************************************************************************/
  863. int GraphicFlush(void)
  864. {
  865.     XFlush(XDisplay);
  866. }
  867.  
  868. /******************************************************************************
  869. * Handle X events                                  *
  870. ******************************************************************************/
  871. GraphicEventType GetGraphicEvent(RealType *ChangeFactor, char **ToggleStr)
  872. {
  873.     static int LastX;
  874.     int Dx;
  875.     XEvent Event;
  876.     XWindowAttributes WinAttr;
  877.  
  878.     XMapWindow(XDisplay, TransformWndw);
  879.  
  880.     while (TRUE) {
  881.     XNextEvent(XDisplay, &Event);
  882.     switch (Event.type) {
  883.         case Expose:
  884.             /* Get rid of all Expose events in the queue. */
  885.             while (XCheckWindowEvent(XDisplay, Event.xbutton.window,
  886.                           ExposureMask, &Event));
  887.             if (Event.xbutton.window == TransformWndw)
  888.             RedrawTransformWindow();
  889.         else
  890.             if (Event.xbutton.window == ViewWndw) {
  891.             XGetWindowAttributes(XDisplay, ViewWndw, &WinAttr);
  892.             ViewWidth = WinAttr.width;
  893.             ViewHeight = WinAttr.height;
  894.             UpdateInteractHandleInput();
  895.         }
  896.         break;
  897.         case ButtonPress:
  898.         LastX = Event.xbutton.x;
  899.         *ChangeFactor = ((RealType) (LastX - SubWindowWidthState2)) /
  900.                             SubWindowWidthState2;
  901.         if (Event.xbutton.button == 3) {
  902.             AbortKeyPressed = TRUE;
  903.             break;
  904.         }
  905.  
  906.         if (Event.xbutton.window == ObjScrTglWndw) {
  907.             XClearWindow(XDisplay, ObjScrTglWndw);
  908.             ObjectSpaceState = !ObjectSpaceState;
  909.             DrawText(ObjScrTglWndw,
  910.                  *ToggleStr = ObjectSpaceState ? "Object" : "Screen",
  911.                  SubWindowWidthState2, SubWindowHeightState2,
  912.                  TransTextPixel);
  913.             return EVENT_SCR_OBJ_TGL;
  914.         }
  915.         else
  916.         if (Event.xbutton.window == PersOrthoTglWndw) {
  917.             XClearWindow(XDisplay, PersOrthoTglWndw);
  918.             PerspectiveState = !PerspectiveState;
  919.             DrawText(PersOrthoTglWndw,
  920.                  *ToggleStr = PerspectiveState ? "Perspective" :
  921.                                                  "Orthographic",
  922.                  SubWindowWidthState2, SubWindowHeightState2,
  923.                  TransTextPixel);
  924.             return EVENT_PERS_ORTHO_TGL;
  925.         }
  926.         else
  927.         if (Event.xbutton.window == PersOrthoZWndw) {
  928.             return EVENT_PERS_ORTHO_Z;
  929.         }
  930.         else
  931.         if (Event.xbutton.window == RotateXWndw) {
  932.             return EVENT_ROTATE_X;
  933.         }
  934.         else
  935.         if (Event.xbutton.window == RotateYWndw) {
  936.             return EVENT_ROTATE_Y;
  937.         }
  938.         else
  939.         if (Event.xbutton.window == RotateZWndw) {
  940.             return EVENT_ROTATE_Z;
  941.         }
  942.         else
  943.         if (Event.xbutton.window == TranslateXWndw) {
  944.             return EVENT_TRANSLATE_X;
  945.         }
  946.         else
  947.         if (Event.xbutton.window == TranslateYWndw) {
  948.             return EVENT_TRANSLATE_Y;
  949.         }
  950.         else
  951.         if (Event.xbutton.window == TranslateZWndw) {
  952.             return EVENT_TRANSLATE_Z;
  953.         }
  954.         else
  955.         if (Event.xbutton.window == ScaleWndw) {
  956.             return EVENT_SCALE;
  957.         }
  958.         else
  959.         if (Event.xbutton.window == DepthCueWndw) {
  960.             XClearWindow(XDisplay, DepthCueWndw);
  961.             DepthCueState = !DepthCueState;
  962.             DrawText(DepthCueWndw,
  963.                  *ToggleStr = DepthCueState ? "Depth Cue" :
  964.                               "No Depth Cue",
  965.                  SubWindowWidthState2, SubWindowHeightState2,
  966.                  TransTextPixel);
  967.             return EVENT_DEPTH_CUE;
  968.         }
  969.         else
  970.         if (Event.xbutton.window == SaveMatrixWndw) {
  971.             return EVENT_SAVE_MATRIX;
  972.         }
  973.         else
  974.         if (Event.xbutton.window == SavePSWndw) {
  975.             return EVENT_SAVE_PS;
  976.         }
  977.         else
  978.         if (Event.xbutton.window == ResetMatrixWndw) {
  979.             return EVENT_RESET_MATRIX;
  980.         }
  981.         else
  982.         if (Event.xbutton.window == QuitWndw) {
  983.             XUnmapWindow(XDisplay, TransformWndw);
  984.             GraphicFlush();
  985.             return EVENT_QUIT;
  986.         }
  987.         break;
  988.         case MotionNotify:
  989.         /* We may get events of movement in Y which are ignored. */
  990.         if (Event.xbutton.x - LastX == 0) break;
  991.  
  992.         *ChangeFactor = ((RealType) (Event.xbutton.x - LastX)) /
  993.                             SubWindowWidthState2;
  994.         LastX = Event.xbutton.x;
  995.  
  996.         if (Event.xbutton.window == PersOrthoZWndw) {
  997.             return EVENT_PERS_ORTHO_Z;
  998.         }
  999.         if (Event.xbutton.window == RotateXWndw) {
  1000.             return EVENT_ROTATE_X;
  1001.         }
  1002.         else
  1003.         if (Event.xbutton.window == RotateYWndw) {
  1004.             return EVENT_ROTATE_Y;
  1005.         }
  1006.         else
  1007.         if (Event.xbutton.window == RotateZWndw) {
  1008.             return EVENT_ROTATE_Z;
  1009.         }
  1010.         else
  1011.         if (Event.xbutton.window == TranslateXWndw) {
  1012.             return EVENT_TRANSLATE_X;
  1013.         }
  1014.         else
  1015.         if (Event.xbutton.window == TranslateYWndw) {
  1016.             return EVENT_TRANSLATE_Y;
  1017.         }
  1018.         else
  1019.         if (Event.xbutton.window == TranslateZWndw) {
  1020.             return EVENT_TRANSLATE_Z;
  1021.         }
  1022.         else
  1023.         if (Event.xbutton.window == ScaleWndw) {
  1024.             return EVENT_SCALE;
  1025.         }
  1026.         break;
  1027.         default:
  1028.         fprintf(stderr, "undefined event type %d.\n", Event.type);
  1029.     }
  1030.     }
  1031. }
  1032.  
  1033. /******************************************************************************
  1034. * Draw text centered at the given position.                      *
  1035. ******************************************************************************/
  1036. static void DrawText(Window Win, char *Str, int PosX, int PosY,
  1037.              unsigned long Color)
  1038. {
  1039.     int Len = strlen(Str),
  1040.         Width = XTextWidth(XLoadedFont, Str, Len);
  1041.     XGCValues values;
  1042.  
  1043.     values.foreground = Color;
  1044.     XChangeGC(XDisplay, XTransGraphContext, GCForeground, &values);
  1045.  
  1046.     XDrawString(XDisplay, Win, XTransGraphContext, PosX - Width / 2,
  1047.         PosY + XFontYOffsetToCenter, Str, Len);
  1048. }
  1049.  
  1050. #endif /* __MSDOS__ */
  1051.