home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / grafik / irit / drawfn3s / drawfn3d.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-06  |  17.8 KB  |  541 lines

  1. /*****************************************************************************
  2. *   Program to draw a surface function given as    (X, Y, Z) = F(u, v).         *
  3. *                                         *
  4. *   Written by :  Gershon Elber                     Mar. 1989   *
  5. *****************************************************************************/
  6.  
  7. #include <graphics.h>
  8. #include <stdlib.h>
  9. #include <math.h>
  10. #include <string.h>
  11. #include <setjmp.h>
  12. #include <conio.h>
  13. #include <stdio.h>
  14. #include <dos.h>
  15. #include <dir.h>
  16. #include "Program.h"
  17. #include "Expr2TrG.h"
  18. #include "GenMat.h"
  19. #include "MouseDrv.h"
  20. #include "GraphGnG.h"
  21. #include "ViewObj.h"
  22. #include "Config.h"
  23. #include "MathErr.h"
  24.  
  25. char *VersionStr = "DrawFn3d    IBMPC version 1.2,    Gershon Elber,    "
  26.         __DATE__ ",   " __TIME__ "\n"
  27.         "(C) Copyright 1989 Gershon Elber, Non commercial use only.";
  28.  
  29. extern unsigned int  _stklen = 32767;
  30.  
  31. int MouseExists = FALSE; /* Set according to autotest and config enforcment. */
  32. int GraphDriver = DETECT;                        /* " */
  33.  
  34. static jmp_buf LongJumpBuffer;              /* Used in control C trapping. */
  35. static char CurrentWorkingDir[LINE_LEN];/* Save start CWD to recover on exit.*/
  36.  
  37. /* The foolowings are setable (via configuration file drawfn3d.cfg): */
  38. static double UMin = -1.0, UMax = 1.0, VMin = -1.0, VMax = 1.0;
  39. static int NumOfSamples = DEFAULT_SAMPLES, NumOfIsoLines = DEFAULT_ISO_LINES,
  40.        ValidUIsoLines, ValidVIsoLines, DblBuffer = FALSE;
  41.  
  42. /* And here is the configuration module data structure: */
  43. static ConfigStruct SetUp[] =
  44. { { "UMin",        (void *) &UMin,        SU_REAL_TYPE },
  45.   { "UMax",        (void *) &UMax,        SU_REAL_TYPE },
  46.   { "VMin",        (void *) &VMin,        SU_REAL_TYPE },
  47.   { "VMax",        (void *) &VMax,        SU_REAL_TYPE },
  48.   { "NumOfSamples",    (void *) &NumOfSamples,    SU_INTEGER_TYPE },
  49.   { "NumOfIsoLines",    (void *) &NumOfIsoLines, SU_INTEGER_TYPE },
  50.   { "GraphDriver",    (void *) &GraphDriver,  SU_INTEGER_TYPE },
  51.   { "DblBuffer",    (void *) &DblBuffer,    SU_BOOLEAN_TYPE },
  52.   { "Mouse",        (void *) &MouseExists,    SU_BOOLEAN_TYPE } };
  53.  
  54.  /* Number of entries in SetUp structure: */
  55. #define NUM_SET_UP  sizeof(SetUp) / sizeof(ConfigStruct)
  56.  
  57. static void DrawFunction(ExprNode *PFunc[3], char SFunc[3][LINE_LEN_LONG],
  58.     int Color, double UMin, double UMax, double VMin, double VMax,
  59.     MatrixType TransMat, int NumOfSamples, int NumOfIsoLines,
  60.     struct IsoLine *IsoLinesU[MAX_ISO_LINES],
  61.     struct IsoLine *IsoLinesV[MAX_ISO_LINES]);
  62. static void Draw3DAxes(MatrixType TransMat);
  63. static void DoTransformFunction(char SFunc[3][LINE_LEN_LONG],
  64.     MatrixType TransMat, int NumOfSamples,
  65.     int NumOfIsoLines, int DblBuffer,
  66.     struct IsoLine *IsoLinesU[MAX_ISO_LINES],
  67.     struct IsoLine *IsoLinesV[MAX_ISO_LINES]);
  68. static void DrawTransFunction(char SFunc[3][LINE_LEN_LONG], int Color,
  69.     MatrixType TransMat, int NumOfSamples, int NumOfIsoLines,
  70.     struct IsoLine *IsoLinesU[MAX_ISO_LINES],
  71.     struct IsoLine *IsoLinesV[MAX_ISO_LINES]);
  72. static void TestQuitView(void);
  73. static void PrintMathError(void);
  74.  
  75. /*****************************************************************************
  76. * Main routine of function drawing.                         *
  77. *****************************************************************************/
  78. void main(int argc, char **argv)
  79. {
  80.     static struct MenuItem MainMenu[] = {         /* Main Menu selection. */
  81.     YELLOW,        "Function Drawing",
  82.     FUNC_COLOR,    "Get Function",
  83.     CYAN,        "Parameters set",
  84.     CYAN,        "Redraw",
  85.     CYAN,        "Transform Func",
  86.     MAGENTA,    "Save Function",
  87.     MAGENTA,    "",
  88.     CYAN,        "Help",
  89.     MAGENTA,    "",
  90.     BLUE,        "Quit"
  91.     };
  92.     /* Used to save the 3 input functions (X, Y, Z) as binary tree. */
  93.     ExprNode *PFunc[3];
  94.     /* Used to save the 3 input functions (X, Y, Z) as string. */
  95.     char SFunc[3][LINE_LEN_LONG],
  96.     *ErrorMsg;
  97.     /* Num. of samples per One Iso line, & num. of iso lines in u & v axes.  */
  98.     int i, select, InputExists = FALSE;
  99.     MatrixType TransMat;   /* Current 3D transformation will be stored here. */
  100.     struct IsoLine *IsoLinesU[MAX_ISO_LINES], *IsoLinesV[MAX_ISO_LINES];
  101.  
  102.     getcwd(CurrentWorkingDir, LINE_LEN-1);
  103.  
  104.     MouseExists = MouseDetect();       /* Automatic mouse detection routine. */
  105.  
  106.     if (_osmajor <= 2)    /* No argv[0] is given (prgm name) - allways NULL! */
  107.      Config("DrawFn3d", SetUp, NUM_SET_UP);/*Read config. file if exists.*/
  108.     else Config(*argv, SetUp, NUM_SET_UP);   /* Read config. file if exists. */
  109.  
  110.     SFunc[0][0] = SFunc[1][0] = SFunc[2][0] = 0; /* Make sure strings empty. */
  111.  
  112.     while (argc-- > 1) {
  113.     if (strcmp(*++argv, "-z") == 0) {
  114.         fprintf(stderr, "\n%s\n", VersionStr);
  115.         fprintf(stderr, "\nUsage: drawfn3d [-z]\n");
  116.         ConfigPrint(SetUp, NUM_SET_UP);
  117.         MyExit(0);
  118.     }
  119.     }
  120.  
  121.     /* If math error occurs - long jump to given place: */
  122.     MathErrorSetUp(ME_LONGJMP, &LongJumpBuffer);
  123.  
  124.     SetUpHardErr();          /* Set up hardware error, int 24 trap routine. */
  125.  
  126.     for    (i=0; i<NumOfIsoLines; i++) {/*    Allocate the starting data structure.*/
  127.     IsoLinesU[i] = (IsoLine    *) malloc(3*sizeof(float)*NumOfSamples);
  128.     IsoLinesV[i] = (IsoLine    *) malloc(3*sizeof(float)*NumOfSamples);
  129.     if (IsoLinesV[i] == (IsoLine *)    NULL) {
  130.         printf("Not enough memory: needed %ld, found only %ld.",
  131.          3L * sizeof(float) * NumOfSamples * NumOfIsoLines * 2L,
  132.          3L * sizeof(float) * NumOfSamples * i * 2L);
  133.         getch();
  134.         MyExit(1);
  135.     }
  136.     }
  137.  
  138.     GGInitGraph();
  139.     GGClearMenuArea();
  140.     GGClearViewArea();
  141.  
  142.     if (MouseExists)   /* Must be initialized AFTER graph mode was selected. */
  143.     if ((ErrorMsg = MouseInit()) != 0) {
  144.         /* Must be called before any usage! */
  145.         fprintf(stderr, "\n%s\n\n\tPress any key to continue:", ErrorMsg);
  146.         MouseExists = FALSE;
  147.         getch();
  148.     }
  149.  
  150.     while (TRUE) {
  151.     GGMenuDraw(9, MainMenu, TRUE);               /* Draw MainMenu. */
  152.     select = GGMenuPick();
  153.  
  154.     setjmp(LongJumpBuffer);
  155.     PrintMathError();            /* If was error - put error msg. */
  156.  
  157.     switch (select)    {
  158.         case 1:                /* Get New function to draw. */
  159.         DoGetFunc(PFunc, SFunc, &InputExists,
  160.             &UMin, &UMax, &VMin, &VMax, &NumOfIsoLines, &NumOfSamples,
  161.             IsoLinesU, IsoLinesV, TransMat);
  162.         break;
  163.  
  164.         case 2:                      /* Set Parameters. */
  165.         if (InputExists)
  166.             DoSetParam(&NumOfSamples, &NumOfIsoLines,
  167.             &UMin, &UMax, &VMin, &VMax,
  168.             &DblBuffer, IsoLinesU, IsoLinesV);
  169.         else {
  170.             GGPutErrorMsg("Load Surf. first");
  171.             break;
  172.         }
  173.  
  174.         case 3:                          /* Redraw. */
  175.         if (InputExists)
  176.             RedrawScreen(PFunc, SFunc, UMin, UMax, VMin, VMax,
  177.             TransMat, NumOfSamples, NumOfIsoLines,
  178.             IsoLinesU, IsoLinesV);
  179.         else GGPutErrorMsg("Load Surf. first");
  180.         break;
  181.  
  182.         case 4:                      /* Transform Function. */
  183.         if (InputExists)
  184.             DoTransformFunction(SFunc, TransMat, NumOfSamples,
  185.             NumOfIsoLines, DblBuffer, IsoLinesU, IsoLinesV);
  186.         else GGPutErrorMsg("Load Surf. first");
  187.         break;
  188.  
  189.         case 5:                       /* Save Function. */
  190.         if (InputExists)
  191.             DoSaveFunc(PFunc, SFunc, UMin, UMax, VMin, VMax,
  192.             NumOfIsoLines, NumOfSamples, TransMat);
  193.         else GGPutErrorMsg("Load Surf. first");
  194.         break;
  195.  
  196.         case 7:                            /* Help. */
  197.         GGPrintHelpMenu("DrawFn3d.hlp", "MAINMENU");
  198.         break;
  199.  
  200.         case 9:                            /* Quit. */
  201.         if (GGConfirm("Quit Program")) MyExit(0);
  202.         break;
  203.     }
  204.     }
  205. }
  206.  
  207. /*****************************************************************************
  208. *   Routines to    clear the data area and    redraw axes and    functions:         *
  209. *****************************************************************************/
  210. void RedrawScreen(ExprNode *PFunc[3], char SFunc[3][LINE_LEN_LONG],
  211.     double UMin, double UMax, double VMin, double VMax,
  212.     MatrixType TransMat, int NumOfSamples, int NumOfIsoLines,
  213.     struct IsoLine *IsoLinesU[MAX_ISO_LINES],
  214.     struct IsoLine *IsoLinesV[MAX_ISO_LINES])
  215. {
  216.     struct viewporttype    view;
  217.  
  218.     getviewsettings(&view);
  219.     GGClearViewArea();
  220.  
  221.     Draw3DAxes(TransMat);
  222.  
  223.     if (setjmp(LongJumpBuffer) == 0)
  224.     DrawFunction(PFunc, SFunc, FUNC_COLOR, UMin, UMax, VMin, VMax,
  225.         TransMat, NumOfSamples, NumOfIsoLines, IsoLinesU, IsoLinesV);
  226.  
  227.     PrintMathError();                /* If was error - put error msg. */
  228.  
  229.     setviewport(view.left, view.top, view.right, view.bottom, view.clip);
  230. }
  231.  
  232. /*****************************************************************************
  233. * Routine to draw the given function PFunc. This routine does not only         *
  234. * calculate the    function, but also updates IsoLinesU/V.                 *
  235. * As control break may interrupt the drawing the data in IsoLinesU/V arrays  *
  236. * might not be fully updated. ValidU/VIsoLines are therefore updated to the  *
  237. * current updated iso line. The DoTransFunction uses there validations.      *
  238. *****************************************************************************/
  239. static void DrawFunction(ExprNode *PFunc[3], char SFunc[3][LINE_LEN_LONG],
  240.     int Color, double UMin, double UMax, double VMin, double VMax,
  241.     MatrixType TransMat, int NumOfSamples, int NumOfIsoLines,
  242.     struct IsoLine *IsoLinesU[MAX_ISO_LINES],
  243.     struct IsoLine *IsoLinesV[MAX_ISO_LINES])
  244. {
  245.     double Du, u, Dv, v, Vec[3];
  246.     char Line[LINE_LEN_LONG];
  247.     int    i, j, k;
  248.  
  249.     GGMySetColor(Color);
  250.     setlinestyle(SOLID_LINE, 0, NORM_WIDTH);
  251.     EvalError();
  252.  
  253.     ValidVIsoLines = ValidUIsoLines = -1;         /* In case of ^C break. */
  254.  
  255.     /* Generate    and draw the U isolines: */
  256.     u =    UMin;
  257.     Du = (UMax - UMin) / (NumOfIsoLines-1);
  258.     for    (i=0; i<NumOfIsoLines; i++) {
  259.     TestQuitView();
  260.     v = VMin;
  261.     Dv = (VMax - VMin) / (NumOfSamples-1);
  262.     SetParamValue(u, PARAMETER_U);
  263.     SetParamValue(v, PARAMETER_V);
  264.     for (j=0; j<3; j++) {
  265.         Vec[j] = EvalTree(PFunc[j]);
  266.         IsoLinesU[i] -> Samples[0][j] = (float) Vec[j];
  267.     }
  268.     MultVecby4by4(Vec, Vec, TransMat);
  269.     GGMyMove(Vec[0], Vec[1]);
  270.  
  271.     for (j=1; j<NumOfSamples; j++) {
  272.         v += Dv;
  273.         SetParamValue(v, PARAMETER_V);
  274.         for    (k=0; k<3; k++)    {
  275.         Vec[k] = EvalTree(PFunc[k]);
  276.         IsoLinesU[i] ->    Samples[j][k] =    (float)    Vec[k];
  277.         }
  278.         MultVecby4by4(Vec, Vec, TransMat);
  279.         GGMyDraw(Vec[0], Vec[1]);
  280.     }
  281.     u += Du;
  282.     ValidUIsoLines = i;
  283.     }
  284.  
  285.     /* Generate    and draw the V isolines: */
  286.     v =    VMin;
  287.     Dv = (VMax - VMin) / (NumOfIsoLines-1);
  288.     for    (i=0; i<NumOfIsoLines; i++) {
  289.     TestQuitView();
  290.     u = UMin;
  291.     Du = (UMax - UMin) / (NumOfSamples-1);
  292.     SetParamValue(u, PARAMETER_U);
  293.     SetParamValue(v, PARAMETER_V);
  294.     for (j=0; j<3; j++) {
  295.         Vec[j] = EvalTree(PFunc[j]);
  296.         IsoLinesV[i] -> Samples[0][j] = (float) Vec[j];
  297.     }
  298.     MultVecby4by4(Vec, Vec, TransMat);
  299.     GGMyMove(Vec[0], Vec[1]);
  300.  
  301.     for (j=1; j<NumOfSamples; j++) {
  302.         u += Du;
  303.         SetParamValue(u, PARAMETER_U);
  304.         for    (k=0; k<3; k++)    {
  305.         Vec[k] = EvalTree(PFunc[k]);
  306.         IsoLinesV[i] ->    Samples[j][k] =    (float)    Vec[k];
  307.         }
  308.         MultVecby4by4(Vec, Vec, TransMat);
  309.         GGMyDraw(Vec[0], Vec[1]);
  310.     }
  311.     v += Dv;
  312.     ValidVIsoLines = i;
  313.     }
  314.  
  315.     for (i=0; i<3; i++) {
  316.     sprintf(Line, "%c(u, v) = %s", 'X' + i, SFunc[i]);
  317.     GGPutMsgXY(Line, FUNC_POS_X, FUNC_POS_Y + FUNC_DIF_Y * i);
  318.     }
  319.  
  320. }
  321.  
  322. /****************************************************************************
  323. * Routine to Draw3D axes (X, Y, Z) :                        *
  324. ****************************************************************************/
  325. static void Draw3DAxes(MatrixType TransMat)
  326. {
  327.     double Vec[3], Orig[3];
  328.  
  329.     GGMySetColor(AXES_COLOR);
  330.  
  331.     setlinestyle(SOLID_LINE, 0, THICK_WIDTH);
  332.  
  333.     Orig[0] = 0.0; Orig[1] = 0.0; Orig[2] = 0.0;
  334.     MultVecby4by4(Orig, Orig, TransMat);
  335.     GGMyMove(Orig[0], Orig[1]);
  336.  
  337.     Vec[0] = 1.0; Vec[1] = 0.0;    Vec[2] = 0.0;
  338.     MultVecby4by4(Vec, Vec, TransMat);
  339.     GGMyDraw(Vec[0], Vec[1]);
  340.     GGPutMsgXY("X", Vec[0], Vec[1]);
  341.  
  342.     GGMyMove(Orig[0], Orig[1]);
  343.  
  344.     Vec[0] = 0.0; Vec[1] = 1.0; Vec[2] = 0.0;
  345.     MultVecby4by4(Vec, Vec, TransMat);
  346.     GGMyDraw(Vec[0], Vec[1]);
  347.     GGPutMsgXY("Y", Vec[0], Vec[1]);
  348.  
  349.     GGMyMove(Orig[0], Orig[1]);
  350.  
  351.     Vec[0] = 0.0; Vec[1] = 0.0; Vec[2] = 1.0;
  352.     MultVecby4by4(Vec, Vec, TransMat);
  353.     GGMyDraw(Vec[0], Vec[1]);
  354.     GGPutMsgXY("Z", Vec[0], Vec[1]);
  355. }
  356.  
  357. /****************************************************************************
  358. * Routine to handle the    view matrix transformation:                *
  359. * If GlobalDblBuffer is    active then double buffering is    used. In that case  *
  360. * the exit page    will allways be    page 0.                        *
  361. ****************************************************************************/
  362. static void DoTransformFunction(char SFunc[3][LINE_LEN_LONG],
  363.     MatrixType TransMat, int NumOfSamples, int NumOfIsoLines, int DblBuffer,
  364.     struct IsoLine *IsoLinesU[MAX_ISO_LINES],
  365.     struct IsoLine *IsoLinesV[MAX_ISO_LINES])
  366. {
  367.     int    i, j, ViewPage = 0, DrawPage, UpPage;  /* Used for double buffering. */
  368.     MatrixType OrigMat;
  369.     struct viewporttype    view;
  370.  
  371.     for (i=0; i<4; i++) for (j=0; j<4; j++) OrigMat[i][j] = TransMat[i][j];
  372.  
  373.     if (DblBuffer) UpPage = 1;
  374.     else       UpPage = 0;     /* Practically deactivate double buffering. */
  375.  
  376.     if (GGScreenMaxPages < 2) UpPage = 0;      /* Only one page in hardware. */
  377.  
  378.     DrawPage = UpPage;
  379.  
  380.     getviewsettings(&view);
  381.     setviewport(0, 0, (int) (GGScreenMaxY/GGAspectRatio), GGScreenMaxY, TRUE);
  382.  
  383.     setactivepage(0);
  384.     InteractDrawMenu();
  385.     if (UpPage != 0) {
  386.     setactivepage(UpPage);
  387.     InteractDrawMenu();
  388.     }
  389.     setvisualpage(ViewPage);
  390.     setactivepage(ViewPage);          /* So the DoSetMatrix can print... */
  391.     while (!InteractHandleInput(TransMat, OrigMat)) {
  392.     setactivepage(DrawPage);
  393.     GGClearViewArea();
  394.  
  395.     Draw3DAxes(TransMat);
  396.  
  397.     if (setjmp(LongJumpBuffer) == 0)
  398.         DrawTransFunction(SFunc, FUNC_COLOR, TransMat,
  399.             NumOfSamples, NumOfIsoLines, IsoLinesU, IsoLinesV);
  400.  
  401.     PrintMathError();            /* If was error - put error msg. */
  402.  
  403.     if (DrawPage) {
  404.         DrawPage = 0;
  405.         ViewPage = UpPage;
  406.     }
  407.     else {
  408.         DrawPage = UpPage;
  409.         ViewPage = 0;
  410.     }
  411.     setvisualpage(ViewPage);
  412.     setactivepage(ViewPage);      /* So the DoSetMatrix can print... */
  413.     }
  414.  
  415.     if (ViewPage) {              /* In case the last page was page 1... */
  416.     setactivepage(0);
  417.     setvisualpage(0);
  418.     GGClearViewArea();
  419.  
  420.     Draw3DAxes(TransMat);
  421.  
  422.     if (setjmp(LongJumpBuffer) == 0)
  423.         DrawTransFunction(SFunc, FUNC_COLOR, TransMat,
  424.             NumOfSamples, NumOfIsoLines, IsoLinesU, IsoLinesV);
  425.  
  426.     PrintMathError();            /* If was error - put error msg. */
  427.     }
  428.  
  429.     GGClearMenuArea();
  430.     setviewport(view.left, view.top, view.right, view.bottom, view.clip);
  431. }
  432.  
  433. /*****************************************************************************
  434. * Routine to draw the given function pfunc                     *
  435. * This routine does not    calculate the function , but uses IsoLinesU/V instead*
  436. * Therefore ValidU/VIsoLines is used instead of NumOfIsoLines!             *
  437. *****************************************************************************/
  438. static void DrawTransFunction(char SFunc[3][LINE_LEN_LONG], int Color,
  439.     MatrixType TransMat, int NumOfSamples, int NumOfIsoLines,
  440.     struct IsoLine *IsoLinesU[MAX_ISO_LINES],
  441.     struct IsoLine *IsoLinesV[MAX_ISO_LINES])
  442. {
  443.     double Vec[3];
  444.     char Line[LINE_LEN_LONG];
  445.     int    i, j, k;
  446.  
  447.     GGMySetColor(Color);
  448.     setlinestyle(SOLID_LINE, 0, NORM_WIDTH);
  449.  
  450.     /* Generate    and draw the U isolines: */
  451.     for    (i=0; i<=ValidUIsoLines; i++) {
  452.     TestQuitView();
  453.     for (j=0; j<3; j++) Vec[j] = (double) IsoLinesU[i] -> Samples[0][j];
  454.     MultVecby4by4(Vec, Vec, TransMat);
  455.     GGMyMove(Vec[0], Vec[1]);
  456.  
  457.     for (j=1; j<NumOfSamples; j++) {
  458.         for    (k=0; k<3; k++)    Vec[k] =
  459.             (double) IsoLinesU[i] -> Samples[j][k];
  460.         MultVecby4by4(Vec, Vec, TransMat);
  461.         GGMyDraw(Vec[0], Vec[1]);
  462.     }
  463.     }
  464.  
  465.     /* Generate    and draw the V isolines: */
  466.     for    (i=0; i<=ValidVIsoLines; i++) {
  467.     TestQuitView();
  468.     for (j=0; j<3; j++) Vec[j] = (double) IsoLinesV[i] -> Samples[0][j];
  469.     MultVecby4by4(Vec, Vec, TransMat);
  470.     GGMyMove(Vec[0], Vec[1]);
  471.  
  472.     for (j=1; j<NumOfSamples; j++) {
  473.         for    (k=0; k<3; k++)    Vec[k] =
  474.             (double) IsoLinesV[i] -> Samples[j][k];
  475.         MultVecby4by4(Vec, Vec, TransMat);
  476.         GGMyDraw(Vec[0], Vec[1]);
  477.     }
  478.     }
  479.  
  480.     for (i=0; i<3; i++) {
  481.     sprintf(Line, "%c(u, v) = %s", 'X'+i, SFunc[i]);
  482.     GGPutMsgXY(Line, FUNC_POS_X, FUNC_POS_Y + FUNC_DIF_Y * i);
  483.     }
  484. }
  485.  
  486. /*****************************************************************************
  487. *  Routine to test if quit display event - occured - SPACE was hit on         *
  488. * keyboard or right button was clicked on mouse.                 *
  489. *****************************************************************************/
  490. static void TestQuitView(void)
  491. {
  492.     int x, y, Buttons;
  493.  
  494.     if (kbhit() && getch() == ' ')
  495.     longjmp(LongJumpBuffer, 1);                   /* Jump to... */
  496.  
  497.     if (MouseExists && MouseQueryBuffer()) {
  498.     MouseGetBuffer(&x, &y, &Buttons);
  499.     if (Buttons & 0x02) longjmp(LongJumpBuffer, 1);           /* Jump to... */
  500.     }
  501. }
  502.  
  503. /****************************************************************************
  504. * Routine to print math    error according    MathErr trapping module or        *
  505. * evaluations in extr2tre module - function evaltree(),    which might be        *
  506. * retrieved via    EvalError() function:                        *
  507. ****************************************************************************/
  508. static void PrintMathError(void)
  509. {
  510.     int    EvalErr;
  511.     char *p = NULL;
  512.  
  513.     if ((EvalErr = EvalError()) != 0) switch (EvalErr) {
  514.     case E_ERR_DivByZero:
  515.         p = "Div by zero";
  516.         break;
  517.     default:
  518.         p = "Undef. math error";
  519.         break;
  520.     }
  521.     else p = MathErrorGet();
  522.  
  523.     GGMySetColor(RED);
  524.  
  525.     if (p != NULL) GGPutErrorMsg(p);
  526. }
  527.  
  528. /*****************************************************************************
  529. * My Routine to exit the program - do some closing staff before calling exit *
  530. *****************************************************************************/
  531. void MyExit(int ExitCode)
  532. {
  533.     GGCloseGraph();                       /* Recover text mode. */
  534.     MouseClose();                /* Recover mouse interrupts. */
  535.  
  536.     chdir(CurrentWorkingDir);      /* Recover original directory before exit. */
  537.     setdisk(CurrentWorkingDir[0] - 'A');        /* Move to the old disk. */
  538.  
  539.     exit(ExitCode);
  540. }
  541.