]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/gtkgensurf/gensurf.cpp
Merge branch 'TimePath/gtk++' into 'master'
[xonotic/netradiant.git] / contrib / gtkgensurf / gensurf.cpp
1 /*
2    GenSurf plugin for GtkRadiant
3    Copyright (C) 2001 David Hyde, Loki software and qeradiant.com
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #include <gtk/gtk.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 /*
24    #include <string.h>
25    #include <tchar.h>
26    #include <math.h>
27  */
28 #include "gensurf.h"
29
30 char gszAppDir[NAME_MAX];
31 char gszCaption[64];
32 char gszIni[NAME_MAX];
33 char gszHelpFile[NAME_MAX];
34 char gszMapFile[NAME_MAX];
35 char gszVersion[64];
36 double Amplitude;
37 double Roughness;
38 double TexOffset[2];
39 double TexScale[2];
40 double WaveLength;
41 double Hll, Hur, Vll, Vur;
42 double Z00, Z01, Z10, Z11;
43 ELEMENT Vertex[( MAX_ROWS + 1 ) * ( MAX_ROWS + 1 )];
44 int AddHints;
45 int ArghRad2;
46 int AutoOverwrite;
47 int Decimate = 0;
48 int SnapToGrid = 0;           // 0, or the grid size to snap to. // Hydra : snap to grid
49 int FileAppend = 0;
50 int FixBorders;
51 int HideBackFaces = 0;
52 int NH, NV;
53 int NumVerticesSelected;
54 int Plane;
55 int Preview;
56 int RandomSeed = 1;
57 int Skybox;
58 int UseDetail;
59 int UseLadder;
60 int VertexMode = 0;
61 int WaveType;
62 int gNumNodes = 0;
63 int gNumTris = 0;
64 int vid_x, vid_y;
65 int view_x, view_y;
66 int view_cx, view_cy;
67 int UsePatches;
68 int SlantAngle;
69 int GimpHints;
70 int Antialiasing;             // ^Fishman - Antializing for the preview window.
71 int AddTerrainKey;             // ^Fishman - Add terrain key to func_group.
72 int SP;             // ^Fishman - Snap to grid.
73
74 ui::Window g_pWnd{ui::null};        // ghwnd;
75 GtkWidget *g_pRadiantWnd; // ghwnd_main;
76 /*HWND      ghwndAngles;
77  */GtkWidget *g_pWndPreview;
78 GtkWidget *g_pPreviewWidget;
79 MYBITMAP gbmp;
80 NODE      *gNode = (NODE *)NULL;
81 TRI       *gTri = (TRI *)NULL;
82
83 int Game;
84 bounding_box PlayerBox[NUMGAMES] = { {{-16., 16.}, {-16., 16.}, {-24., 32.}},    // Quake2
85                                                                          {{-16., 16.}, {-16., 16.}, {-36., 36.}},    // Half-Life
86                                                                          {{-16., 16.}, {-16., 16.}, {-32., 32.}},    // SiN
87                                                                          {{-16., 16.}, {-16., 16.}, {-24., 32.}},    // Heretic2 (guess)
88                                                                          {{-16., 16.}, {-16., 16.}, {-24., 32.}},    // KingPin (guess)
89                                                                          {{-30., 30.}, {-30., 30.}, {-10.,160.}},    // Genesis3D (no idea)
90                                                                          {{-16., 16.}, {-16., 16.}, {-24., 32.}}};   // Quake3 (not sure)
91 //char      gszOutputDir[NUMGAMES][NAME_MAX];
92 //char      gszTextureDir[NUMGAMES][NAME_MAX];
93 char Texture[NUMGAMES][3][64];
94 //char      pakfile[NUMGAMES][NAME_MAX];
95 //char      lastpakfile[NUMGAMES][NAME_MAX];
96 //int       UsePak[NUMGAMES];
97 //char      GameDir[NUMGAMES][NAME_MAX];
98
99 char GameName[NUMGAMES][16] = {"Quake2", "Half-Life", "SiN", "Heretic2", "Kingpin", "Genesis3D", "Quake3" };
100
101
102 bool GenSurfInit(){
103         strcpy( gszVersion, "1.05" );
104         strcpy( gszCaption, "GtkGenSurf" );
105         if ( strlen( gszVersion ) ) {
106                 strcat( gszCaption, " v" );
107                 strcat( gszCaption, gszVersion );
108         }
109
110         strcpy( gszIni, g_FuncTable.m_pfnProfileGetDirectory() );
111         strcat( gszIni, "gensurf.ini" );
112
113 /*if (g_FuncTable.m_pfnReadProjectKey != NULL)
114    {
115     char *basepath;
116
117     basepath = g_FuncTable.m_pfnReadProjectKey("basepath");
118     if (basepath)
119     {
120       g_strdown (basepath);
121       if (strstr(basepath,"baseq3"))
122         Game = QUAKE3;
123       else if (strstr (basepath,"baseq2"))
124         Game = QUAKE2;
125       else // Gotta have a game, might as well be Quake3
126         Game = QUAKE3;
127     }
128     else
129       Game = QUAKE3;
130    }
131    else */
132         Game = QUAKE3;
133
134
135         if ( g_pWnd == NULL ) {
136                 g_pWnd = create_main_dialog();
137         }
138
139         ReadIniFile( gszIni );
140
141         return true;
142 }
143
144 // Reads default values
145
146 #define OPTS_SECTION "Options"
147
148 void ReadIniFile( const char *file ){
149         char *Text;
150         float x1,x2,x3,x4;
151         int i;
152
153         Text = g_FuncTable.m_pfnProfileLoadString( file, OPTS_SECTION, "Amplitude", "" );
154         if ( strlen( Text ) ) {
155                 Amplitude = atof( Text );
156         }
157         else{
158                 Amplitude = 128;
159         }
160
161         Text = g_FuncTable.m_pfnProfileLoadString( file, OPTS_SECTION, "Roughness", "" );
162         if ( strlen( Text ) ) {
163                 Roughness = atof( Text );
164         }
165         else{
166                 Roughness = 16;
167         }
168
169         Text = g_FuncTable.m_pfnProfileLoadString( file, OPTS_SECTION, "WaveLength", "" );
170         if ( strlen( Text ) ) {
171                 WaveLength = atof( Text );
172         }
173         else{
174                 WaveLength = 1024;
175         }
176
177         Text = g_FuncTable.m_pfnProfileLoadString( file, OPTS_SECTION, "Extents", "" );
178         if ( strlen( Text ) ) {
179                 sscanf( Text,"%f,%f,%f,%f",&x1,&x2,&x3,&x4 );
180                 Hll = x1;
181                 Vll = x2;
182                 Hur = x3;
183                 Vur = x4;
184         }
185         else
186         {
187                 Hll = -512;
188                 Vll = -512;
189                 Hur =  512;
190                 Vur =  512;
191         }
192
193         Text = g_FuncTable.m_pfnProfileLoadString( file, OPTS_SECTION, "CornerValues", "" );
194         if ( strlen( Text ) ) {
195                 sscanf( Text,"%f,%f,%f,%f",&x1,&x2,&x3,&x4 );
196                 Z00 = x1;
197                 Z01 = x2;
198                 Z10 = x3;
199                 Z11 = x4;
200         }
201         else
202         {
203                 Z00 = 0.;
204                 Z01 = 0.;
205                 Z10 = 0.;
206                 Z11 = 0.;
207         }
208
209         Text = g_FuncTable.m_pfnProfileLoadString( file, OPTS_SECTION, "TextureOffset", "" );
210         if ( strlen( Text ) ) {
211                 sscanf( Text,"%f,%f",&x1,&x2 );
212                 TexOffset[0] = x1;
213                 TexOffset[1] = x2;
214         }
215         else
216         {
217                 TexOffset[0] = 0.;
218                 TexOffset[1] = 0.;
219         }
220
221         Text = g_FuncTable.m_pfnProfileLoadString( file, OPTS_SECTION,"TextureScale","" );
222         if ( strlen( Text ) ) {
223                 sscanf( Text,"%f,%f",&x1,&x2 );
224                 TexScale[0] = x1;
225                 TexScale[1] = x2;
226                 if ( TexScale[0] == 0. ) {
227                         TexScale[0] = 1.0;
228                 }
229                 if ( TexScale[1] == 0. ) {
230                         TexScale[1] = 1.0;
231                 }
232         }
233         else
234         {
235                 TexScale[0] = 1.;
236                 TexScale[1] = 1.;
237         }
238
239         NH = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"NH",8 );
240         NH = max( 1,min( NH,MAX_ROWS ) );
241         NV = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"NV",8 );
242         NV = max( 1,min( NV,MAX_ROWS ) );
243
244 //      Decimate   = GetPrivateProfileInt(OPTS_SECTION,"Decimate",0,file);
245 //      Decimate = max(0,min(Decimate,100));
246
247         AddHints          = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"AddHints",0 );
248         ArghRad2          = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"ArghRad2",0 );
249         AutoOverwrite = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"AutoOverwrite",0 );
250         FixBorders        = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"FixBorders",1 );
251         HideBackFaces = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"HideBackFaces",0 );
252         Plane                 = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"Plane",0 );
253         Preview               = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"Preview", 0 );
254         Antialiasing    = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"Antialiasing",0 ); // ^Fishman - Antializing for the preview window.
255         RandomSeed        = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"RandomSeed",1 );
256         Skybox                = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"Skybox",0 );
257         UseDetail         = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"UseDetail",0 );
258         AddTerrainKey   =   g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"AddTerrainKey",0 ); // ^Fishman - Add terrain key to func_group.
259         UseLadder         = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"UseLadder",0 );
260         WaveType          = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"WaveType",0 );
261         vid_x                 = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"vid_x", 0 );
262         vid_y                 = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"vid_y", 0 );
263         view_x                = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"view_x",0 );
264         view_y                = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"view_y",0 );
265         view_cx               = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"view_cx",0 );
266         view_cy               = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"view_cy",0 );
267
268         UsePatches        = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"UsePatches",0 );
269
270         SlantAngle = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"SlantAngle",60 );
271         GimpHints  = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"GimpHints",0 );
272
273         for ( i = 0; i < NUMGAMES; i++ )
274         {
275                 //    strcpy (gszOutputDir[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"OutputDir",""));
276                 strcpy( Texture[i][0], g_FuncTable.m_pfnProfileLoadString( file, GameName[i], "Texture", "" ) );
277                 strcpy( Texture[i][1], g_FuncTable.m_pfnProfileLoadString( file, GameName[i], "Texture2", "" ) );
278                 strcpy( Texture[i][2], g_FuncTable.m_pfnProfileLoadString( file, GameName[i], "Texture3", "" ) );
279                 //    strcpy (gszTextureDir[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"TextureDir",""));
280                 //    UsePak[i] = GetPrivateProfileInt(GameName[i],"UsePak",0);
281                 //    strcpy (pakfile[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"PakFile",""));
282                 //    strcpy (lastpakfile[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"LastPakFile",""));
283                 //    strcpy (GameDir[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"GameDir","\0"));
284         }
285         /*
286            if(!strlen(gszTextureDir[QUAKE2]))
287               strcpy(gszTextureDir[QUAKE2],"c:\\quake2\\baseq2\\textures\\");
288            if(!strlen(gszTextureDir[KINGPIN]))
289               strcpy(gszTextureDir[KINGPIN],"c:\\kingpin\\main\\textures\\");
290          */
291         if ( !strlen( Texture[QUAKE2][0] ) ) {
292                 strcpy( Texture[QUAKE2][0],   "textures/e1u1/grass1_4" );
293         }
294         if ( !strlen( Texture[HALFLIFE][0] ) ) {
295                 strcpy( Texture[HALFLIFE][0], "textures/OUT_GRND1" );
296         }
297         if ( !strlen( Texture[SIN][0] ) ) {
298                 strcpy( Texture[SIN][0],      "textures/generic/floor_organic/fl_grass" );
299         }
300         if ( !strlen( Texture[HERETIC2][0] ) ) {
301                 strcpy( Texture[HERETIC2][0], "textures/canyon/canyon05" );
302         }
303         if ( !strlen( Texture[KINGPIN][0] ) ) {
304                 strcpy( Texture[KINGPIN][0],  "textures/bricks/s_sr_m3" );
305         }
306         if ( !strlen( Texture[GENESIS3D][0] ) ) {
307                 strcpy( Texture[GENESIS3D][0],"textures/rock13" );
308         }
309         if ( !strlen( Texture[QUAKE3][0] ) ) {
310                 strcpy( Texture[QUAKE3][0],   "textures/organics/grass3" );
311         }
312         if ( !strlen( Texture[QUAKE3][1] ) ) {
313                 strcpy( Texture[QUAKE3][1],   "textures/common/caulk" );
314         }
315         strcpy( gbmp.name, g_FuncTable.m_pfnProfileLoadString( file, "Bitmap","Filename","" ) );
316
317
318         gbmp.colors = NULL;
319         if ( strlen( gbmp.name ) ) {
320                 OpenBitmap();
321         }
322
323         strcpy( gbmp.defpath, g_FuncTable.m_pfnProfileLoadString( file, "Bitmap","DefaultPath","" ) );
324
325         Text = g_FuncTable.m_pfnProfileLoadString( file, "Bitmap","BlackValue","" );
326         if ( strlen( Text ) ) {
327                 gbmp.black_value = atof( Text );
328         }
329         else{
330                 gbmp.black_value = 0;
331         }
332
333         Text = g_FuncTable.m_pfnProfileLoadString( file, "Bitmap","WhiteValue","" );
334         if ( strlen( Text ) ) {
335                 gbmp.white_value = atof( Text );
336         }
337         else{
338                 gbmp.white_value = 256.;
339         }
340 }
341
342 /*
343    ============
344    va
345
346    does a varargs printf into a temp buffer, so I don't need to have
347    varargs versions of all text functions.
348    FIXME: make this buffer size safe someday
349    ============
350  */
351 char *va( const char *format, ... ){
352         va_list argptr;
353         static char string[1024];
354
355         va_start( argptr, format );
356         vsprintf( string, format,argptr );
357         va_end( argptr );
358
359         return string;
360 }
361
362
363 // Writes current values to INI file
364 void WriteIniFile( const char *file ){
365         int i;
366
367         g_FuncTable.m_pfnProfileSaveString( file, OPTS_SECTION, "Amplitude",    va( "%g",Amplitude ) );
368         g_FuncTable.m_pfnProfileSaveString( file, OPTS_SECTION, "Roughness",    va( "%g",Roughness ) );
369         g_FuncTable.m_pfnProfileSaveString( file, OPTS_SECTION, "WaveLength",   va( "%g",WaveLength ) );
370         g_FuncTable.m_pfnProfileSaveString( file, OPTS_SECTION, "Extents",      va( "%g,%g,%g,%g",Hll,Vll,Hur,Vur ) );
371         g_FuncTable.m_pfnProfileSaveString( file, OPTS_SECTION, "CornerValues", va( "%g,%g,%g,%g",Z00,Z01,Z10,Z11 ) );
372         g_FuncTable.m_pfnProfileSaveString( file, OPTS_SECTION, "TextureOffset",va( "%g,%g",TexOffset[0],TexOffset[1] ) );
373         g_FuncTable.m_pfnProfileSaveString( file, OPTS_SECTION, "TextureScale", va( "%g,%g",TexScale[0],TexScale[1] ) );
374         g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "NH", NH );
375         g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "NV", NV );
376         g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "AddHints", AddHints );
377         g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "ArghRad2", ArghRad2 );
378         g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "AutoOverwrite", AutoOverwrite );
379         g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "FixBorders", FixBorders );
380         g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "Plane", Plane );
381         g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "Preview", Preview );
382         g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "Antialiasing", Antialiasing ); // ^Fishman - Antializing for the preview window.
383         g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "RandomSeed", RandomSeed );
384         g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "Skybox", Skybox );
385         g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "UseDetail", UseDetail );
386         g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "AddTerrainKey", AddTerrainKey ); // ^Fishman - Add terrain key to func_group.
387         g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "UseLadder", UseLadder );
388         g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "WaveType", WaveType );
389         g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "vid_x", vid_x );
390         g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "vid_y", vid_y );
391         g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "view_x", view_x );
392         g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "view_y", view_y );
393         g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "view_cx", view_cx );
394         g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "view_cy", view_cy );
395         g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "UsePatches", UsePatches );
396         g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "SlantAngle", SlantAngle );
397         for ( i = 0; i < NUMGAMES; i++ )
398         {
399                 g_FuncTable.m_pfnProfileSaveString( file, GameName[i], "Texture",   Texture[i][0] );
400                 g_FuncTable.m_pfnProfileSaveString( file, GameName[i], "Texture2",  Texture[i][1] );
401                 g_FuncTable.m_pfnProfileSaveString( file, GameName[i], "Texture3",  Texture[i][2] );
402         }
403
404         g_FuncTable.m_pfnProfileSaveString( file, "Bitmap", "Filename", gbmp.name );
405         g_FuncTable.m_pfnProfileSaveString( file, "Bitmap", "DefaultPath", gbmp.defpath );
406         g_FuncTable.m_pfnProfileSaveString( file, "Bitmap", "BlackValue", va( "%g",gbmp.black_value ) );
407         g_FuncTable.m_pfnProfileSaveString( file, "Bitmap", "WhiteValue", va( "%g",gbmp.white_value ) );
408 //g_FuncTable.m_pfnProfileSaveString (file, "Formula", "Formula", ExcelFunc );
409 }
410
411 void UpdatePreview( bool DataChange ){
412         if ( g_pWndPreview && gtk_widget_get_visible( g_pWndPreview ) ) {
413                 if ( DataChange ) {
414                         GenerateXYZ();
415                 }
416
417                 gtk_widget_draw( g_pPreviewWidget, NULL );
418         }
419 }
420
421 void SaveSetup( GtkWidget *parent ){
422         const char *name = g_FuncTable.m_pfnFileDialog( parent, false, "Save GenSurf Settings",
423                                                                                                         g_FuncTable.m_pfnProfileGetDirectory() );
424
425         if ( name != NULL ) {
426                 char key[32], text[32];
427                 int i, j;
428
429                 WriteIniFile( name );
430                 g_FuncTable.m_pfnProfileSaveString( name, OPTS_SECTION,"MapFile",gszMapFile );
431                 sprintf( text,"0x%04x",FileAppend );
432                 g_FuncTable.m_pfnProfileSaveString( name, OPTS_SECTION,"Append",text );
433                 sprintf( text,"0x%04x",Decimate );
434                 g_FuncTable.m_pfnProfileSaveString( name, OPTS_SECTION,"Decimate",text );
435                 for ( i = 0; i <= NH; i++ )
436                 {
437                         for ( j = 0; j <= NV; j++ )
438                         {
439                                 if ( xyz[i][j].fixed ) {
440                                         sprintf( key,"I%dJ%d",i,j );
441                                         sprintf( text,"%g %g %g", xyz[i][j].fixed_value, xyz[i][j].range, xyz[i][j].rate );
442                                         g_FuncTable.m_pfnProfileSaveString( name, "FixedPoints",key,text );
443                                 }
444                         }
445                 }
446         }
447 }
448
449 void OpenSetup( GtkWidget *parent, int UseDefaults ){
450         const char *name;
451         char key[32], *text;
452         float value,range,rate;
453         int i, j;
454
455         if ( UseDefaults ) {
456                 name = g_strdup( "plugins/defaults.srf" ); // dummy string
457         }
458         else{
459                 name = g_FuncTable.m_pfnFileDialog( parent, true, "Open GenSurf Settings",
460                                                                                         g_FuncTable.m_pfnProfileGetDirectory() );
461         }
462
463         if ( name != NULL ) {
464                 ReadIniFile( name );
465                 Decimate   = g_FuncTable.m_pfnProfileLoadInt( name, OPTS_SECTION,"Decimate",0 );
466                 Decimate   = max( 0,min( Decimate,100 ) );
467
468                 for ( i = 0; i <= NH; i++ )
469                 {
470                         for ( j = 0; j <= NV; j++ )
471                         {
472                                 sprintf( key,"I%dJ%d",i,j );
473                                 text = g_FuncTable.m_pfnProfileLoadString( name, "FixedPoints", key, "" );
474                                 if ( strlen( text ) ) {
475                                         xyz[i][j].fixed = 1;
476                                         xyz[i][j].rate        = 0.;
477                                         sscanf( text,"%g %g %g",&value,&range,&rate );
478                                         xyz[i][j].fixed_value = value;
479                                         xyz[i][j].range       = range;
480                                         xyz[i][j].rate        = rate;
481                                 }
482                                 else{
483                                         xyz[i][j].fixed = 0;
484                                 }
485                         }
486                 }
487         }
488 }