home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 3 / CDPDIII.bin / pd / graphics / 3d / icoons / source / file.c < prev    next >
C/C++ Source or Header  |  1992-10-25  |  19KB  |  773 lines

  1. /* :ts=8 */
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6. #include <math.h>
  7. #include "general.h"
  8. #include "globals.h"
  9. #include "intui.h"
  10. #include "spl_util.h"
  11. #include "file.h"
  12.  
  13. #define Size_JMan_Point_Table     1000
  14. static int JMan_Point_Table_Idx;
  15. static short *JMan_Point_Table;
  16.  
  17. void StrTrim(char *Out, char *In)
  18. /************************************************************************/
  19. /*                                    */
  20. /* Remove leading and trailing spaces from In, and copy to Out.        */
  21. /*                                    */
  22. /************************************************************************/
  23. {
  24.     int    Last, i, j;
  25.  
  26.     if (In[0] == '\0') {
  27.  
  28.         Out[0] = '\0';
  29.     return;
  30.  
  31.     } /* if */
  32.  
  33.     for (Last = strlen(In)-1; isspace(In[Last]); Last--) ;
  34.  
  35.     for (i = 0; isspace(In[i]); i++) ;
  36.  
  37.     for (j=0; i <= Last; i++,j++) Out[j] = In[i];
  38.  
  39.     Out[j] = '\0';
  40.  
  41. } /* StrTrim */
  42.  
  43. static 
  44. Boolean_T Read_Line(FILE *Stream, char *Line)
  45. /************************************************************************/
  46. /*                                    */
  47. /* Read next line from stream 'Stream'. Return it in 'Line'.        */
  48. /* Ignore blank lines and lines starting with '#'.            */
  49. /*                                    */
  50. /* The function will return TRUE in case of error or eof.        */
  51. /*                                    */
  52. /************************************************************************/
  53. {
  54.  
  55.     while (fgets(Line, Buffer_Length, Stream) != NULL) {
  56.  
  57.     Line[Buffer_Length] = '\0';
  58.  
  59.     StrTrim(Line, Line);
  60.  
  61.     if (Line[0] != '#' && Line[0] != '\0') return(FALSE);
  62.  
  63.     } /* while */
  64.  
  65.     return(TRUE);
  66.  
  67. } /* Read_Line */
  68.  
  69. static 
  70. void Display_Open_Error_Msg(char *Filename)
  71. /************************************************************************/
  72. /*                                    */
  73. /*                                    */
  74. /************************************************************************/
  75. {
  76.     sprintf(Error_Msg, "Couldn't open %s", Filename);
  77.     Display_Message(Error_Msg);
  78. } /* Display_Open_Error_Msg */
  79.  
  80. Boolean_T Object_File_Write(char *Filename)
  81. /************************************************************************/
  82. /*                                    */
  83. /*                                    */
  84. /************************************************************************/
  85. {
  86.     FILE    *Stream;
  87.     Spline_T    *Spline;
  88.     Knot_T    *Knot;
  89.     int        i, j;
  90.  
  91.     Stream = fopen(Filename, "w");
  92.     if (Stream == NULL) {
  93.     Display_Open_Error_Msg(Filename);
  94.     return(TRUE);
  95.     }
  96.  
  97.     Display_Status("Saving object...");
  98.     Set_Pointer(TRUE);
  99.  
  100.     fprintf(Stream, "#\n");
  101.     fprintf(Stream, "# Patches created by ICoons\n");
  102.     fprintf(Stream, "#\n");
  103.  
  104.     fprintf(Stream, "#\n");
  105.     fprintf(Stream, "#--------------------------------------------------\n");
  106.     fprintf(Stream, "# Points:\n");
  107.     fprintf(Stream, "#--------------------------------------------------\n");
  108.     fprintf(Stream, "#\n");
  109.  
  110.     for (i = 0; i < Max_Nbr_Points; i++) {
  111.  
  112.         if (Points[i].Reference_Count > 0) {
  113.  
  114.             fprintf(Stream, "P %d %d %lf %lf %lf\n",
  115.                     i, 
  116.                 Points[i].Reference_Count,
  117.                 Points[i].Pos[0],
  118.                 Points[i].Pos[1],
  119.                 Points[i].Pos[2]);
  120.  
  121.     } /* if */
  122.  
  123.     } /* for */
  124.  
  125.     fprintf(Stream, "#\n");
  126.     fprintf(Stream, "#--------------------------------------------------\n");
  127.     fprintf(Stream, "# Splines:\n");
  128.     fprintf(Stream, "#--------------------------------------------------\n");
  129.     fprintf(Stream, "#\n");
  130.  
  131.     for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
  132.  
  133.     if (Spline->Nbr_Knots > 0) {
  134.  
  135.         fprintf(Stream, "S %d %d\n", 
  136.                 Spline->Nbr_Knots, 
  137.             Spline->Loop);
  138.  
  139.         for (j = 0, Knot = Spline->First; 
  140.           j < Spline->Nbr_Knots; j++, Knot = Knot->Next) {
  141.  
  142.         fprintf(Stream, "K %d %lf %lf %lf\n",
  143.                 Knot->Point_Id,
  144.                 Knot->Tension,
  145.                 Knot->Bias,
  146.                 Knot->Continuity);
  147.  
  148.         } /* for */
  149.  
  150.             fprintf(Stream, "#\n");
  151.             fprintf(Stream, 
  152.             "#--------------------------------------------------\n");
  153.             fprintf(Stream, "#\n");
  154.  
  155.     } /* if */
  156.  
  157.     } /* for */
  158.  
  159.     fclose(Stream);
  160.     Set_Pointer(FALSE);
  161.     Display_Status(NULL);
  162.  
  163.     return(FALSE);
  164.  
  165. } /* Object_File_Write */
  166.  
  167. Boolean_T Object_File_Read(char *Filename)
  168. /************************************************************************/
  169. /*                                    */
  170. /*                                    */
  171. /************************************************************************/
  172. {
  173.     FILE    *Stream;
  174.     char    Line[Buffer_Length+1];
  175.     Spline_T    *Spline;
  176.     Knot_T    *Knot;
  177.     int        Point_Id;
  178.     int        New_Point_Id;
  179.     int        Reference_Count;
  180.     Vector_T    Pos;
  181.     int        Nbr_Knots;
  182.     int        Loop;
  183.     double    Tension, Bias, Continuity;
  184.  
  185.     Knot   = NULL;
  186.     Spline = NULL;
  187.  
  188.     Stream = fopen(Filename, "r");
  189.     if (Stream == NULL) {
  190.     Display_Open_Error_Msg(Filename);
  191.     return(TRUE);
  192.     }
  193.  
  194.     Display_Status("Loading object...");
  195.     Set_Pointer(TRUE);
  196.  
  197.     for (Point_Id = 0; Point_Id < Max_Nbr_Points; Point_Id++) 
  198.                         Points[Point_Id].Work = -1;
  199.  
  200.     while (! Read_Line(Stream, Line)) {
  201.  
  202.     if (Line[0] == 'P') {         /* Point:        */
  203.  
  204.             sscanf(Line, "P %d %d %lf %lf %lf",
  205.                     &Point_Id, 
  206.                 &Reference_Count,
  207.                 &Pos[0], &Pos[1], &Pos[2]);
  208.  
  209.         if (Point_Id >= 0 && Point_Id < Max_Nbr_Points) {
  210.  
  211.         New_Point_Id = Point_New(Pos);
  212.         if (New_Point_Id < 0) {
  213.                    Display_Message("No more space for points.");
  214.                 Set_Pointer(FALSE);
  215.             fclose(Stream);
  216.                 return(TRUE);        
  217.         }
  218.         Points[Point_Id].Work = New_Point_Id;
  219.  
  220.         } /* if */
  221.  
  222.     } /* if */
  223.  
  224.     if (Line[0] == 'S') {     /* Spline start    :        */
  225.  
  226.         sscanf(Line, "S %d %d",  &Nbr_Knots,  &Loop);
  227.  
  228.         Spline = Spline_New();
  229.         if (Spline == NULL) {
  230.                Display_Message("Couldn't allocate memory for new spline");
  231.             Set_Pointer(FALSE);
  232.         fclose(Stream);
  233.             return(TRUE);        
  234.         }
  235.  
  236.         Spline->Flags     = 0;
  237.         Spline->Nbr_Knots = 0;
  238.         Spline_Loop(Spline, Loop);
  239.         Knot           = NULL;
  240.  
  241.          } /* if */
  242.  
  243.     if (Line[0] == 'K') {     /* Knot :        */
  244.  
  245.         sscanf(Line, "K %d %lf %lf %lf",
  246.                 &Point_Id,
  247.                 &Tension,
  248.                 &Bias,
  249.                 &Continuity);
  250.  
  251.         if (Spline != NULL) {
  252.         
  253.         Knot = Knot_New(Spline, Knot);
  254.         if (Knot == NULL) {
  255.             Display_Message("Couldn't allocate memory for new knot");
  256.                 Set_Pointer(FALSE);
  257.             fclose(Stream);
  258.                return(TRUE);
  259.         } /* if */
  260.  
  261.         if (Point_Id < 0 || Point_Id >= Max_Nbr_Points) {
  262.             Display_Message("Invalid point id in file");
  263.                 Set_Pointer(FALSE);
  264.             fclose(Stream);
  265.                return(TRUE);
  266.         }
  267.         /* We have probably moved this point to another position */
  268.         /* Get new point id.                     */
  269.  
  270.         New_Point_Id = Points[Point_Id].Work;
  271.         if (New_Point_Id < 0 || New_Point_Id >= Max_Nbr_Points) {
  272.             Display_Message("Inconsistent point id in file");
  273.                 Set_Pointer(FALSE);
  274.             fclose(Stream);
  275.                return(TRUE);
  276.         }
  277.             Knot->Point_Id   = New_Point_Id;
  278.             Knot->Tension    = Tension;
  279.             Knot->Bias        = Bias;
  280.             Knot->Continuity = Continuity;
  281.             Knot->Flags      = 0;
  282.  
  283.         Points[New_Point_Id].Reference_Count++;
  284.  
  285.         } /* if */
  286.  
  287.     } /* if */
  288.  
  289.     } /* while */
  290.  
  291.     fclose(Stream);
  292.     Display_Status(NULL);
  293.     Set_Pointer(FALSE);
  294.  
  295.     return(FALSE);
  296.  
  297. } /* Object_File_Read */
  298.  
  299. static
  300. Boolean_T JMan_Header_Read(FILE *Stream, int *Nbr_Splines)
  301. /************************************************************************/
  302. /*                                    */
  303. /*                                    */
  304. /************************************************************************/
  305. {
  306.     char    Line[Buffer_Length+1];
  307.     if (Read_Line(Stream, Line)) goto Eof;
  308.     if (strncmp(Line, "SCUL", 4) != 0) {
  309.     Display_Message("Not a Journeyman .seg file");
  310.     return(TRUE);
  311.     } /* if */
  312.  
  313.     if (Read_Line(Stream, Line)) goto Eof;    /* A            */
  314.     if (Read_Line(Stream, Line)) goto Eof;    /* MinPos MaxPos    */
  315.     if (Read_Line(Stream, Line)) goto Eof;    /* Pos             */
  316.  
  317.     if (Read_Line(Stream, Line)) goto Eof;    /* Nbr_Splines        */
  318.     *Nbr_Splines = atoi(Line);
  319.  
  320.     if (*Nbr_Splines < 1) {
  321.  
  322.     sprintf(Error_Msg, "Number of splines (%s) out of range", Line);
  323.     Display_Message(Error_Msg);
  324.     return(TRUE);
  325.  
  326.     } /* if */
  327.  
  328.     return(FALSE);
  329.  
  330. Eof:
  331.     Display_Message("Eof before expected");
  332.     fclose(Stream);
  333.     return(TRUE);
  334.  
  335. } /* JMan_Header_Read */
  336.  
  337. static
  338. Boolean_T JMan_Knot_Read(FILE *Stream, Spline_T *Spline, Knot_T **Knot,
  339.                 int *Nbr_Points)
  340. /************************************************************************/
  341. /*                                    */
  342. /*                                    */
  343. /************************************************************************/
  344. {
  345.     char    Line[Buffer_Length+1];
  346.     int        i1, i2, i3;
  347.     int        Idx;
  348.     double    X, Y, Z;
  349.     double    Tension, Bias, Continuity;
  350.     double    Alfa1, Gamma1, Magnitude1;
  351.     double    Alfa2, Gamma2, Magnitude2;
  352.  
  353.     JMan_Point_Table_Idx++;
  354.  
  355.     if (Read_Line(Stream, Line)) goto Eof;    /* i1 i2 i3    */
  356.     sscanf(Line, "%d %d %d", &i1, &i2, &i3);
  357.     
  358.     if ((i1 != 0 && i1 != 1 && i1 != 4 && i1 != 5) ||
  359.     (i2 != 8) ||
  360.     (i3 != 0 && i3 != 1)) {
  361.  
  362.     sprintf(Error_Msg, "Format error in line \n'%s'", Line);
  363.     Display_Message(Error_Msg);
  364.     return(TRUE);
  365.  
  366.     } /* if */
  367.  
  368.     if (i1 & 4) Spline_Loop(Spline, TRUE);
  369.  
  370.     if (Read_Line(Stream, Line)) goto Eof;    /* Pos or id        */
  371.     if (i3 == 0) {
  372.     sscanf(Line, "%lf %lf %lf",&X, &Y, &Z);
  373.  
  374.     if (*Nbr_Points >= Max_Nbr_Points - 1) {
  375.         Display_Message("Too many points");
  376.         return(TRUE);
  377.     } /* if */
  378.  
  379.     Points[*Nbr_Points].Reference_Count  = 0;
  380.     Points[*Nbr_Points].Flags            = 0;
  381.     Points[*Nbr_Points].Pos[0]           = X;
  382.     Points[*Nbr_Points].Pos[1]           = Y;
  383.     Points[*Nbr_Points].Pos[2]           = Z;
  384.  
  385.     Idx = JMan_Point_Table_Idx;
  386.     JMan_Point_Table[Idx] = *Nbr_Points;
  387.     *Nbr_Points += 1;
  388.  
  389.     } else {
  390.  
  391.     sscanf(Line, "%d",&Idx);
  392.     JMan_Point_Table[JMan_Point_Table_Idx] = -Idx;
  393.  
  394.     if (Idx < 1 || Idx >= Size_JMan_Point_Table) {
  395.         sprintf(Error_Msg, "Invalid point id %d)", Idx);
  396.         Display_Message(Error_Msg);
  397.         return(TRUE);
  398.     } /* if */
  399.  
  400.     } /* if .. else .. */
  401.     *Knot = Knot_New(Spline, *Knot);
  402.     if (*Knot == NULL) {
  403.     Display_Message("Couldn't allocate memory for new knot");
  404.     return(TRUE);
  405.     } /* if */
  406.  
  407.     (*Knot)->Point_Id   = Idx;
  408.     (*Knot)->Flags      = 0;
  409.  
  410.     if (Read_Line(Stream, Line)) goto Eof;    /* Spline parm 1    */
  411.     sscanf(Line, "%lf %lf %lf",&Alfa1, &Gamma1, &Magnitude1);
  412.  
  413.     if (Read_Line(Stream, Line)) goto Eof;    /* Spline parm 2    */
  414.     sscanf(Line, "%lf %lf %lf",&Alfa2, &Gamma2, &Magnitude2);
  415.  
  416.     if (i1 & 1) Tension     = 0.0;    /* "Smooth"    */
  417.     else    Tension        = 1.0;    /* "Peak"    */
  418.     Bias    = 0.0;
  419.     Continuity    = 0.0;
  420.  
  421.     (*Knot)->Tension    = Tension;
  422.     (*Knot)->Bias         = Bias;
  423.     (*Knot)->Continuity = Continuity;
  424.  
  425.     return(FALSE);
  426.  
  427. Eof:
  428.     Display_Message("Eof before expected");
  429.     fclose(Stream);
  430.     return(TRUE);
  431.  
  432. } /* JMan_Knot_Read */
  433.  
  434. Boolean_T JMan_File_Read(char *Filename)
  435. /************************************************************************/
  436. /*                                    */
  437. /*                                    */
  438. /************************************************************************/
  439. {
  440.     FILE    *Stream;
  441.     char    Line[Buffer_Length+1];
  442.     Spline_T    *Spline;
  443.     Knot_T    *Knot;
  444.     int        Spline_Id;
  445.     int        Knot_Id;
  446.     int        Point_Id;
  447.     int        Nbr_Points;
  448.     int        Nbr_Splines;
  449.     int        Nbr_Knots;
  450.     int        i;
  451.     short    Point_Table[Size_JMan_Point_Table];
  452.  
  453.     Display_Status("Loading Journeyman object...");
  454.     Set_Pointer(TRUE);
  455.  
  456.     for (i = 0; i < Size_JMan_Point_Table; i++) Point_Table[i] = 0;
  457.     JMan_Point_Table_Idx = 0;
  458.     JMan_Point_Table     = Point_Table;
  459.  
  460.     Nbr_Points  = 0;
  461.     Spline    = NULL;
  462.  
  463.     Splines_Init();
  464.  
  465.     Stream = fopen(Filename, "r");
  466.     if (Stream == NULL) {
  467.     Display_Open_Error_Msg(Filename);
  468.         Set_Pointer(FALSE);
  469.     return(TRUE);
  470.     } /* if */
  471.  
  472.     if (JMan_Header_Read(Stream, &Nbr_Splines)) {
  473.  
  474.         Set_Pointer(FALSE);
  475.     fclose(Stream);
  476.         return(TRUE);
  477.  
  478.     } /* if */
  479.  
  480.     for (Spline_Id = 0; Spline_Id < Nbr_Splines; Spline_Id++) {
  481.   
  482.         Spline = Spline_New();
  483.     if (Spline == NULL) {
  484.         Display_Message("Couldn't allocate memory for new spline");
  485.             Set_Pointer(FALSE);
  486.         fclose(Stream);
  487.         Splines_Init();
  488.         return(TRUE);        
  489.     }
  490.     
  491.     Spline->Flags     = 0;
  492.     Spline->Nbr_Knots = 0;
  493.     /* Spline->Loop      = FALSE; */
  494.  
  495.         if (Read_Line(Stream, Line)) goto Eof;
  496.     Nbr_Knots = atoi(Line);
  497.  
  498.     if (Nbr_Knots < 1) {
  499.  
  500.         sprintf(Error_Msg, "Nbr of knots (%s) out of range", Line);
  501.         Display_Message(Error_Msg);
  502.             Set_Pointer(FALSE);
  503.         fclose(Stream);
  504.         Splines_Init();
  505.         return(TRUE);
  506.  
  507.     } /* if */
  508.  
  509.         Knot = NULL;
  510.     for (Knot_Id = 0; Knot_Id < Nbr_Knots; Knot_Id++) {
  511.  
  512.         sprintf(Error_Msg, "Reading spline %d", Spline_Id);
  513.             Display_Status(Error_Msg);
  514.     
  515.         if (JMan_Knot_Read(Stream, Spline, &Knot, &Nbr_Points)) {
  516.  
  517.         fclose(Stream);
  518.         Splines_Init();
  519.                 Set_Pointer(FALSE);
  520.         return(TRUE);
  521.  
  522.         } /* if */
  523.     
  524.     } /* for */
  525.     Spline->Nbr_Knots = Nbr_Knots;
  526.     
  527.     } /* for */
  528.  
  529.     fclose(Stream);
  530.  
  531.     /****************************************************************/
  532.     /*                                */
  533.     /* Now postprocess the data.                    */
  534.     /* Right now the knots points to the JMan_Point_Table, and not    */
  535.     /* to the points, furthermore point reference-counts are wrong    */
  536.     /* So do the following:                        */
  537.     /*                                */
  538.     /* For each knot:                        */
  539.     /*                                */
  540.     /*    Get idx into Jman point table.                */
  541.     /*    get idx to point from JMan point table.            */
  542.     /*    If this idx < 0, then this is itself a reference to the    */
  543.     /*    point table, so fetch this idx from the table.        */
  544.     /*    Continue with this while the idx is < 0.            */
  545.     /*    Now set real point_id in the knot and update the reference*/
  546.     /*    count.                            */
  547.     /*                                */
  548.     /****************************************************************/
  549.     Display_Status("Post Processing data");
  550.  
  551.     for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
  552.        for (Knot_Id = 0, Knot = Spline->First; 
  553.          Knot_Id < Spline->Nbr_Knots; Knot_Id++, Knot = Knot->Next) {
  554.  
  555.  
  556.         /* Get idx into JMan point table */
  557.     
  558.         i = Knot->Point_Id;
  559.         if (i < 1 || i >= Size_JMan_Point_Table) {
  560.         sprintf(Error_Msg, "Unused index (%d) in point table", i);
  561.         Display_Message(Error_Msg);
  562.         Splines_Init();
  563.                 Set_Pointer(FALSE);
  564.         return(TRUE);
  565.         } /* if */
  566.  
  567.         while ( (Point_Id = JMan_Point_Table[i]) < 0) {
  568.  
  569.         i = -Point_Id;
  570.  
  571.             if (i < 1 || i >= Size_JMan_Point_Table) {
  572.             sprintf(Error_Msg, "Unused index (%d) in point table", i);
  573.             Display_Message(Error_Msg);
  574.             Splines_Init();
  575.                     Set_Pointer(FALSE);
  576.             return(TRUE);
  577.             } /* if */
  578.  
  579.         } /* while */
  580.  
  581.         if (Point_Id < 0 || Point_Id > Max_Nbr_Points) {
  582.         sprintf(Error_Msg, "Bad reference (%d) in point table %d", Point_Id, i);
  583.         Display_Message(Error_Msg);
  584.         Splines_Init();
  585.                 Set_Pointer(FALSE);
  586.         return(TRUE);
  587.         } /* if */
  588.  
  589.         Points[Point_Id].Reference_Count++;
  590.         Knot->Point_Id = Point_Id;
  591.  
  592.       } /* for */ 
  593.  
  594.     } /* for */
  595.  
  596.     Display_Status(NULL);
  597.     Set_Pointer(FALSE);
  598.  
  599.     return(FALSE);
  600.  
  601. Eof:
  602.     Display_Status(NULL);
  603.     Display_Message("Eof before expected");
  604.     fclose(Stream);
  605.     Splines_Init();
  606.     Set_Pointer(FALSE);
  607.     return(TRUE);
  608.     
  609.  
  610. } /* JMan_File_Read */
  611.  
  612. Boolean_T Config_File_Write(char *Filename)
  613. /************************************************************************/
  614. /*                                    */
  615. /* Write the config file with the name 'Filename'.            */
  616. /*                                    */
  617. /* Return TRUE in case of error.                    */
  618. /*                                    */
  619. /************************************************************************/
  620. {
  621.     FILE    *Stream;
  622.     char    Line[Buffer_Length+1];
  623.     double    D1, D2, D3;
  624.  
  625.     Stream = fopen(Filename, "w");
  626.     if (Stream == NULL)  {
  627.     Display_Open_Error_Msg(Filename);
  628.     return(TRUE);
  629.     }
  630.     D1 = Delay_Draw_Seconds;
  631.     D2 = Delay_Draw_Micros;
  632.     D3 = D1 + D2 / 1000000.0;
  633.  
  634.     fprintf(Stream, "#\n");
  635.     fprintf(Stream, "#Configuration file for ICoons version 1.0\n");
  636.     fprintf(Stream, "#\n");
  637.     fprintf(Stream, "Delay_Draw        = %lf\n", D3);
  638.  
  639.     fprintf(Stream, "Spline_Resolution = %d\n", Spline_Resolution);
  640.     fprintf(Stream, "Patch_Resolution  = %d\n", Patch_Resolution);
  641.     fprintf(Stream, "Backface_Culling  = %d\n", Backface_Culling ? 'Y' : 'N');
  642.  
  643.     fprintf(Stream, "Grid_Size         = %lf\n", Grid_Size);
  644.     fprintf(Stream, "Grid_Active       = %c\n", Grid_Active ? 'Y' : 'N');
  645.     fprintf(Stream, "Grid_Snap_Active  = %c\n", Grid_Snap_Active ? 'Y' : 'N');
  646.  
  647.     fprintf(Stream, "MQ_Size_KnotInfo  = %d\n", MQ_Size_KnotInfo);
  648.     fprintf(Stream, "MQ_Size_Rotate_P  = %d\n", MQ_Size_Rotate_P);
  649.     fprintf(Stream, "MQ_Size_Rotate_G  = %d\n", MQ_Size_Rotate_G);
  650.     fprintf(Stream, "MQ_Size_Scale_G   = %d\n", MQ_Size_Scale_G);
  651.     fprintf(Stream, "MQ_Size_Move_G    = %d\n", MQ_Size_Move_G);
  652.     fprintf(Stream, "MQ_Size_Move      = %d\n", MQ_Size_Move);
  653.  
  654.     fclose(Stream);
  655.  
  656.     return(FALSE);
  657.  
  658. } /* Config_File_Write */
  659.  
  660. Boolean_T Config_File_Read(char *Filename)
  661. /************************************************************************/
  662. /*                                    */
  663. /* Read the config file with the name 'Filename'.            */
  664. /*                                    */
  665. /* Return TRUE in case of error.                    */
  666. /*                                    */
  667. /************************************************************************/
  668. {
  669.     FILE    *Stream;
  670.     char    Line[Buffer_Length+1];
  671.     char    *Name, *Value;
  672.     double    D1, D2, D3;
  673.     long    L;
  674.  
  675.     Stream = fopen(Filename, "r");
  676.     if (Stream == NULL) {
  677.  
  678.     sprintf(Line, "s:%s", Filename);
  679.  
  680.         Stream = fopen(Line, "r");
  681.         if (Stream == NULL)  {
  682.         Display_Open_Error_Msg(Filename);
  683.         return(TRUE);
  684.     }
  685.  
  686.     } /* if */
  687.  
  688.     while (! Read_Line(Stream, Line)) {
  689.  
  690.     Name = strtok(Line, "=");
  691.     if (Name == NULL) continue;
  692.     Value = strtok(NULL, "\n");
  693.     if (Value == NULL) continue;
  694.     StrTrim(Name, Name);
  695.  
  696.     if (strcmp(Name, "Delay_Draw") == 0) {
  697.  
  698.         D1 = atof(Value);
  699.         if (D1 <= 0.0) continue;
  700.         D3 = modf(D1, &D2);
  701.         Delay_Draw_Seconds = D2;
  702.         Delay_Draw_Micros  = D3 * 1000000.0;
  703.  
  704.     } else if (strcmp(Name, "Spline_Resolution") == 0) {
  705.  
  706.         L = atoi(Value);
  707.         if (L > 0 && L <= Max_Spline_Resolution) Spline_Resolution = L;
  708.  
  709.     } else if (strcmp(Name, "Patch_Resolution") == 0) {
  710.  
  711.         L = atoi(Value);
  712.         if (L > 0 && L <= Max_Patch_Resolution) Patch_Resolution = L;
  713.  
  714.     } else if (strcmp(Name, "Backface_Culling") == 0) {
  715.  
  716.         StrTrim(Value, Value);
  717.         Backface_Culling = (*Value == 'y' || *Value == 'Y');
  718.  
  719.     } else if (strcmp(Name, "Grid_Size") == 0) {
  720.  
  721.         D1 = atof(Value);
  722.         if (D1 > 0.5 && D1 < 500.0) Grid_Size = D1;
  723.  
  724.     } else if (strcmp(Name, "Grid_Active") == 0) {
  725.  
  726.         StrTrim(Value, Value);
  727.         Grid_Active = (*Value == 'y' || *Value == 'Y');
  728.  
  729.     } else if (strcmp(Name, "Grid_Snap_Active") == 0) {
  730.  
  731.         StrTrim(Value, Value);
  732.         Grid_Snap_Active = (*Value == 'y' || *Value == 'Y');
  733.  
  734.     } else if (strcmp(Value, "MQ_Size_KnotInfo") == 0) {
  735.  
  736.         L = atoi(Value);
  737.         if (L >= 0 && L <= 5) MQ_Size_KnotInfo = L;
  738.  
  739.     } else if (strcmp(Value, "MQ_Size_Rotate_P") == 0) {
  740.  
  741.         L = atoi(Value);
  742.         if (L >= 0 && L <= 5) MQ_Size_Rotate_P = L;
  743.  
  744.     } else if (strcmp(Value, "MQ_Size_Rotate_G") == 0) {
  745.  
  746.         L = atoi(Value);
  747.         if (L >= 0 && L <= 5) MQ_Size_Rotate_G = L;
  748.  
  749.     } else if (strcmp(Value, "MQ_Size_Scale_G") == 0) {
  750.  
  751.         L = atoi(Value);
  752.         if (L >= 0 && L <= 5) MQ_Size_Scale_G = L;
  753.  
  754.     } else if (strcmp(Value, "MQ_Size_Move_G") == 0) {
  755.  
  756.         L = atoi(Value);
  757.         if (L >= 0 && L <= 5) MQ_Size_Move_G = L;
  758.  
  759.     } else if (strcmp(Value, "MQ_Size_Move") == 0) {
  760.  
  761.         L = atoi(Value);
  762.         if (L >= 0 && L <= 5) MQ_Size_Move = L;
  763.  
  764.     } /* if .. else .. else .. */
  765.     
  766.     } /* while */
  767.  
  768.     fclose(Stream);
  769.  
  770.     return(FALSE);
  771.  
  772. } /* Config_File_Read */
  773.