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

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