]> SALOME platform Git repositories - plugins/ghs3dplugin.git/blob - src/GHS3DPlugin/libmesh5.c
Salome HOME
Increment version number (prepare SALOME version 7.0.0)
[plugins/ghs3dplugin.git] / src / GHS3DPlugin / libmesh5.c
1
2
3 /*----------------------------------------------------------*/
4 /*                                                                                                                      */
5 /*                                              LIBMESH V 5.45                                          */
6 /*                                                                                                                      */
7 /*----------------------------------------------------------*/
8 /*                                                                                                                      */
9 /*      Description:            handle .meshb file format I/O           */
10 /*      Author:                         Loic MARECHAL                                           */
11 /*      Creation date:          feb 16 2007                                                     */
12 /*      Last modification:      feb 08 2011                                                     */
13 /*                                                                                                                      */
14 /*----------------------------------------------------------*/
15
16
17 /*----------------------------------------------------------*/
18 /* Includes                                                                                                     */
19 /*----------------------------------------------------------*/
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stdarg.h>
24 #include <string.h>
25 #include <float.h>
26 #include <math.h>
27 #include <ctype.h>
28 #include "libmesh5.h"
29
30
31 /*----------------------------------------------------------*/
32 /* Defines                                                                                                      */
33 /*----------------------------------------------------------*/
34
35 #define Asc 1
36 #define Bin 2
37 #define MshFil 4
38 #define SolFil 8
39 #define MaxMsh 100
40 #define InfKwd 1
41 #define RegKwd 2
42 #define SolKwd 3
43 #define WrdSiz 4
44 #define BufSiz 10000
45
46
47 /*----------------------------------------------------------*/
48 /* Structures                                                                                           */
49 /*----------------------------------------------------------*/
50
51 typedef struct
52 {
53         int typ, SolSiz, NmbWrd, NmbLin, NmbTyp, TypTab[ GmfMaxTyp ];
54         long pos;
55         char fmt[ GmfMaxTyp*9 ];
56 }KwdSct;
57
58 typedef struct
59 {
60         int dim, ver, mod, typ, cod, pos;
61         long NexKwdPos;
62         KwdSct KwdTab[ GmfMaxKwd + 1 ];
63         FILE *hdl;
64         int *IntBuf;
65         float *FltBuf;
66         unsigned char *buf;
67         char FilNam[ GmfStrSiz ];
68         double DblBuf[1000/8];
69         unsigned char blk[ BufSiz + 1000 ];
70 }GmfMshSct;
71
72
73 /*----------------------------------------------------------*/
74 /* Global variables                                                                                     */
75 /*----------------------------------------------------------*/
76
77 int GmfIniFlg=0;
78 GmfMshSct *GmfMshTab[ MaxMsh + 1 ];
79 char *GmfKwdFmt[ GmfMaxKwd + 1 ][4] = 
80 {       {"Reserved", "", "", ""},
81         {"MeshVersionFormatted", "", "", "i"},
82         {"Reserved", "", "", ""},
83         {"Dimension", "", "", "i"},
84         {"Vertices", "Vertex", "i", "dri"},
85         {"Edges", "Edge", "i", "iii"},
86         {"Triangles", "Triangle", "i", "iiii"},
87         {"Quadrilaterals", "Quadrilateral", "i", "iiiii"},
88         {"Tetrahedra", "Tetrahedron", "i", "iiiii"},
89         {"Prisms", "Prism", "i", "iiiiiii"},
90         {"Hexahedra", "Hexahedron", "i", "iiiiiiiii"},
91         {"IterationsAll", "IterationAll","","i"},
92         {"TimesAll", "TimeAll","","r"},                                 
93         {"Corners", "Corner", "i", "i"},
94         {"Ridges", "Ridge", "i", "i"},
95         {"RequiredVertices", "RequiredVertex", "i", "i"},
96         {"RequiredEdges", "RequiredEdge", "i", "i"},
97         {"RequiredTriangles", "RequiredTriangle", "i", "i"},
98         {"RequiredQuadrilaterals", "RequiredQuadrilateral", "i", "i"},
99         {"TangentAtEdgeVertices", "TangentAtEdgeVertex", "i", "iii"},
100         {"NormalAtVertices", "NormalAtVertex", "i", "ii"},
101         {"NormalAtTriangleVertices", "NormalAtTriangleVertex", "i", "iii"},
102         {"NormalAtQuadrilateralVertices", "NormalAtQuadrilateralVertex", "i", "iiii"},
103         {"AngleOfCornerBound", "", "", "r"},
104         {"TrianglesP2", "TriangleP2", "i", "iiiiiii"},
105         {"EdgesP2", "EdgeP2", "i", "iiii"},
106         {"SolAtPyramids", "SolAtPyramid", "i", "sr"},
107         {"QuadrilateralsQ2", "QuadrilateralQ2", "i", "iiiiiiiiii"},
108         {"ISolAtPyramids", "ISolAtPyramid", "i", "iiiii"},
109         {"Reserved", "", "", ""},
110         {"TetrahedraP2", "TetrahedronP2", "i", "iiiiiiiiiii"},
111         {"Reserved", "", "", ""},
112         {"Reserved", "", "", ""},
113         {"HexahedraQ2", "HexahedronQ2", "i", "iiiiiiiiiiiiiiiiiiiiiiiiiiii"},
114         {"Reserved", "", "", ""},
115         {"Reserved", "", "", ""},
116         {"Reserved", "", "", ""},
117         {"Reserved", "", "", ""},
118         {"Reserved", "", "", ""},
119         {"Reserved", "", "", ""},
120         {"Reserved", "", "", ""},
121         {"Reserved", "", "", ""},
122         {"Reserved", "", "", ""},
123         {"Reserved", "", "", ""},
124         {"Reserved", "", "", ""},
125         {"Reserved", "", "", ""},
126         {"Polyhedra", "Polyhedron", "i", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"},
127         {"Polygons", "Polygon", "", "iiiiiiiii"},
128         {"Reserved", "", "", ""},
129         {"Pyramids", "Pyramid", "i", "iiiiii"},
130         {"BoundingBox", "", "", "drdr"},
131         {"Body","i", "drdrdrdr"},
132         {"PrivateTable", "PrivateTable", "i", "i"},
133         {"Reserved", "", "", ""},
134         {"End", "", "", ""},
135         {"Reserved", "", "", ""},
136         {"Reserved", "", "", ""},
137         {"Reserved", "", "", ""},
138         {"Reserved", "", "", ""},
139         {"Tangents", "Tangent", "i", "dr"},
140         {"Normals", "Normal", "i", "dr"},
141         {"TangentAtVertices", "TangentAtVertex", "i", "ii"},
142         {"SolAtVertices", "SolAtVertex", "i", "sr"},
143         {"SolAtEdges", "SolAtEdge", "i", "sr"},
144         {"SolAtTriangles", "SolAtTriangle", "i", "sr"},
145         {"SolAtQuadrilaterals", "SolAtQuadrilateral", "i", "sr"},
146         {"SolAtTetrahedra", "SolAtTetrahedron", "i", "sr"},
147         {"SolAtPrisms", "SolAtPrism", "i", "sr"},
148         {"SolAtHexahedra", "SolAtHexahedron", "i", "sr"},
149         {"DSolAtVertices", "DSolAtVertex", "i", "sr"},
150         {"ISolAtVertices", "ISolAtVertex", "i", "i"},
151         {"ISolAtEdges", "ISolAtEdge", "i", "ii"},
152         {"ISolAtTriangles", "ISolAtTriangle", "i", "iii"},
153         {"ISolAtQuadrilaterals", "ISolAtQuadrilateral", "i", "iiii"},
154         {"ISolAtTetrahedra", "ISolAtTetrahedron", "i", "iiii"},
155         {"ISolAtPrisms", "ISolAtPrism", "i", "iiiiii"},
156         {"ISolAtHexahedra", "ISolAtHexahedron", "i", "iiiiiiii"},
157         {"Iterations", "","","i"},
158         {"Time", "","","r"},
159         {"Reserved", "","",""}
160  };
161
162
163 /*----------------------------------------------------------*/
164 /* Prototypes of local procedures                                                       */
165 /*----------------------------------------------------------*/
166
167 static void ScaWrd(GmfMshSct *, unsigned char *);
168 static void ScaDblWrd(GmfMshSct *, unsigned char *);
169 static void ScaBlk(GmfMshSct *, unsigned char *, int);
170 static long GetPos(GmfMshSct *);
171 static void RecWrd(GmfMshSct *, unsigned char *);
172 static void RecDblWrd(GmfMshSct *, unsigned char *);
173 static void RecBlk(GmfMshSct *, unsigned char *, int);
174 static void SetPos(GmfMshSct *, long);
175 static int ScaKwdTab(GmfMshSct *);
176 static void ExpFmt(GmfMshSct *, int);
177 static void ScaKwdHdr(GmfMshSct *, int);
178
179
180 /*----------------------------------------------------------*/
181 /* Open a mesh file in read or write mod                                        */
182 /*----------------------------------------------------------*/
183
184 int GmfOpenMesh(const char *FilNam, int mod, ...)
185 {
186         int i, KwdCod, res, *PtrVer, *PtrDim, MshIdx=0;
187         char str[ GmfStrSiz ];
188         va_list VarArg;
189         GmfMshSct *msh;
190
191         if(!GmfIniFlg)
192         {
193                 for(i=0;i<=MaxMsh;i++)
194                         GmfMshTab[i] = NULL;
195
196                 GmfIniFlg = 1;
197         }
198
199         /*---------------------*/
200         /* MESH STRUCTURE INIT */
201         /*---------------------*/
202
203         for(i=1;i<=MaxMsh;i++)
204                 if(!GmfMshTab[i])
205                 {
206                         MshIdx = i;
207                         break;
208                 }
209
210         if( !MshIdx || !(msh = calloc(1, sizeof(GmfMshSct))) )
211                 return(0);
212
213         /* Copy the FilNam into the structure */
214
215         if(strlen(FilNam) + 7 >= GmfStrSiz)
216                 return(0);
217
218         strcpy(msh->FilNam, FilNam);
219
220         /* Store the opening mod (read or write) and guess the filetype (binary or ascii) depending on the extension */
221
222         msh->mod = mod;
223         msh->buf = (void *)msh->DblBuf;
224         msh->FltBuf = (void *)msh->DblBuf;
225         msh->IntBuf = (void *)msh->DblBuf;
226
227         if(strstr(msh->FilNam, ".meshb"))
228                 msh->typ |= (Bin | MshFil);
229         else if(strstr(msh->FilNam, ".mesh"))
230                 msh->typ |= (Asc | MshFil);
231         else if(strstr(msh->FilNam, ".solb"))
232                 msh->typ |= (Bin | SolFil);
233         else if(strstr(msh->FilNam, ".sol"))
234                 msh->typ |= (Asc | SolFil);
235         else
236                 return(0);
237
238         /* Open the file in the required mod and initialyse the mesh structure */
239
240         if(msh->mod == GmfRead)
241         {
242
243                 /*-----------------------*/
244                 /* OPEN FILE FOR READING */
245                 /*-----------------------*/
246
247                 va_start(VarArg, mod);
248                 PtrVer = va_arg(VarArg, int *);
249                 PtrDim = va_arg(VarArg, int *);
250                 va_end(VarArg);
251
252                 /* Create the name string and open the file */
253
254                 if(!(msh->hdl = fopen(msh->FilNam, "rb")))
255                         return(0);
256
257                 /* Read the endian coding tag, the mesh version and the mesh dimension (mandatory kwd) */
258
259                 if(msh->typ & Bin)
260                 {
261                         fread((unsigned char *)&msh->cod, WrdSiz, 1, msh->hdl);
262
263                         if( (msh->cod != 1) && (msh->cod != 16777216) )
264                                 return(0);
265
266                         ScaWrd(msh, (unsigned char *)&msh->ver);
267
268                         if( (msh->ver < 1) || (msh->ver > 3) )
269                                 return(0);
270
271                         if( (msh->ver == 3) && (sizeof(long) == 4) )
272                                 return(0);
273
274                         ScaWrd(msh, (unsigned char *)&KwdCod);
275
276                         if(KwdCod != GmfDimension)
277                                 return(0);
278
279                         GetPos(msh);
280                         ScaWrd(msh, (unsigned char *)&msh->dim);
281                 }
282                 else
283                 {
284                         do
285                         {
286                                 res = fscanf(msh->hdl, "%s", str);
287                         }while( (res != EOF) && strcmp(str, "MeshVersionFormatted") );
288
289                         if(res == EOF)
290                                 return(0);
291
292                         fscanf(msh->hdl, "%d", &msh->ver);
293
294                         if( (msh->ver < 1) || (msh->ver > 3) )
295                                 return(0);
296
297                         do
298                         {
299                                 res = fscanf(msh->hdl, "%s", str);
300                         }while( (res != EOF) && strcmp(str, "Dimension") );
301
302                         if(res == EOF)
303                                 return(0);
304
305                         fscanf(msh->hdl, "%d", &msh->dim);
306                 }
307
308                 if( (msh->dim != 2) && (msh->dim != 3) )
309                         return(0);
310
311                 (*PtrVer) = msh->ver;
312                 (*PtrDim) = msh->dim;
313
314                 /*------------*/
315                 /* KW READING */
316                 /*------------*/
317
318                 /* Read the list of kw present in the file */
319
320                 if(!ScaKwdTab(msh))
321                         return(0);
322
323                 GmfMshTab[ MshIdx ] = msh;
324
325                 return(MshIdx);
326         }
327         else if(msh->mod == GmfWrite)
328         {
329
330                 /*-----------------------*/
331                 /* OPEN FILE FOR WRITING */
332                 /*-----------------------*/
333
334                 msh->cod = 1;
335
336                 /* Check if the user provided a valid version number and dimension */
337
338                 va_start(VarArg, mod);
339                 msh->ver = va_arg(VarArg, int);
340                 msh->dim = va_arg(VarArg, int);
341                 va_end(VarArg);
342
343                 if( (msh->ver < 1) || (msh->ver > 3) )
344                         return(0);
345
346                 if( (msh->ver == 3) && (sizeof(long) == 4) )
347                         return(0);
348
349                 if( (msh->dim != 2) && (msh->dim != 3) )
350                         return(0);
351
352                 /* Create the mesh file */
353
354                 if(!(msh->hdl = fopen(msh->FilNam, "wb")))
355                         return(0);
356
357                 GmfMshTab[ MshIdx ] = msh;
358
359
360                 /*------------*/
361                 /* KW WRITING */
362                 /*------------*/
363
364                 /* Write the mesh version and dimension */
365
366                 if(msh->typ & Asc)
367                 {
368                         fprintf(msh->hdl, "%s %d\n\n", GmfKwdFmt[ GmfVersionFormatted ][0], msh->ver);
369                         fprintf(msh->hdl, "%s %d\n", GmfKwdFmt[ GmfDimension ][0], msh->dim);
370                 }
371                 else
372                 {
373                         RecWrd(msh, (unsigned char *)&msh->cod);
374                         RecWrd(msh, (unsigned char *)&msh->ver);
375                         GmfSetKwd(MshIdx, GmfDimension, 0);
376                         RecWrd(msh, (unsigned char *)&msh->dim);
377                 }
378
379                 return(MshIdx);
380         }
381         else
382                 return(0);
383 }
384
385
386 /*----------------------------------------------------------*/
387 /* Close a meshfile in the right way                                            */
388 /*----------------------------------------------------------*/
389
390 int GmfCloseMesh(int MshIdx)
391 {
392         int res = 1;
393         GmfMshSct *msh;
394
395         if( (MshIdx < 1) || (MshIdx > MaxMsh) )
396                 return(0);
397
398         msh = GmfMshTab[ MshIdx ];
399         RecBlk(msh, msh->buf, 0);
400
401         /* In write down the "End" kw in write mode */
402
403   if(msh->mod == GmfWrite) {
404                 if(msh->typ & Asc)
405                         fprintf(msh->hdl, "\n%s\n", GmfKwdFmt[ GmfEnd ][0]);
406                 else
407                         GmfSetKwd(MshIdx, GmfEnd, 0);
408   }
409
410         /* Close the file and free the mesh structure */
411
412         if(fclose(msh->hdl))
413                 res = 0;
414
415         free(msh);
416         GmfMshTab[ MshIdx ] = NULL;
417
418         return(res);
419 }
420
421
422 /*----------------------------------------------------------*/
423 /* Read the number of lines and set the position to this kwd*/
424 /*----------------------------------------------------------*/
425
426 int GmfStatKwd(int MshIdx, int KwdCod, ...)
427 {
428         int i, *PtrNmbTyp, *PtrSolSiz, *TypTab;
429         GmfMshSct *msh;
430         KwdSct *kwd;
431         va_list VarArg;
432
433         if( (MshIdx < 1) || (MshIdx > MaxMsh) )
434                 return(0);
435
436         msh = GmfMshTab[ MshIdx ];
437
438         if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) )
439                 return(0);
440
441         kwd = &msh->KwdTab[ KwdCod ];
442
443         if(!kwd->NmbLin)
444                 return(0);
445
446         /* Read further arguments if this kw is a sol */
447
448         if(kwd->typ == SolKwd)
449         {
450                 va_start(VarArg, KwdCod);
451
452                 PtrNmbTyp = va_arg(VarArg, int *);
453                 *PtrNmbTyp = kwd->NmbTyp;
454
455                 PtrSolSiz = va_arg(VarArg, int *);
456                 *PtrSolSiz = kwd->SolSiz;
457
458                 TypTab = va_arg(VarArg, int *);
459
460                 for(i=0;i<kwd->NmbTyp;i++)
461                         TypTab[i] = kwd->TypTab[i];
462
463                 va_end(VarArg);
464         }
465
466         return(kwd->NmbLin);
467 }
468
469
470 /*----------------------------------------------------------*/
471 /* Set the current file position to a given kwd                         */
472 /*----------------------------------------------------------*/
473
474 int GmfGotoKwd(int MshIdx, int KwdCod)
475 {
476         GmfMshSct *msh;
477         KwdSct *kwd;
478
479         if( (MshIdx < 1) || (MshIdx > MaxMsh) )
480                 return(0);
481
482         msh = GmfMshTab[ MshIdx ];
483
484         if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) )
485                 return(0);
486
487         kwd = &msh->KwdTab[ KwdCod ];
488
489         if(!kwd->NmbLin)
490                 return(0);
491
492         return(fseek(msh->hdl, kwd->pos, SEEK_SET));
493 }
494
495
496 /*----------------------------------------------------------*/
497 /* Write the kwd and set the number of lines                            */
498 /*----------------------------------------------------------*/
499
500 int GmfSetKwd(int MshIdx, int KwdCod, ...)
501 {
502         int i, NmbLin=0, *TypTab;
503         long CurPos;
504         va_list VarArg;
505         GmfMshSct *msh;
506         KwdSct *kwd;
507
508         if( (MshIdx < 1) || (MshIdx > MaxMsh) )
509                 return(0);
510
511         msh = GmfMshTab[ MshIdx ];
512         RecBlk(msh, msh->buf, 0);
513
514         if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) )
515                 return(0);
516
517         kwd = &msh->KwdTab[ KwdCod ];
518
519         /* Read further arguments if this kw has a header */
520
521         if(strlen(GmfKwdFmt[ KwdCod ][2]))
522         {
523                 va_start(VarArg, KwdCod);
524                 NmbLin = va_arg(VarArg, int);
525
526                 if(!strcmp(GmfKwdFmt[ KwdCod ][3], "sr"))
527                 {
528                         kwd->NmbTyp = va_arg(VarArg, int);
529                         TypTab = va_arg(VarArg, int *);
530
531                         for(i=0;i<kwd->NmbTyp;i++)
532                                 kwd->TypTab[i] = TypTab[i];
533                 }
534
535                 va_end(VarArg);
536         }
537
538         /* Setup the kwd info */
539
540         ExpFmt(msh, KwdCod);
541
542         if(!kwd->typ)
543                 return(0);
544         else if(kwd->typ == InfKwd)
545                 kwd->NmbLin = 1;
546         else
547                 kwd->NmbLin = NmbLin;
548
549         /* Store the next kwd position in binary file */
550
551         if( (msh->typ & Bin) && msh->NexKwdPos )
552         {
553                 CurPos = ftell(msh->hdl);
554                 fseek(msh->hdl, msh->NexKwdPos, SEEK_SET);
555                 SetPos(msh, CurPos);
556                 fseek(msh->hdl, CurPos, SEEK_SET);
557         }
558
559         /* Write the header */
560
561         if(msh->typ & Asc)
562         {
563                 fprintf(msh->hdl, "\n%s\n", GmfKwdFmt[ KwdCod ][0]);
564
565                 if(kwd->typ != InfKwd)
566                         fprintf(msh->hdl, "%d\n", kwd->NmbLin);
567
568                 /* In case of solution field, write the extended header */
569
570                 if(kwd->typ == SolKwd)
571                 {
572                         fprintf(msh->hdl, "%d ", kwd->NmbTyp);
573
574                         for(i=0;i<kwd->NmbTyp;i++)
575                                 fprintf(msh->hdl, "%d ", kwd->TypTab[i]);
576
577                         fprintf(msh->hdl, "\n\n");
578                 }
579         }
580         else
581         {
582                 RecWrd(msh, (unsigned char *)&KwdCod);
583                 msh->NexKwdPos = ftell(msh->hdl);
584                 SetPos(msh, 0);
585
586                 if(kwd->typ != InfKwd)
587                         RecWrd(msh, (unsigned char *)&kwd->NmbLin);
588
589                 /* In case of solution field, write the extended header at once */
590
591                 if(kwd->typ == SolKwd)
592                 {
593                         RecWrd(msh, (unsigned char *)&kwd->NmbTyp);
594
595                         for(i=0;i<kwd->NmbTyp;i++)
596                                 RecWrd(msh, (unsigned char *)&kwd->TypTab[i]);
597                 }
598         }
599         msh->pos = 0;
600         return(kwd->NmbLin);
601 }
602
603
604 /*----------------------------------------------------------*/
605 /* Read a full line from the current kwd                                        */
606 /*----------------------------------------------------------*/
607
608 void GmfGetLin(int MshIdx, int KwdCod, ...)
609 {
610         int i, j;
611         float *FltSolTab;
612         double *DblSolTab;
613         va_list VarArg;
614         GmfMshSct *msh = GmfMshTab[ MshIdx ];
615         KwdSct *kwd = &msh->KwdTab[ KwdCod ];
616
617         /* Start decoding the arguments */
618
619         va_start(VarArg, KwdCod);
620
621         if(kwd->typ != SolKwd)
622         {
623                 if(msh->ver == 1)
624                 {
625                         if(msh->typ & Asc)
626                         {
627                                 for(i=0;i<kwd->SolSiz;i++)
628                                         if(kwd->fmt[i] == 'r')
629                                                 fscanf(msh->hdl, "%f", va_arg(VarArg, float *));
630                                         else
631                                                 fscanf(msh->hdl, "%d", va_arg(VarArg, int *));
632                         }
633                         else
634                         {
635                                 ScaBlk(msh, msh->buf, kwd->SolSiz);
636
637                                 for(i=0;i<kwd->SolSiz;i++)
638                                         if(kwd->fmt[i] == 'r')
639                                                 *(va_arg(VarArg, float *)) = msh->FltBuf[i];
640                                         else
641                                                 *(va_arg(VarArg, int *)) = msh->IntBuf[i];
642                         }
643                 }
644                 else
645                 {
646                         if(msh->typ & Asc)
647                         {
648                                 for(i=0;i<kwd->SolSiz;i++)
649                                         if(kwd->fmt[i] == 'r')
650                                                 fscanf(msh->hdl, "%lf", va_arg(VarArg, double *));
651                                         else
652                                                 fscanf(msh->hdl, "%d", va_arg(VarArg, int *));
653                         }
654                         else
655                                 for(i=0;i<kwd->SolSiz;i++)
656                                         if(kwd->fmt[i] == 'r')
657                                                 ScaDblWrd(msh, (unsigned char *)va_arg(VarArg, double *));
658                                         else
659                                                 ScaWrd(msh, (unsigned char *)va_arg(VarArg, int *));
660                 }
661         }
662         else
663         {
664                 if(msh->ver == 1)
665                 {
666                         FltSolTab = va_arg(VarArg, float *);
667
668                         if(msh->typ & Asc)
669                                 for(j=0;j<kwd->SolSiz;j++)
670                                         fscanf(msh->hdl, "%f", &FltSolTab[j]);
671                         else
672                                 ScaBlk(msh, (unsigned char *)FltSolTab, kwd->NmbWrd);
673                 }
674                 else
675                 {
676                         DblSolTab = va_arg(VarArg, double *);
677
678                         if(msh->typ & Asc)
679                                 for(j=0;j<kwd->SolSiz;j++)
680                                         fscanf(msh->hdl, "%lf", &DblSolTab[j]);
681                         else
682                                 for(j=0;j<kwd->SolSiz;j++)
683                                         ScaDblWrd(msh, (unsigned char *)&DblSolTab[j]);
684                 }
685         }
686
687         va_end(VarArg);
688 }
689
690
691 /*----------------------------------------------------------*/
692 /* Write a full line from the current kwd                                       */
693 /*----------------------------------------------------------*/
694
695 void GmfSetLin(int MshIdx, int KwdCod, ...)
696 {
697         int i, j, pos, *IntBuf;
698         float *FltSolTab;
699         double *DblSolTab, *DblBuf;
700         va_list VarArg;
701         GmfMshSct *msh = GmfMshTab[ MshIdx ];
702         KwdSct *kwd = &msh->KwdTab[ KwdCod ];
703
704         /* Start decoding the arguments */
705
706         va_start(VarArg, KwdCod);
707
708         if(kwd->typ != SolKwd)
709         {
710                 if(msh->ver == 1)
711                 {
712                         if(msh->typ & Asc)
713                         {
714                                 for(i=0;i<kwd->SolSiz;i++)
715                                         if(kwd->fmt[i] == 'r')
716                                                 fprintf(msh->hdl, "%g ", (float)va_arg(VarArg, double));
717                                         else
718                                                 fprintf(msh->hdl, "%d ", va_arg(VarArg, int));
719                         }
720                         else
721                         {
722                                 for(i=0;i<kwd->SolSiz;i++)
723                                         if(kwd->fmt[i] == 'r')
724                                                 msh->FltBuf[i] = va_arg(VarArg, double);
725                                         else
726                                                 msh->IntBuf[i] = va_arg(VarArg, int);
727
728                                 RecBlk(msh, msh->buf, kwd->SolSiz);
729                         }
730                 }
731                 else
732                 {
733                         if(msh->typ & Asc)
734                         {
735                                 for(i=0;i<kwd->SolSiz;i++)
736                                         if(kwd->fmt[i] == 'r')
737                                                 fprintf(msh->hdl, "%.15lg ", va_arg(VarArg, double));
738                                         else
739                                                 fprintf(msh->hdl, "%d ", va_arg(VarArg, int));
740                         }
741                         else
742                         {
743                                 pos = 0;
744
745                                 for(i=0;i<kwd->SolSiz;i++)
746                                         if(kwd->fmt[i] == 'r')
747                                         {
748                                                 DblBuf = (void *)&msh->buf[ pos ];
749                                                 *DblBuf = va_arg(VarArg, double);
750                                                 pos += 8;
751                                         }
752                                         else
753                                         {
754                                                 IntBuf = (void *)&msh->buf[ pos ];
755                                                 *IntBuf = va_arg(VarArg, int);
756                                                 pos += 4;
757                                         }
758                                 RecBlk(msh, msh->buf, kwd->NmbWrd);
759                         }
760                 }
761         }
762         else
763         {
764                 if(msh->ver == 1)
765                 {
766                         FltSolTab = va_arg(VarArg, float *);
767
768                         if(msh->typ & Asc)
769                                 for(j=0;j<kwd->SolSiz;j++)
770                                         fprintf(msh->hdl, "%g ", FltSolTab[j]);
771                         else
772                                 RecBlk(msh, (unsigned char *)FltSolTab, kwd->NmbWrd);
773                 }
774                 else
775                 {
776                         DblSolTab = va_arg(VarArg, double *);
777
778                         if(msh->typ & Asc)
779                                 for(j=0;j<kwd->SolSiz;j++)
780                                         fprintf(msh->hdl, "%.15lg ", DblSolTab[j]);
781                         else
782                                 RecBlk(msh, (unsigned char *)DblSolTab, kwd->NmbWrd);
783                 }
784         }
785
786         va_end(VarArg);
787
788         if(msh->typ & Asc)
789                 fprintf(msh->hdl, "\n");
790 }
791
792
793 /*----------------------------------------------------------*/
794 /* Private procedure for transmesh : copy a whole line          */
795 /*----------------------------------------------------------*/
796
797 void GmfCpyLin(int InpIdx, int OutIdx, int KwdCod)
798 {
799         double d;
800         float f;
801         int i, a;
802         GmfMshSct *InpMsh = GmfMshTab[ InpIdx ], *OutMsh = GmfMshTab[ OutIdx ];
803         KwdSct *kwd = &InpMsh->KwdTab[ KwdCod ];
804
805         for(i=0;i<kwd->SolSiz;i++)
806         {
807                 if(kwd->fmt[i] == 'r')
808                 {
809                         if(InpMsh->ver == 1)
810                         {
811                                 if(InpMsh->typ & Asc)
812                                         fscanf(InpMsh->hdl, "%f", &f);
813                                 else
814                                         ScaWrd(InpMsh, (unsigned char *)&f);
815
816                                 d = f;
817                         }
818                         else
819                         {
820                                 if(InpMsh->typ & Asc)
821                                         fscanf(InpMsh->hdl, "%lf", &d);
822                                 else
823                                         ScaDblWrd(InpMsh, (unsigned char *)&d);
824
825                                 f = (float)d;
826                         }
827
828                         if(OutMsh->ver == 1)
829                                 if(OutMsh->typ & Asc)
830                                         fprintf(OutMsh->hdl, "%g ", f);
831                                 else
832                                         RecWrd(OutMsh, (unsigned char *)&f);
833                         else
834                                 if(OutMsh->typ & Asc)
835                                         fprintf(OutMsh->hdl, "%.15g ", d);
836                                 else
837                                         RecDblWrd(OutMsh, (unsigned char *)&d);
838                 }
839                 else
840                 {
841                         if(InpMsh->typ & Asc)
842                                 fscanf(InpMsh->hdl, "%d", &a);
843                         else
844                                 ScaWrd(InpMsh, (unsigned char *)&a);
845
846                         if(OutMsh->typ & Asc)
847                                 fprintf(OutMsh->hdl, "%d ", a);
848                         else
849                                 RecWrd(OutMsh, (unsigned char *)&a);
850                 }
851         }
852
853         if(OutMsh->typ & Asc)
854                 fprintf(OutMsh->hdl, "\n");
855 }
856
857
858 /*----------------------------------------------------------*/
859 /* Find every kw present in a meshfile                                          */
860 /*----------------------------------------------------------*/
861
862 static int ScaKwdTab(GmfMshSct *msh)
863 {
864         int KwdCod;
865         long  NexPos, CurPos, EndPos;
866         char str[ GmfStrSiz ];
867
868         if(msh->typ & Asc)
869         {
870                 /* Scan each string in the file until the end */
871
872                 while(fscanf(msh->hdl, "%s", str) != EOF)
873                 {
874                         /* Fast test in order to reject quickly the numeric values */
875
876                         if(isalpha(str[0]))
877                         {
878                                 /* Search which kwd code this string is associated with, 
879                                         then get its header and save the curent position in file (just before the data) */
880
881                                 for(KwdCod=1; KwdCod<= GmfMaxKwd; KwdCod++)
882                                         if(!strcmp(str, GmfKwdFmt[ KwdCod ][0]))
883                                         {
884                                                 ScaKwdHdr(msh, KwdCod);
885                                                 break;
886                                         }
887                         }
888                         else if(str[0] == '#')
889                                 while(fgetc(msh->hdl) != '\n');
890                 }
891         }
892         else
893         {
894                 /* Get file size */
895
896                 CurPos = ftell(msh->hdl);
897                 fseek(msh->hdl, 0, SEEK_END);
898                 EndPos = ftell(msh->hdl);
899                 fseek(msh->hdl, CurPos, SEEK_SET);
900
901                 /* Jump through kwd positions in the file */
902
903                 do
904                 {
905                         /* Get the kwd code and the next kwd position */
906
907                         ScaWrd(msh, (unsigned char *)&KwdCod);
908                         NexPos = GetPos(msh);
909
910                         if(NexPos > EndPos)
911                                 return(0);
912
913                         /* Check if this kwd belongs to this mesh version */
914
915                         if( (KwdCod >= 1) && (KwdCod <= GmfMaxKwd) )
916                                 ScaKwdHdr(msh, KwdCod);
917
918                         /* Go to the next kwd */
919
920                         if(NexPos)
921                                 fseek(msh->hdl, NexPos, SEEK_SET);
922                 }while(NexPos && (KwdCod != GmfEnd));
923         }
924
925         return(1);
926 }
927
928
929 /*----------------------------------------------------------*/
930 /* Read and setup the keyword's header                                          */
931 /*----------------------------------------------------------*/
932
933 static void ScaKwdHdr(GmfMshSct *msh, int KwdCod)
934 {
935         int i;
936         KwdSct *kwd = &msh->KwdTab[ KwdCod ];
937
938         if(!strcmp("i", GmfKwdFmt[ KwdCod ][2]))
939         {
940                 if(msh->typ & Asc)
941                         fscanf(msh->hdl, "%d", &kwd->NmbLin);
942                 else
943                         ScaWrd(msh, (unsigned char *)&kwd->NmbLin);
944         }
945         else
946                 kwd->NmbLin = 1;
947
948         if(!strcmp("sr", GmfKwdFmt[ KwdCod ][3]))
949         {
950                 if(msh->typ & Asc)
951                 {
952                         fscanf(msh->hdl, "%d", &kwd->NmbTyp);
953
954                         for(i=0;i<kwd->NmbTyp;i++)
955                                 fscanf(msh->hdl, "%d", &kwd->TypTab[i]);
956                 }
957                 else
958                 {
959                         ScaWrd(msh, (unsigned char *)&kwd->NmbTyp);
960
961                         for(i=0;i<kwd->NmbTyp;i++)
962                                 ScaWrd(msh, (unsigned char *)&kwd->TypTab[i]);
963                 }
964         }
965
966         ExpFmt(msh, KwdCod);
967         kwd->pos = ftell(msh->hdl);
968 }
969
970
971 /*----------------------------------------------------------*/
972 /* Expand the compacted format and compute the line size        */
973 /*----------------------------------------------------------*/
974
975 static void ExpFmt(GmfMshSct *msh, int KwdCod)
976 {
977         int i, j, TmpSiz=0;
978         char chr, *InpFmt = GmfKwdFmt[ KwdCod ][3];
979         KwdSct *kwd = &msh->KwdTab[ KwdCod ];
980
981         /* Set the kwd's type */
982
983         if(!strlen(GmfKwdFmt[ KwdCod ][2]))
984                 kwd->typ = InfKwd;
985         else if(!strcmp(InpFmt, "sr"))
986                 kwd->typ = SolKwd;
987         else
988                 kwd->typ = RegKwd;
989
990         /* Get the solution-field's size */
991
992         if(kwd->typ == SolKwd)
993                 for(i=0;i<kwd->NmbTyp;i++)
994                         switch(kwd->TypTab[i])
995                         {
996                                 case GmfSca    : TmpSiz += 1; break;
997                                 case GmfVec    : TmpSiz += msh->dim; break;
998                                 case GmfSymMat : TmpSiz += (msh->dim * (msh->dim+1)) / 2; break;
999                                 case GmfMat    : TmpSiz += msh->dim * msh->dim; break;
1000                         }
1001
1002         /* Scan each character from the format string */
1003
1004         i = kwd->SolSiz = kwd->NmbWrd = 0;
1005
1006         while(i < strlen(InpFmt))
1007         {
1008                 chr = InpFmt[ i++ ];
1009
1010                 if(chr == 'd')
1011                 {
1012                         chr = InpFmt[i++];
1013
1014                         for(j=0;j<msh->dim;j++)
1015                                 kwd->fmt[ kwd->SolSiz++ ] = chr;
1016                 }
1017                 else if(chr == 's')
1018                 {
1019                         chr = InpFmt[i++];
1020
1021                         for(j=0;j<TmpSiz;j++)
1022                                 kwd->fmt[ kwd->SolSiz++ ] = chr;
1023                 }
1024                 else
1025                         kwd->fmt[ kwd->SolSiz++ ] = chr;
1026         }
1027
1028         for(i=0;i<kwd->SolSiz;i++)
1029                 if(kwd->fmt[i] == 'i')
1030                         kwd->NmbWrd++;
1031                 else if(msh->ver >= 2)
1032                         kwd->NmbWrd += 2;
1033                 else
1034                         kwd->NmbWrd++;
1035 }
1036
1037
1038 /*----------------------------------------------------------*/
1039 /* Read a four bytes word from a mesh file                                      */
1040 /*----------------------------------------------------------*/
1041
1042 static void ScaWrd(GmfMshSct *msh, unsigned char *wrd)
1043 {
1044         unsigned char swp;
1045
1046         fread(wrd, WrdSiz, 1, msh->hdl);
1047
1048         if(msh->cod == 1)
1049                 return;
1050
1051         swp = wrd[3];
1052         wrd[3] = wrd[0];
1053         wrd[0] = swp;
1054
1055         swp = wrd[2];
1056         wrd[2] = wrd[1];
1057         wrd[1] = swp;
1058 }
1059
1060
1061 /*----------------------------------------------------------*/
1062 /* Read an eight bytes word from a mesh file                            */
1063 /*----------------------------------------------------------*/
1064
1065 static void ScaDblWrd(GmfMshSct *msh, unsigned char *wrd)
1066 {
1067         int i;
1068         unsigned char swp;
1069
1070         fread(wrd, WrdSiz, 2, msh->hdl);
1071
1072         if(msh->cod == 1)
1073                 return;
1074
1075         for(i=0;i<4;i++)
1076         {
1077                 swp = wrd[7-i];
1078                 wrd[7-i] = wrd[i];
1079                 wrd[i] = swp;
1080         }
1081 }
1082
1083
1084 /*----------------------------------------------------------*/
1085 /* Read ablock of four bytes word from a mesh file                      */
1086 /*----------------------------------------------------------*/
1087
1088 static void ScaBlk(GmfMshSct *msh, unsigned char *blk, int siz)
1089 {
1090         int i, j;
1091         unsigned char swp, *wrd;
1092
1093         fread(blk, WrdSiz, siz, msh->hdl);
1094
1095         if(msh->cod == 1)
1096                 return;
1097
1098         for(i=0;i<siz;i++)
1099         {
1100                 wrd = &blk[ i * 4 ];
1101
1102                 for(j=0;j<2;j++)
1103                 {
1104                         swp = wrd[ 3-j ];
1105                         wrd[ 3-j ] = wrd[j];
1106                         wrd[j] = swp;
1107                 }
1108         }
1109 }
1110
1111
1112 /*----------------------------------------------------------*/
1113 /* Read a 4 or 8 bytes position in mesh file                            */
1114 /*----------------------------------------------------------*/
1115
1116 static long GetPos(GmfMshSct *msh)
1117 {
1118         int IntVal;
1119         long pos;
1120
1121         if(msh->ver >= 3)
1122                 ScaDblWrd(msh, (unsigned char*)&pos);
1123         else
1124         {
1125                 ScaWrd(msh, (unsigned char*)&IntVal);
1126                 pos = IntVal;
1127         }
1128
1129         return(pos);
1130 }
1131
1132
1133 /*----------------------------------------------------------*/
1134 /* Write a four bytes word to a mesh file                                       */
1135 /*----------------------------------------------------------*/
1136
1137 static void RecWrd(GmfMshSct *msh, unsigned char *wrd)
1138 {
1139         fwrite(wrd, WrdSiz, 1, msh->hdl);
1140 }
1141
1142
1143 /*----------------------------------------------------------*/
1144 /* Write an eight bytes word to a mesh file                                     */
1145 /*----------------------------------------------------------*/
1146
1147 static void RecDblWrd(GmfMshSct *msh, unsigned char *wrd)
1148 {
1149         fwrite(wrd, WrdSiz, 2, msh->hdl);
1150 }
1151
1152
1153 /*----------------------------------------------------------*/
1154 /* Write a block of four bytes word to a mesh file                      */
1155 /*----------------------------------------------------------*/
1156
1157 static void RecBlk(GmfMshSct *msh, unsigned char *blk, int siz)
1158 {
1159         /* Copy this line-block into the main mesh buffer */
1160
1161         if(siz)
1162         {
1163                 memcpy(&msh->blk[ msh->pos ], blk, siz * WrdSiz);
1164                 msh->pos += siz * WrdSiz;
1165         }
1166
1167         /* When the buffer is full or this procedure is called with a 0 size, flush the cache on disk */
1168
1169         if( (msh->pos > BufSiz) || (!siz && msh->pos) )
1170         {
1171                 fwrite(msh->blk, 1, msh->pos, msh->hdl);
1172                 msh->pos = 0;
1173         }
1174 }
1175
1176
1177 /*----------------------------------------------------------*/
1178 /* Read a 4 or 8 bytes position in mesh file                            */
1179 /*----------------------------------------------------------*/
1180
1181 static void SetPos(GmfMshSct *msh, long pos)
1182 {
1183         int IntVal;
1184
1185         if(msh->ver >= 3)
1186                 RecDblWrd(msh, (unsigned char*)&pos);
1187         else
1188         {
1189                 IntVal = pos;
1190                 RecWrd(msh, (unsigned char*)&IntVal);
1191         }
1192 }