1 #include "stdafx.h"
2 #include "MASTER.h"
3 #define TECPLOTENGINEMODULE
4 
5 /*
6 ******************************************************************
7 ******************************************************************
8 *******                                                   ********
9 ******  (C) 1988-2010 Tecplot, Inc.                        *******
10 *******                                                   ********
11 ******************************************************************
12 ******************************************************************
13 */
14 
15 #define DATAIO4MODULE
16 #include "GLOBAL.h"
17 #include "TASSERT.h"
18 #include "Q_UNICODE.h"
19 #include "ALLOC.h"
20 
21 #include "AUXDATA.h"
22 #include "DATASET.h"
23 #include "FILESTREAM.h"
24 
25 #if defined TECPLOTKERNEL
26 /* CORE SOURCE CODE REMOVED */
27 #endif
28 
29 #include "GEOM2.h"
30 #include "GEOM.h"
31 #include "INPUT.h"
32 #include "SET.h"
33 #include "TEXT.h"
34 #include "DATAIO4.h"
35 #include "DATASET0.h"
36 
37 #include "CHARTYPE.h"
38 #include "STRUTIL.h"
39 #include "ARRLIST.h"
40 #include "STRLIST.h"
41 #include "Q_MSG.h"
42 
43 #if defined IRIS
44 #include <ieeefp.h>
45 #endif
46 
47 using namespace tecplot::strutil;
48 
49 #if !defined(TECPLOTKERNEL) && defined(MSWIN)
50 # pragma warning(disable : 4244)
51 #endif
52 
53 /*END HEADER*/
54 
55 /*
56  * This module contains mostly low level i/o functions.
57  */
58 
59 #if defined DECALPHA || defined COMPAQALPHA
60 #define _IEEE_FP_INEXACT
61 #define _IEEE_FP
62 #endif
63 
64 #if defined SUN41
65 #define SEEK_SET 0
66 #define SEEK_CUR 1
67 #define SEEK_END 2
68 #endif
69 
70 #if defined TECPLOTKERNEL
71 /* CORE SOURCE CODE REMOVED */
72 #endif
73 
74 /**********************************************************************
75  **********************************************************************
76  **********************        INPUT         **************************
77  **********************************************************************
78  **********************************************************************/
79 
FilterFloatChar(float X)80 static char FilterFloatChar(float X)
81 {
82     char C;
83     if (((X >= 32.0) && (X <= 127.0)) ||
84         ((X >= 160.0) && (X <= 255.0)) ||
85         (X == 0.0))
86         C = (char)X;
87     else
88         C = '?';
89     return (C);
90 }
91 
92 
GetNextValue(FileStream_s * FileStream,FieldDataType_e FieldDataType,double VMin,double VMax,Boolean_t * IsOk)93 double GetNextValue(FileStream_s   *FileStream,
94                     FieldDataType_e FieldDataType,
95                     double          VMin,
96                     double          VMax,
97                     Boolean_t      *IsOk)
98 {
99     double X = 0.0;
100 
101     REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
102     REQUIRE(!(*IsOk) || VALID_FIELD_DATA_TYPE(FieldDataType));
103     REQUIRE(!(*IsOk) || VALID_REF(FileStream));
104 
105     if (*IsOk)
106     {
107         switch (FieldDataType)
108         {
109             case FieldDataType_Float :
110             {
111                 float XX;
112 
113                 *IsOk = (TP_FREAD(&XX, 4, 1, FileStream->File) == 1);
114 
115                 if (!FileStream->IsByteOrderNative)
116                     REVERSE_4_BYTES(&XX);
117 
118                 if (*IsOk)
119                     X = XX;
120                 else
121                     X = 0.0;
122             } break;
123             case FieldDataType_Double :
124             {
125                 double XX;
126 
127                 *IsOk = (TP_FREAD(&XX, sizeof(double), 1, FileStream->File) == 1);
128                 if (!FileStream->IsByteOrderNative)
129                     REVERSE_8_BYTES(&XX);
130 
131                 if (*IsOk)
132                     X = XX;
133                 else
134                     X = 0.0;
135             } break;
136             case FieldDataType_Int32  :
137             {
138                 Int32_t L;
139                 *IsOk = (TP_FREAD(&L, sizeof(Int32_t), 1, FileStream->File) == 1);
140                 if (!FileStream->IsByteOrderNative)
141                     REVERSE_4_BYTES(&L);
142                 if (*IsOk)
143                     X = (double)L;
144             } break;
145             case FieldDataType_Int16  :
146             {
147                 Int16_t S;
148                 *IsOk = (TP_FREAD(&S, sizeof(Int16_t), 1, FileStream->File) == 1);
149                 if (!FileStream->IsByteOrderNative)
150                     REVERSE_2_BYTES(&S);
151                 if (*IsOk)
152                     X = (double)S;
153             } break;
154             case FieldDataType_Byte  :
155             {
156                 Byte_t B;
157                 *IsOk = (TP_FREAD(&B, sizeof(Byte_t), 1, FileStream->File) == 1);
158                 if (*IsOk)
159                     X = (double)B;
160             } break;
161             case FieldDataType_Bit :
162             {
163                 /*
164                  * Important note:
165                  *   Reading bit data a value at a time is only valid for a
166                  *   single bit value. If the file contains a block of more than
167                  *   one bit value and you attempt to read it a bit at a time it
168                  *   will not work as Tecplot does not buffer the read. In order
169                  *   to read a block of bits you must perform a block read.
170                  */
171                 Byte_t B;
172                 *IsOk = (TP_FREAD(&B, sizeof(Byte_t), 1, FileStream->File) == 1);
173                 if (*IsOk)
174                     X = (double)(B & (Byte_t)01);
175             } break;
176             default: CHECK(FALSE); break;
177         }
178 
179         if (*IsOk)
180         {
181             if ((X < VMin) || (X > VMax))
182             {
183                 *IsOk = FALSE;
184             }
185         }
186     }
187 
188     return X;
189 }
190 
191 
GetNextI(FileStream_s * FileStream,Boolean_t * IsOk)192 LgIndex_t GetNextI(FileStream_s *FileStream,
193                    Boolean_t    *IsOk)
194 {
195     LgIndex_t I = 0;
196 
197     REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
198     REQUIRE(!(*IsOk) || (VALID_REF(FileStream) && VALID_REF(FileStream->File)));
199 
200     if (*IsOk)
201     {
202         Int32_t Int32Val;
203         *IsOk = (TP_FREAD((void *) & Int32Val, 4, 1, FileStream->File) == 1);
204         if (!FileStream->IsByteOrderNative)
205             REVERSE_4_BYTES(&Int32Val);
206 
207         I = Int32Val;
208     }
209     return I;
210 }
211 
212 
GetIoFileInt(FileStream_s * FileStream,short Version,LgIndex_t IMin,LgIndex_t IMax,Boolean_t * IsOk)213 LgIndex_t GetIoFileInt(FileStream_s *FileStream,
214                        short         Version,
215                        LgIndex_t     IMin,
216                        LgIndex_t     IMax,
217                        Boolean_t    *IsOk)
218 {
219     LgIndex_t I = 0;
220 
221     REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
222     REQUIRE(!(*IsOk) || (0 < Version && Version <= TecplotBinaryFileVersion));
223     REQUIRE(!(*IsOk) || (VALID_REF(FileStream) && VALID_REF(FileStream->File)));
224     REQUIRE(!(*IsOk) || IMin <= IMax);
225 
226     if (!(*IsOk))
227         return (0);
228 
229     if (Version <= 63)
230     {
231         float  X;
232         if (*IsOk)
233         {
234             X = (float)GetNextValue(FileStream, FieldDataType_Float,
235                                     (double)IMin - 1.0e-10,
236                                     (double)IMax + 1.0e-10, IsOk);
237             if (*IsOk)
238             {
239                 if (ABS(X) < (float)MAXINDEX)
240                     I = (LgIndex_t)X;
241                 else
242                     *IsOk = FALSE;
243             }
244             else
245                 *IsOk = FALSE;
246         }
247     }
248     else
249     {
250         I = GetNextI(FileStream, IsOk);
251     }
252 
253     if ((I < IMin) || (I > IMax))
254         *IsOk = FALSE;
255 
256     return (I);
257 }
258 
259 /**
260  * Basically this is "realloc" but apparently "realloc" doesn't behave reliably
261  * on all platforms.
262  */
ReallocString(char ** String,LgIndex_t NewLength)263 static Boolean_t ReallocString(char      **String,
264                                LgIndex_t NewLength)
265 {
266     Boolean_t IsOk;
267     char *NewString;
268 
269     REQUIRE(VALID_REF(String));
270     REQUIRE(*String == NULL || VALID_REF(*String));
271     REQUIRE((*String != NULL && NewLength >= (LgIndex_t)strlen(*String)) ||
272             (*String == NULL && NewLength >= 0));
273 
274     NewString = ALLOC_ARRAY(NewLength + 1, char, "reallocated string");
275     IsOk = (NewString != NULL);
276     if (IsOk)
277     {
278         if (*String == NULL)
279         {
280             NewString[0] = '\0';
281         }
282         else
283         {
284             strcpy(NewString, *String);
285             FREE_ARRAY(*String, "old string");
286         }
287         *String = NewString;
288     }
289 
290     ENSURE(VALID_BOOLEAN(IsOk));
291     ENSURE(IMPLICATION(IsOk, VALID_REF(*String)));
292     return IsOk;
293 }
294 
295 
296 /**
297  * Reads a string from all versions of a binary plt file.
298  *
299  * param FileStream
300  *     Open file stream positioned at the string to read.
301  * param IVersion
302  *     Binary file version number.
303  * param MaxCharacters
304  *     IVersion < 63
305  *       This value is exactly the number of characters (actually floats, each
306  *       one representing a character's ordinal value) to read from the file.
307  *     IVersion >= 63 and ProcessData == TRUE
308  *       If non-zero, this value represents the largest string to be returned.
309  *       In other words, larger strings are read from the file but an allocated
310  *       string of up to MaxCharacters is returned. A zero value indicates that
311  *       the string size is unlimited and determined only by the actual length
312  *       of the string in the file.
313  * param TargetStr
314  *     Pointer to hold the allocated string if ProcessData == TRUE.
315  * param ProcessData
316  *     Indicates if the read string should be retrieved.
317  *
318  * return
319  *     TRUE if the read was successful with an allocated string *TargetStr
320  *     containing the string read (no larger than requested or necessary),
321  *     FALSE otherwise.
322  */
ReadInString(FileStream_s * FileStream,short IVersion,int MaxCharacters,char ** TargetStr,Boolean_t ProcessData)323 Boolean_t ReadInString(FileStream_s  *FileStream,
324                        short          IVersion,
325                        int            MaxCharacters,
326                        char         **TargetStr,
327                        Boolean_t      ProcessData)
328 {
329     Boolean_t IsOk = TRUE;
330 
331     REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
332     REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion);
333     REQUIRE(IMPLICATION(IVersion < 63 || ProcessData, MaxCharacters >= 0));
334     REQUIRE(IMPLICATION(ProcessData, VALID_REF(TargetStr)));
335     REQUIRE(VALID_BOOLEAN(ProcessData));
336 
337     if (IVersion < 63)
338     {
339         /*
340          *  One word per character.  Read Exactly "MaxCharacters" number of words.
341          */
342         float X;
343 
344         if (ProcessData)
345         {
346             *TargetStr = ALLOC_ARRAY(MaxCharacters + 1, char, "target string");
347             IsOk = (*TargetStr != NULL);
348         }
349 
350         if (IsOk)
351         {
352             LgIndex_t I;
353             for (I = 0; IsOk && I < MaxCharacters; I++)
354             {
355                 X = (float)GetNextValue(FileStream, FieldDataType_Float, 0.0, 127.0, &IsOk);
356                 if (!IsOk)
357                     break;
358                 if (ProcessData)
359                     (*TargetStr)[I] = FilterFloatChar(X);
360             }
361             if (ProcessData)
362                 (*TargetStr)[I] = '\0';
363         }
364         else
365         {
366             ErrMsg(translate("Cannot allocate memory for string during read",
367                              "'string' meaning the computer science data type"));
368         }
369     }
370     else
371     {
372 #define      MAX_STRBUFFER_LEN 4095
373         static char StrBuffer[MAX_STRBUFFER_LEN+1];
374         LgIndex_t   StrBufferLen = 0;
375         LgIndex_t   TargetStrLen = 0;
376         LgIndex_t   I = 0;
377         LgIndex_t   CharValue = 0;
378 
379         if (ProcessData)
380             *TargetStr = NULL;
381 
382         do
383         {
384             CharValue = GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk);
385             if (IsOk && ProcessData)
386             {
387                 /*
388                  * if the limit is not exceded, stuff the
389                  * character into the buffer
390                  */
391                 if (CharValue != '\0' &&
392                     (I < MaxCharacters || MaxCharacters == 0))
393                 {
394                     StrBuffer[StrBufferLen] = (char)CharValue;
395                     StrBufferLen++;
396                 }
397 
398                 if (CharValue == '\0' ||
399                     StrBufferLen == MAX_STRBUFFER_LEN)
400                 {
401                     if (StrBufferLen != 0 || *TargetStr == NULL)
402                     {
403                         StrBuffer[StrBufferLen] = '\0';
404                         TargetStrLen += StrBufferLen;
405                         IsOk = ReallocString(TargetStr, TargetStrLen);
406                         if (IsOk)
407                             strcat(*TargetStr, StrBuffer);
408                         StrBufferLen = 0; /* reset the string buffer */
409                     }
410                 }
411             }
412 
413             I++;
414         }
415         while (IsOk && (char)CharValue != '\0');
416 
417         /* if we failed cleanup if necessary */
418         if (!IsOk       &&
419             ProcessData &&
420             *TargetStr != NULL)
421         {
422             FREE_ARRAY(*TargetStr, "failed read string");
423             *TargetStr = NULL;
424         }
425     }
426 
427     ENSURE(IMPLICATION(ProcessData,
428                        (VALID_REF(*TargetStr) || *TargetStr == NULL)));
429     ENSURE(VALID_BOOLEAN(IsOk));
430     return (IsOk);
431 }
432 
433 /**
434  */
ReadDoubleBlock(FileStream_s * FileStream,Boolean_t DoRead,double * Buffer,LgIndex_t StartIndex,LgIndex_t NumValues,Boolean_t * IsOk)435 static void ReadDoubleBlock(FileStream_s *FileStream,
436                             Boolean_t     DoRead,
437                             double       *Buffer,
438                             LgIndex_t     StartIndex,
439                             LgIndex_t     NumValues,
440                             Boolean_t    *IsOk)
441 {
442     if (DoRead)
443     {
444         double *DPtr = Buffer + StartIndex;
445         *IsOk = (TP_FREAD(DPtr, sizeof(double), NumValues, FileStream->File) == (size_t)NumValues);
446         if (!FileStream->IsByteOrderNative && *IsOk)
447         {
448             LgIndex_t N;
449             for (N = 0; N < NumValues; N++)
450                 REVERSE_8_BYTES(&DPtr[N]);
451         }
452     }
453     else
454         *IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(double), SEEK_CUR) == 0);
455 }
456 
457 /**
458  */
ReadFloatBlock(FileStream_s * FileStream,Boolean_t DoRead,float * Buffer,LgIndex_t StartIndex,LgIndex_t NumValues,Boolean_t * IsOk)459 static void ReadFloatBlock(FileStream_s *FileStream,
460                            Boolean_t     DoRead,
461                            float        *Buffer,
462                            LgIndex_t     StartIndex,
463                            LgIndex_t     NumValues,
464                            Boolean_t    *IsOk)
465 {
466     if (DoRead)
467     {
468         float *FPtr = Buffer + StartIndex;
469         *IsOk = (TP_FREAD(FPtr, sizeof(float), NumValues, FileStream->File) == (size_t)NumValues);
470         if (!FileStream->IsByteOrderNative && *IsOk)
471         {
472             LgIndex_t N;
473             for (N = 0; N < NumValues; N++)
474                 REVERSE_4_BYTES(&FPtr[N]);
475         }
476     }
477     else
478         *IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(float), SEEK_CUR) == 0);
479 }
480 
481 
482 /**
483  */
ReadBitBlock(FileStream_s * FileStream,Boolean_t DoRead,Byte_t * Buffer,LgIndex_t NumValues,Boolean_t * IsOk)484 static void ReadBitBlock(FileStream_s *FileStream,
485                          Boolean_t     DoRead,
486                          Byte_t       *Buffer,
487                          LgIndex_t     NumValues,
488                          Boolean_t    *IsOk)
489 {
490     /*
491      * Do not allow reading of bit values if startindex is not 0.
492      * (This means geometries cannot use bit data.
493      */
494     LgIndex_t NumBytes = (NumValues + 7) / 8;
495     if (DoRead)
496     {
497         *IsOk = (TP_FREAD(Buffer,
498                           sizeof(Byte_t),
499                           NumBytes,
500                           FileStream->File) == (size_t)NumBytes);
501     }
502     else
503         *IsOk = (TP_FSEEK(FileStream->File, NumBytes * sizeof(Byte_t), SEEK_CUR) == 0);
504 }
505 
506 /**
507  */
ReadByteBlock(FileStream_s * FileStream,Boolean_t DoRead,Byte_t * Buffer,HgIndex_t StartIndex,HgIndex_t NumValues,Boolean_t * IsOk)508 void ReadByteBlock(FileStream_s *FileStream,
509                    Boolean_t     DoRead,
510                    Byte_t       *Buffer,
511                    HgIndex_t     StartIndex,
512                    HgIndex_t     NumValues,
513                    Boolean_t    *IsOk)
514 {
515     if (DoRead)
516     {
517         *IsOk = (TP_FREAD(Buffer + StartIndex,
518                           sizeof(Byte_t),
519                           NumValues,
520                           FileStream->File) == (size_t)NumValues);
521     }
522     else
523         *IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(Byte_t), SEEK_CUR) == 0);
524 }
525 
526 
527 /**
528  */
ReadInt16Block(FileStream_s * FileStream,Boolean_t DoRead,Int16_t * Buffer,HgIndex_t StartIndex,HgIndex_t NumValues,Boolean_t * IsOk)529 void ReadInt16Block(FileStream_s *FileStream,
530                     Boolean_t     DoRead,
531                     Int16_t      *Buffer,
532                     HgIndex_t     StartIndex,
533                     HgIndex_t     NumValues,
534                     Boolean_t    *IsOk)
535 {
536     if (DoRead)
537     {
538         Int16_t *IntPtr = Buffer + StartIndex;
539         *IsOk = (TP_FREAD(IntPtr,
540                           sizeof(Int16_t),
541                           NumValues,
542                           FileStream->File) == (size_t)NumValues);
543 
544         if (!FileStream->IsByteOrderNative && *IsOk)
545         {
546             LgIndex_t N;
547             for (N = 0; N < NumValues; N++)
548                 REVERSE_2_BYTES(&IntPtr[N]);
549         }
550     }
551     else
552         *IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(Int16_t), SEEK_CUR) == 0);
553 }
554 
555 /**
556  */
ReadInt16BlockToInt32(FileStream_s * FileStream,Boolean_t DoRead,Int32_t * Buffer,HgIndex_t StartIndex,HgIndex_t NumValues,Boolean_t * IsOk)557 void ReadInt16BlockToInt32(FileStream_s *FileStream,
558                            Boolean_t     DoRead,
559                            Int32_t      *Buffer,
560                            HgIndex_t     StartIndex,
561                            HgIndex_t     NumValues,
562                            Boolean_t    *IsOk)
563 {
564     REQUIRE(VALID_REF(FileStream));
565     REQUIRE(VALID_BOOLEAN(DoRead));
566     REQUIRE(VALID_REF(Buffer));
567     REQUIRE(StartIndex >= 0);
568     REQUIRE(NumValues >= 0);
569     REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
570 
571     if (DoRead)
572     {
573         HgIndex_t EndIndex = StartIndex + NumValues;
574         for (HgIndex_t ValueIndex = StartIndex; *IsOk && ValueIndex < EndIndex; ValueIndex++)
575         {
576             Int16_t Value;
577             *IsOk = (TP_FREAD(&Value, sizeof(Int16_t), 1, FileStream->File) == 1);
578             if (!FileStream->IsByteOrderNative && *IsOk)
579                 REVERSE_2_BYTES(&Value);
580             Buffer[ValueIndex] = (Int32_t)Value;
581         }
582     }
583     else
584         *IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(Int16_t), SEEK_CUR) == 0);
585 }
586 
587 /**
588  */
ReadInt32Block(FileStream_s * FileStream,Boolean_t DoRead,Int32_t * Buffer,HgIndex_t StartIndex,HgIndex_t NumValues,Boolean_t * IsOk)589 void ReadInt32Block(FileStream_s *FileStream,
590                     Boolean_t     DoRead,
591                     Int32_t      *Buffer,
592                     HgIndex_t     StartIndex,
593                     HgIndex_t     NumValues,
594                     Boolean_t    *IsOk)
595 {
596     if (DoRead)
597     {
598         Int32_t *IntPtr = Buffer + StartIndex;
599         *IsOk = (TP_FREAD(IntPtr,
600                           sizeof(Int32_t),
601                           NumValues,
602                           FileStream->File) == (size_t)NumValues);
603 
604         if (!FileStream->IsByteOrderNative && *IsOk)
605         {
606             LgIndex_t N;
607             for (N = 0; N < NumValues; N++)
608                 REVERSE_4_BYTES(&IntPtr[N]);
609         }
610     }
611     else
612         *IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(Int32_t), SEEK_CUR) == 0);
613 }
614 
615 /**
616  */
ReadPureBlock(FileStream_s * FileStream,Boolean_t DoRead,void * Buffer,FieldDataType_e FieldDataType,HgIndex_t StartIndex,HgIndex_t NumValues,Boolean_t * IsOk)617 void ReadPureBlock(FileStream_s   *FileStream,
618                    Boolean_t       DoRead,
619                    void           *Buffer,
620                    FieldDataType_e FieldDataType,
621                    HgIndex_t       StartIndex,
622                    HgIndex_t       NumValues,
623                    Boolean_t      *IsOk)
624 {
625     REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
626     REQUIRE(VALID_BOOLEAN(DoRead));
627     REQUIRE(!DoRead || VALID_REF(Buffer));
628     REQUIRE(VALID_FIELD_DATA_TYPE(FieldDataType));
629     REQUIRE(StartIndex >= 0);
630     REQUIRE(NumValues >= 0);
631     REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
632 
633     switch (FieldDataType)
634     {
635         case FieldDataType_Float :
636         {
637             ReadFloatBlock(FileStream,
638                            DoRead,
639                            (float *)Buffer,
640                            StartIndex,
641                            NumValues,
642                            IsOk);
643         } break;
644         case FieldDataType_Double :
645         {
646             ReadDoubleBlock(FileStream,
647                             DoRead,
648                             (double *)Buffer,
649                             StartIndex,
650                             NumValues,
651                             IsOk);
652         } break;
653         case FieldDataType_Bit :
654         {
655             if (StartIndex != 0)
656             {
657                 ErrMsg(translate("Internal Error: Attempt to read bit data at non-zero offset",
658                                  "see Tecplot User's manual for a definition of 'bit' data"));
659                 *IsOk = FALSE;
660             }
661             else
662                 ReadBitBlock(FileStream,
663                              DoRead,
664                              (Byte_t *)Buffer,
665                              NumValues,
666                              IsOk);
667         } break;
668         case FieldDataType_Byte :
669         {
670             ReadByteBlock(FileStream,
671                           DoRead,
672                           (Byte_t *)Buffer,
673                           StartIndex,
674                           NumValues,
675                           IsOk);
676         } break;
677         case FieldDataType_Int16 :
678         {
679             ReadInt16Block(FileStream,
680                            DoRead,
681                            (Int16_t *)Buffer,
682                            StartIndex,
683                            NumValues,
684                            IsOk);
685         } break;
686         case FieldDataType_Int32 :
687         {
688             ReadInt32Block(FileStream,
689                            DoRead,
690                            (Int32_t *)Buffer,
691                            StartIndex,
692                            NumValues,
693                            IsOk);
694         } break;
695         case FieldDataType_IJKFunction : /* Not used yet */
696         case FieldDataType_Int64 :       /* Not used yet */
697         default: CHECK(FALSE); break;
698     }
699     ENSURE(VALID_BOOLEAN(*IsOk));
700 }
701 
702 /**
703  */
ReadBlock(FileStream_s * FileStream,FieldData_pa FieldData,Boolean_t DoRead,FieldDataType_e FieldDataTypeInFile,HgIndex_t StartIndex,HgIndex_t EndIndex,Boolean_t * IsOk)704 void ReadBlock(FileStream_s   *FileStream,
705                FieldData_pa    FieldData,
706                Boolean_t       DoRead,
707                FieldDataType_e FieldDataTypeInFile,
708                HgIndex_t       StartIndex,
709                HgIndex_t       EndIndex,
710                Boolean_t      *IsOk)
711 {
712     REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
713     REQUIRE(IMPLICATION(IsOk, VALID_REF(FileStream)));
714     REQUIRE(IMPLICATION(IsOk, VALID_FIELD_DATA_TYPE(FieldDataTypeInFile)));
715     REQUIRE(VALID_BOOLEAN(DoRead));
716     REQUIRE(IMPLICATION(DoRead, VALID_REF(FieldData)));
717 
718     /*
719      * Bit data is packed into bytes. Since Tecplot doesn't buffer reads it can
720      * not perform bit by bit value reads and therefore must only perform block
721      * reads of bit data.
722      */
723     Boolean_t ReadByBlock = IMPLICATION(DoRead, GetFieldDataType(FieldData) == FieldDataTypeInFile);
724     REQUIRE(ReadByBlock || (FieldDataTypeInFile != FieldDataType_Bit));
725 
726     if (*IsOk)
727     {
728         LgIndex_t NumValues = EndIndex - StartIndex + 1;
729         if (ReadByBlock)
730         {
731             void *data_array;
732             if (DoRead)
733                 data_array = GetFieldDataVoidPtr(FieldData);
734             else
735                 data_array = NULL;
736             ReadPureBlock(FileStream,
737                           DoRead,
738                           data_array,
739                           FieldDataTypeInFile,
740                           StartIndex,
741                           NumValues,
742                           IsOk);
743         }
744         else
745         {
746             LgIndex_t N;
747             for (N = 0; *IsOk && (N < NumValues); N++)
748             {
749                 double D = GetNextValue(FileStream, FieldDataTypeInFile, -LARGEDOUBLE, LARGEDOUBLE, IsOk);
750                 if (DoRead)
751                     SetFieldValue(FieldData, N + StartIndex, D);
752             }
753         }
754     }
755 }
756 
757 /**
758  */
ReadClassicOrderedCCBlock(FileStream_s * DataFileStream,FieldData_pa FieldData,FieldDataType_e FieldDataTypeInFile,LgIndex_t NumIPtsInFile,LgIndex_t NumJPtsInFile,LgIndex_t NumKPtsInFile,Boolean_t * IsOk)759 void ReadClassicOrderedCCBlock(FileStream_s         *DataFileStream,
760                                FieldData_pa          FieldData,
761                                FieldDataType_e       FieldDataTypeInFile,
762                                LgIndex_t             NumIPtsInFile,
763                                LgIndex_t             NumJPtsInFile,
764                                LgIndex_t             NumKPtsInFile,
765                                Boolean_t            *IsOk)
766 {
767     REQUIRE(IMPLICATION(*IsOk, VALID_REF(DataFileStream)));
768     REQUIRE(IMPLICATION(*IsOk, VALID_FIELD_DATA_TYPE(FieldDataTypeInFile)));
769     REQUIRE(VALID_REF(FieldData));
770     REQUIRE(NumIPtsInFile >= 0);
771     REQUIRE(NumJPtsInFile >= 0);
772     REQUIRE(NumKPtsInFile >= 0);
773     REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
774 
775     if (*IsOk)
776     {
777         LgIndex_t J, K;
778         LgIndex_t NumIJPts  = NumIPtsInFile * NumJPtsInFile;
779         LgIndex_t IEnd      = MAX(NumIPtsInFile - 1, 1);
780         LgIndex_t JEnd      = MAX(NumJPtsInFile - 1, 1);
781         LgIndex_t KEnd      = MAX(NumKPtsInFile - 1, 1);
782         LgIndex_t NumValues = (IEnd * JEnd * KEnd);
783         Boolean_t IsLinear  = ((NumJPtsInFile == 1 && NumKPtsInFile == 1) ||
784                                (NumIPtsInFile == 1 && NumKPtsInFile == 1) ||
785                                (NumIPtsInFile == 1 && NumJPtsInFile == 1));
786         if (IsLinear)
787             ReadBlock(DataFileStream, FieldData, TRUE, FieldDataTypeInFile,
788                       0, NumValues - 1, IsOk);
789         else
790             for (K = 0; K < KEnd && IsOk; K++)
791                 for (J = 0; J < JEnd && IsOk; J++)
792                 {
793                     LgIndex_t CellIndex = 0 + (J * NumIPtsInFile) + (K * NumIJPts);
794                     ReadBlock(DataFileStream, FieldData, TRUE, FieldDataTypeInFile,
795                               CellIndex, CellIndex + IEnd - 1, IsOk);
796                 }
797     }
798 
799     ENSURE(VALID_BOOLEAN(*IsOk));
800 }
801 
802 /**
803  */
AdjustCustomColor(short IVersion,ColorIndex_t * BColor)804 static void AdjustCustomColor(short         IVersion,
805                               ColorIndex_t *BColor)
806 {
807     REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion);
808     REQUIRE(VALID_REF(BColor));
809 
810     if ((IVersion < 70) && (*BColor >= 15) && (*BColor <= 22))
811         *BColor -= 7;
812 }
813 
814 
815 /*
816  * ReadInDataFileTypeTitleAndVarNames replaces ReadInDataFileTitleAndVarNames
817  * and reads in the filetype as well in files with version >= 109.
818  */
ReadInDataFileTypeTitleAndVarNames(FileStream_s * FileStream,short IVersion,char ** DataSetTitle,DataFileType_e * FileType,int * NumVars,StringList_pa * VarNames)819 Boolean_t ReadInDataFileTypeTitleAndVarNames(FileStream_s   *FileStream,
820                                              short           IVersion,
821                                              char          **DataSetTitle,
822                                              DataFileType_e *FileType,
823                                              int            *NumVars,
824                                              StringList_pa  *VarNames)
825 {
826     EntIndex_t   CurVar;
827     Boolean_t    IsOk = TRUE;
828 
829     REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
830     REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion);
831     REQUIRE(VALID_REF(DataSetTitle) || (DataSetTitle == NULL));
832     REQUIRE(VALID_REF(FileType) || (FileType == NULL));
833     REQUIRE(VALID_REF(NumVars));
834     REQUIRE(VALID_REF(VarNames) || (VarNames == NULL));
835 
836     *NumVars      = 0;
837     if (DataSetTitle)
838         *DataSetTitle = NULL;
839     if (IVersion >= 109)
840     {
841         if (FileType)
842             *FileType = (DataFileType_e)GetIoFileInt(FileStream,
843                                                      IVersion,
844                                                      0,
845                                                      DataFileType_Solution,
846                                                      &IsOk);
847         else
848             GetIoFileInt(FileStream,
849                          IVersion,
850                          0,
851                          DataFileType_Solution,
852                          &IsOk);
853     }
854     if (ReadInString(FileStream,
855                      IVersion,
856                      ((IVersion < 63) ? 80 : MaxChrsDatasetTitle),
857                      DataSetTitle,
858                      (Boolean_t)(DataSetTitle != NULL)))
859     {
860         if (DataSetTitle)
861             TrimLeadAndTrailSpaces(*DataSetTitle);
862         *NumVars = GetIoFileInt(FileStream, IVersion, 0, MAXZONEMAP, &IsOk);
863     }
864     else
865         IsOk = FALSE;
866 
867     if (IsOk && (*NumVars > MaxNumZonesOrVars))
868     {
869         ErrMsg(translate("Too many variables"));
870         IsOk = FALSE;
871     }
872 
873     if (IsOk && VarNames)
874     {
875         if (*NumVars > 0)
876         {
877             /* allocate a string list filled with NULL's */
878             *VarNames = StringListAlloc();
879             IsOk = (*VarNames != NULL);
880             if (IsOk)
881                 IsOk = StringListSetString(*VarNames, *NumVars - 1, NULL);
882 
883             if (!IsOk)
884             {
885                 if (*VarNames != NULL)
886                     StringListDealloc(VarNames);
887                 ErrMsg(translate("Out of space while allocating var names"));
888             }
889         }
890     }
891 
892     for (CurVar = 0; IsOk && (CurVar < *NumVars); CurVar++)
893     {
894         char *VName = NULL;
895 
896         IsOk = ReadInString(FileStream,
897                             IVersion,
898                             ((IVersion < 63) ? 5 : MaxChrsVarName),
899                             VarNames ? &VName : NULL,
900                             (Boolean_t)(VarNames != NULL));
901         if (IsOk && VarNames)
902         {
903             if (VName == NULL)
904             {
905                 /* NULL variable names are converted to empty names */
906                 VName = ALLOC_ARRAY(1, char, "empty variable name");
907                 strcpy(VName, "");
908             }
909             TrimLeadAndTrailSpaces(VName);
910 
911             /*
912              * variables are not allowed to have litteral new line characters
913              * within them but they can sneek in from ASCII data files so
914              * convert any to their appropriate two character representation
915              */
916             IsOk = ReplaceNewlineWithBackslashN(&VName);
917 
918             IsOk = IsOk && StringListSetString(*VarNames, CurVar, VName);
919             if (VName != NULL)
920                 FREE_ARRAY(VName, "variable name");
921         }
922 
923         if (!IsOk)
924         {
925             if (VarNames && *VarNames)
926                 StringListDealloc(VarNames);
927             ErrMsg(translate("Out of space while allocating variable names"));
928         }
929     }
930     ENSURE(VALID_BOOLEAN(IsOk));
931     return (IsOk);
932 }
933 
934 
935 
936 
937 /**
938  */
ReadInPresetZoneColor(FileStream_s * FileStream,short IVersion,ZoneSpec_s * ZoneSpec)939 static Boolean_t ReadInPresetZoneColor(FileStream_s *FileStream,
940                                        short         IVersion,
941                                        ZoneSpec_s   *ZoneSpec)
942 {
943     Boolean_t IsOk = TRUE;
944     LgIndex_t ZoneColor;
945 
946     REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
947     REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion);
948     REQUIRE(VALID_REF(ZoneSpec));
949 
950     ZoneColor = GetIoFileInt(FileStream, IVersion, -1, LastBasicColor, &IsOk);
951     if (IsOk)
952     {
953         if (VALID_BASIC_COLOR(ZoneColor))
954         {
955             ZoneSpec->ZoneLoadInfo.PresetZoneColor = (EntIndex_t)ZoneColor;
956             AdjustCustomColor(IVersion, &ZoneSpec->ZoneLoadInfo.PresetZoneColor);
957         }
958         else if (ZoneColor != -1)
959             IsOk = FALSE;
960     }
961 
962     ENSURE(VALID_BOOLEAN(IsOk));
963     return IsOk;
964 }
965 
966 /**
967  */
ConvertCommonTimeToSolutionTime(ZoneSpec_s * ZoneSpec)968 static void ConvertCommonTimeToSolutionTime(ZoneSpec_s *ZoneSpec)
969 {
970     REQUIRE(VALID_REF(ZoneSpec));
971     REQUIRE(ZoneSpec->AuxData == NULL || VALID_REF(ZoneSpec->AuxData));
972 
973     LgIndex_t ItemIndex;
974     if (ZoneSpec->AuxData != NULL &&
975         AuxDataGetItemIndex(ZoneSpec->AuxData, AuxData_Common_Time, &ItemIndex))
976     {
977         const char    *SameName;
978         ArbParam_t     Value;
979         AuxDataType_e  Type;
980         Boolean_t      Retain;
981 
982         AuxDataGetItemByIndex(ZoneSpec->AuxData, ItemIndex,
983                               &SameName, &Value, &Type, &Retain);
984         CHECK(ustrcmp(AuxData_Common_Time, SameName) == 0);
985         CHECK(Type == AuxDataType_String);
986 
987         char *EndPtr = NULL;
988         double SolutionTime = strtod((const char *)Value, &EndPtr);
989         if (EndPtr != (char *)Value)
990         {
991             /* we only allow white space to trail a value */
992             while (tecplot::isspace(*EndPtr))
993                 EndPtr++;
994         }
995         if (EndPtr != (char *)Value && *EndPtr == '\0')
996         {
997             ZoneSpec->SolutionTime = SolutionTime;
998             ZoneSpec->StrandID     = STRAND_ID_PENDING;
999             AuxDataDeleteItemByIndex(ZoneSpec->AuxData, ItemIndex);
1000         }
1001     }
1002 }
1003 
1004 /*
1005  * Pass1 for a zone reads in and initializes the zone structures.
1006  * These structures are released later if the user elects to not read them
1007  * in.
1008  */
ReadInZoneHeader(FileStream_s * FileStream,short IVersion,ZoneSpec_s * ZoneSpec,Set_pa IsVarCellCentered,EntIndex_t NumVars,Boolean_t * IsRawFNAvailable,LgIndex_t * FNNumBndryConns)1009 Boolean_t ReadInZoneHeader(FileStream_s *FileStream,
1010                            short         IVersion,
1011                            ZoneSpec_s   *ZoneSpec,
1012                            Set_pa        IsVarCellCentered,
1013                            EntIndex_t    NumVars,
1014                            Boolean_t    *IsRawFNAvailable,
1015                            LgIndex_t    *FNNumBndryConns)
1016 {
1017     EntIndex_t Var;
1018     Boolean_t  IsOk = TRUE;
1019     LgIndex_t  I1;
1020 
1021     REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
1022     REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion);
1023     REQUIRE(VALID_REF(ZoneSpec));
1024     REQUIRE(IsVarCellCentered == NULL || VALID_REF(IsVarCellCentered));
1025     REQUIRE(NumVars >= 0);
1026     REQUIRE(VALID_REF(IsRawFNAvailable));
1027     REQUIRE(VALID_REF(FNNumBndryConns));
1028 
1029     SetZoneSpecDefaults(ZoneSpec);
1030 
1031     if (IsVarCellCentered != NULL)
1032     {
1033         /* assign default variable value location: nodal */
1034         ClearSet(IsVarCellCentered);
1035         IsOk = ExpandSet(IsVarCellCentered, NumVars, FALSE);
1036     }
1037 
1038     if (IsOk)
1039         IsOk = ReadInString(FileStream, IVersion,
1040                             ((IVersion < 63) ? 10 : MaxChrsZnTitle),
1041                             &ZoneSpec->Name,
1042                             TRUE);
1043 
1044     if (IsOk && ZoneSpec->Name == NULL)
1045     {
1046         /* NULL zone names are converted to empty names */
1047         ZoneSpec->Name = ALLOC_ARRAY(1, char, "empty zone name");
1048         IsOk = (ZoneSpec->Name != NULL);
1049         if (IsOk)
1050             strcpy(ZoneSpec->Name, "");
1051     }
1052 
1053     if (IsOk)
1054         TrimLeadAndTrailSpaces(ZoneSpec->Name);
1055 
1056     if (IVersion < 101)
1057     {
1058         Boolean_t    IsZoneFinite;
1059         DataFormat_e ZoneDataFormat;
1060 
1061         I1 = GetIoFileInt(FileStream, IVersion, 0, 3, &IsOk);
1062 
1063         if ((I1 < 0) || (I1 > 3))
1064         {
1065             return (FALSE);
1066         }
1067 
1068         ZoneDataFormat = (DataFormat_e)I1;
1069 
1070         IsZoneFinite = (ZoneDataFormat == DataFormat_FEPoint ||
1071                         ZoneDataFormat == DataFormat_FEBlock);
1072 
1073         ZoneSpec->ZoneLoadInfo.IsInBlockFormat = (ZoneDataFormat == DataFormat_IJKBlock ||
1074                                                   ZoneDataFormat == DataFormat_FEBlock);
1075 
1076         if (IVersion > 62)
1077             IsOk = ReadInPresetZoneColor(FileStream, IVersion, ZoneSpec);
1078 
1079         if (IVersion < 60)
1080             GetNextValue(FileStream, FieldDataType_Float, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);  /* Old ZPlane Value */
1081 
1082         if (IsOk)
1083         {
1084             ZoneSpec->NumPtsI = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
1085             ZoneSpec->NumPtsJ = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
1086             if (IVersion >= 60)
1087                 ZoneSpec->NumPtsK = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
1088             else
1089                 ZoneSpec->NumPtsK = 1;
1090         }
1091 
1092         if (IsOk)
1093         {
1094             /* If IMax,JMax, & KMax are all zero then this zone was "zombied" by
1095                a partial read to make layout files align. */
1096 
1097             if (!((ZoneSpec->NumPtsI == 0) &&
1098                   (ZoneSpec->NumPtsJ == 0) &&
1099                   (ZoneSpec->NumPtsK == 0)) &&
1100                 ((ZoneSpec->NumPtsI <= 0) ||
1101                  (ZoneSpec->NumPtsJ <= 0) ||
1102                  (ZoneSpec->NumPtsK < 0)  ||
1103                  ((!IsZoneFinite && (ZoneSpec->NumPtsK == 0)))))
1104             {
1105                 ErrMsg(translate("Datafile is corrupted"));
1106                 IsOk = FALSE;
1107             }
1108 
1109             if (IsZoneFinite)
1110             {
1111                 if (IVersion >= 61)
1112                 {
1113                     ZoneSpec->Type = (ZoneType_e)(ZoneSpec->NumPtsK + 1);
1114                     switch (ZoneSpec->Type)
1115                     {
1116                         case ZoneType_FETriangle: ZoneSpec->NumPtsK = 3; break;
1117                         case ZoneType_FEQuad:     ZoneSpec->NumPtsK = 4; break;
1118                         case ZoneType_FETetra:    ZoneSpec->NumPtsK = 4; break;
1119                         case ZoneType_FEBrick:    ZoneSpec->NumPtsK = 8; break;
1120                         case ZoneType_FELineSeg:  ZoneSpec->NumPtsK = 2; break;
1121                         default:
1122                         {
1123                             ErrMsg(translate("Datafile corrupted: Invalid element type for FE DataSet"));
1124                             IsOk = FALSE;
1125                         }
1126                     }
1127                 }
1128                 else
1129                 {
1130                     ZoneSpec->Type = ZoneType_FEQuad;
1131                     ZoneSpec->NumPtsK = 4;
1132                 }
1133             }
1134             else
1135             {
1136                 ZoneSpec->Type = ZoneType_Ordered;
1137 
1138                 ZoneSpec->ICellDim = ZoneSpec->NumPtsI - 1;
1139                 ZoneSpec->JCellDim = ZoneSpec->NumPtsJ - 1;
1140                 ZoneSpec->KCellDim = ZoneSpec->NumPtsK - 1;
1141             }
1142         }
1143 
1144         /*
1145          * Raw and user defined boundary face neighbors connections were not in
1146          * this or previous versions of the binary data files.
1147          */
1148         *IsRawFNAvailable = FALSE;
1149         *FNNumBndryConns  = 0;
1150     }
1151     else
1152     {
1153         if (IsOk && (IVersion >= 107))
1154         {
1155             ZoneSpec->ParentZone = GetIoFileInt(FileStream, IVersion, -1, MAXZONEMAP - 1, &IsOk);
1156             if (!IsOk)
1157                 ErrMsg(translate("Invalid datafile: parent zone assignment must be to an existing zone within the same datafile."));
1158         }
1159 
1160         if (IsOk && (IVersion >= 106))
1161         {
1162             /* Strand ID and solution time. Strand ID's of STRAND_ID_PENDING, -2, instruct Tecplot to generate strand ID's */
1163             ZoneSpec->StrandID     = GetIoFileInt(FileStream, IVersion, -2, MAXZONEMAP - 1, &IsOk);
1164             ZoneSpec->SolutionTime = GetNextValue(FileStream, FieldDataType_Double, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
1165             if (!IsOk)
1166                 ErrMsg(translate("Invalid datafile: bad StrandID or SolutionTime"));
1167         }
1168 
1169         /* preset zone color */
1170         IsOk = IsOk && ReadInPresetZoneColor(FileStream, IVersion, ZoneSpec);
1171 
1172         /* ZoneType */
1173         I1 = (ZoneType_e)GetIoFileInt(FileStream, IVersion, 0, 7, &IsOk);
1174         switch (I1)
1175         {
1176             case 0: ZoneSpec->Type = ZoneType_Ordered;      break;
1177             case 1: ZoneSpec->Type = ZoneType_FELineSeg;    break;
1178             case 2: ZoneSpec->Type = ZoneType_FETriangle;   break;
1179             case 3: ZoneSpec->Type = ZoneType_FEQuad;       break;
1180             case 4: ZoneSpec->Type = ZoneType_FETetra;      break;
1181             case 5: ZoneSpec->Type = ZoneType_FEBrick;      break;
1182             case 6: ZoneSpec->Type = ZoneType_FEPolygon;    break;
1183             case 7: ZoneSpec->Type = ZoneType_FEPolyhedron; break;
1184             default:
1185             {
1186                 ErrMsg(translate("Invalid datafile: unknown zone type."));
1187                 IsOk = FALSE;
1188             } break;
1189         }
1190 
1191         /* DataPacking (Always BLOCK starting with file version 112 so removed from binary format) */
1192         if (IVersion < 112)
1193             ZoneSpec->ZoneLoadInfo.IsInBlockFormat =
1194                 ((DataPacking_e)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk) == DataPacking_Block);
1195         else
1196             ZoneSpec->ZoneLoadInfo.IsInBlockFormat = TRUE;
1197 
1198         /* is the variable value location specified? */
1199         if ((Boolean_t)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk) && IsOk)
1200         {
1201             /* Variable Value Location foreach Var */
1202             for (Var = 0; Var < NumVars && IsOk; Var++)
1203             {
1204                 if ((Boolean_t)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk) && IsOk &&
1205                     IsVarCellCentered != NULL)
1206                 {
1207                     IsOk = (ZoneSpec->ZoneLoadInfo.IsInBlockFormat);
1208                     if (IsOk)
1209                         IsOk = AddToSet(IsVarCellCentered, Var, FALSE);
1210                     else
1211                         ErrMsg(translate("Invalid datafile: cell centered "
1212                                          "variable must be in block format.",
1213                                          "See the Tecplot User's Manual for a definition of 'block format'"));
1214                 }
1215             }
1216         }
1217 
1218         /* are raw face neighbors supplied in the data section? */
1219         if (IVersion >= 108 && IsOk)
1220         {
1221             *IsRawFNAvailable = GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
1222             if (*IsRawFNAvailable &&
1223                 (ZoneSpec->Type == ZoneType_Ordered ||
1224                  ZoneSpec->Type == ZoneType_FELineSeg))
1225             {
1226                 IsOk = FALSE;
1227                 ErrMsg(translate("Invalid datafile: raw face neighbors may not be "
1228                                  "supplied for ordered or FE line segment zones."));
1229             }
1230         }
1231         else
1232             *IsRawFNAvailable = FALSE;
1233 
1234         /*
1235          * If raw face neighbors are available in the datafile then Tecplot
1236          * should not auto-assign the neighbors after the load.
1237          */
1238         ZoneSpec->FNAreCellFaceNbrsSupplied = *IsRawFNAvailable;
1239 
1240         /* miscellaneous face neighbor info */
1241         *FNNumBndryConns = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
1242         if (*FNNumBndryConns != 0)
1243             ZoneSpec->FNMode = (FaceNeighborMode_e)GetIoFileInt(FileStream, IVersion, 0, 3, &IsOk);
1244 
1245         if (IVersion >= 108 && IsOk)
1246         {
1247             Boolean_t FaceNeighborsComplete = FALSE;
1248             if (*FNNumBndryConns != 0 &&
1249                 ZoneSpec->Type != ZoneType_Ordered)
1250                 FaceNeighborsComplete = (Boolean_t)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
1251 
1252             /*
1253              * If the user defined face neighbors completely specify all the
1254              * face neighbors then we don't want to auto-assign the cell face
1255              * neighbors after loading. If they are not complete then leave the
1256              * setting (as set above) dependent on the availability of the raw
1257              * face neighbors.
1258              *
1259              * NOTE:
1260              *   This is a rather inefficient way to specify face neighbors.
1261              */
1262             if (FaceNeighborsComplete)
1263                 ZoneSpec->FNAreCellFaceNbrsSupplied = TRUE;
1264         }
1265 
1266         if (ZoneSpec->Type == ZoneType_Ordered)
1267         {
1268             /* IMax, JMax, KMax */
1269             ZoneSpec->NumPtsI = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
1270             ZoneSpec->NumPtsJ = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
1271             ZoneSpec->NumPtsK = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
1272             /*
1273              * if not a zombie zone (zombie zone: points in all dimensions are
1274              * zero) then points in each direction must be specified
1275              */
1276             if (IsOk &&
1277                 !(ZoneSpec->NumPtsI == 0 &&
1278                   ZoneSpec->NumPtsJ == 0 &&
1279                   ZoneSpec->NumPtsK == 0)  &&
1280                 (ZoneSpec->NumPtsI == 0 ||
1281                  ZoneSpec->NumPtsJ == 0 ||
1282                  ZoneSpec->NumPtsK == 0))
1283             {
1284                 ErrMsg(translate("Invalid data file: incorrect specification of "
1285                                  "I, J, or K points for ordered data set."));
1286                 IsOk = FALSE;
1287             }
1288         }
1289         else
1290         {
1291             ZoneSpec->NumPtsI = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
1292             if (ZoneSpec->Type == ZoneType_FEPolygon || ZoneSpec->Type == ZoneType_FEPolyhedron)
1293             {
1294                 ZoneSpec->NumPtsK = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk); // ...NumFaces
1295                 if (IVersion >= 111)
1296                 {
1297                     ZoneSpec->NumFaceNodes      = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
1298                     ZoneSpec->NumFaceBndryFaces = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
1299                     ZoneSpec->NumFaceBndryItems = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
1300                 }
1301             }
1302             else
1303             {
1304                 switch (ZoneSpec->Type)
1305                 {
1306                     case ZoneType_FETriangle: ZoneSpec->NumPtsK = 3; break;
1307                     case ZoneType_FEQuad:     ZoneSpec->NumPtsK = 4; break;
1308                     case ZoneType_FETetra:    ZoneSpec->NumPtsK = 4; break;
1309                     case ZoneType_FEBrick:    ZoneSpec->NumPtsK = 8; break;
1310                     case ZoneType_FELineSeg:  ZoneSpec->NumPtsK = 2; break;
1311                     default :
1312                     {
1313                         ErrMsg(translate("Invalid data file: invalid element type for FE data set."));
1314                         IsOk = FALSE;
1315                     }
1316                 }
1317             }
1318             ZoneSpec->NumPtsJ = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
1319 
1320             ZoneSpec->ICellDim = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
1321             ZoneSpec->JCellDim = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
1322             ZoneSpec->KCellDim = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
1323         }
1324 
1325         /* Zone Auxiliary Data indicator followed by Zone Auxiliary Data */
1326         for (I1 = GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
1327              IsOk && I1 != 0;
1328              I1 = GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk))
1329         {
1330             if (ZoneSpec->AuxData == NULL)
1331                 ZoneSpec->AuxData = AuxDataAlloc();
1332             IsOk = (ZoneSpec->AuxData != NULL);
1333             if (IsOk)
1334                 IsOk = ReadInAuxData(FileStream, IVersion, ZoneSpec->AuxData);
1335         }
1336     }
1337 
1338     /*
1339      * Convert AuxZone's Common.Time from non-time aware data files to zone
1340      * solution time if it exists.
1341      */
1342     if (IVersion < 106 && IsOk)
1343         ConvertCommonTimeToSolutionTime(ZoneSpec);
1344 
1345     ENSURE(VALID_BOOLEAN(IsOk));
1346     return (IsOk);
1347 }
1348 
1349 
1350 
1351 
1352 /*
1353  *  Pass1 for Custom labels simply acknowledges that a custom label was
1354  *  parsed and skips over the labels.
1355  */
1356 
ReadInCustomLabels(FileStream_s * FileStream,short IVersion,Boolean_t OkToLoad,StringList_pa * CustomLabelBase)1357 Boolean_t ReadInCustomLabels(FileStream_s  *FileStream,
1358                              short          IVersion,
1359                              Boolean_t      OkToLoad,
1360                              StringList_pa *CustomLabelBase)
1361 {
1362     LgIndex_t NumLabels;
1363     short     I;
1364     Boolean_t IsOk = TRUE;
1365 
1366     REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
1367     REQUIRE(IVersion > 0);
1368     REQUIRE(VALID_BOOLEAN(OkToLoad));
1369     REQUIRE(!(OkToLoad) || VALID_REF(CustomLabelBase));
1370 
1371     NumLabels = (short)GetIoFileInt(FileStream, IVersion, 1, MAXINDEX, &IsOk);
1372     if (IsOk && NumLabels != 0 && OkToLoad)
1373     {
1374         *CustomLabelBase = StringListAlloc();
1375         IsOk = (*CustomLabelBase != NULL);
1376         if (!IsOk)
1377             ErrMsg(translate("Cannot allocate memory for Custom Labels."));
1378     }
1379 
1380     for (I = 0; IsOk && (I < NumLabels); I++)
1381     {
1382         char *TLabel = NULL;
1383 
1384         IsOk = ReadInString(FileStream, IVersion,
1385                             1024,
1386                             &TLabel,
1387                             OkToLoad);
1388         TrimLeadAndTrailSpaces(TLabel);
1389 
1390         if (IsOk && OkToLoad)
1391         {
1392 #if defined TECPLOTKERNEL
1393 /* CORE SOURCE CODE REMOVED */
1394 #endif
1395             IsOk = StringListAppendString(*CustomLabelBase, TLabel);
1396             if (TLabel != NULL)
1397                 FREE_ARRAY(TLabel, "custom label");
1398             if (!IsOk)
1399                 ErrMsg(translate("Cannot allocate memory for Custom Label."));
1400         }
1401     }
1402     if (!IsOk)
1403         ErrMsg(translate("Invalid custom axis label record in binary datafile"));
1404 
1405     ENSURE(VALID_BOOLEAN(IsOk));
1406     ENSURE(!(IsOk && NumLabels != 0 && OkToLoad) ||
1407            StringListValid(*CustomLabelBase));
1408     return IsOk;
1409 }
1410 
1411 
ReadInUserRec(FileStream_s * FileStream,short IVersion,int MaxCharactersAllowed,char ** UserRec)1412 Boolean_t ReadInUserRec(FileStream_s  *FileStream,
1413                         short          IVersion,
1414                         int            MaxCharactersAllowed,
1415                         char         **UserRec) /* NULL if to ignore */
1416 {
1417     if (!ReadInString(FileStream, IVersion,
1418                       MaxCharactersAllowed,
1419                       UserRec,
1420                       (Boolean_t)(UserRec != NULL)))
1421     {
1422         ErrMsg(translate("Invalid USERREC record in binary datafile"));
1423         return (FALSE);
1424     }
1425     return (TRUE);
1426 }
1427 
1428 
1429 /**
1430  */
ReadInAuxData(FileStream_s * FileStream,short IVersion,AuxData_pa AuxData)1431 Boolean_t ReadInAuxData(FileStream_s *FileStream,
1432                         short         IVersion,
1433                         AuxData_pa    AuxData)
1434 {
1435     Boolean_t IsOk;
1436     Boolean_t DoCollectData;
1437     char      *AuxName  = NULL;
1438     LgIndex_t AuxValueType;
1439     char      *AuxValue = NULL;
1440 
1441     REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
1442     REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion);
1443     REQUIRE(AuxData == NULL || VALID_REF(AuxData));
1444 
1445     DoCollectData = (AuxData != NULL);
1446     IsOk = ReadInString(FileStream,
1447                         IVersion,
1448                         MaxChrsVarName, /* ... seems reasonable */
1449                         &AuxName,
1450                         DoCollectData);
1451     if (IsOk && DoCollectData && !AuxDataIsValidName(AuxName))
1452     {
1453         ErrMsg(translate("Invalid auxiliary data name."));
1454         IsOk = FALSE;
1455     }
1456 
1457     /*
1458      * currently only one value type is supported
1459      *   0: AuxiliaryValueFormat_String
1460      */
1461     if (IsOk)
1462     {
1463         AuxValueType = GetIoFileInt(FileStream, IVersion, 0, 0, &IsOk);
1464         if (IsOk && (AuxValueType != (LgIndex_t)AuxDataType_String))
1465         {
1466             ErrMsg(translate("Unsupported auxiliary data type"));
1467             IsOk = FALSE;
1468         }
1469     }
1470 
1471     if (IsOk)
1472         IsOk = ReadInString(FileStream,
1473                             IVersion,
1474                             MaxChrsAuxValueString,
1475                             &AuxValue,
1476                             DoCollectData);
1477     if (IsOk && DoCollectData)
1478         IsOk = AuxDataSetItem(AuxData,
1479                               AuxName, (ArbParam_t)AuxValue,
1480                               AuxDataType_String,
1481                               TRUE); /* Retain */
1482 
1483     /* cleanup: auxiliary data made a copy of the name and value */
1484     if (AuxName != NULL)
1485         FREE_ARRAY(AuxName, "data set auxiliary data item name");
1486     if (AuxValue != NULL)
1487         FREE_ARRAY(AuxValue, "data set auxiliary data item value");
1488 
1489     ENSURE(VALID_BOOLEAN(IsOk));
1490     return IsOk;
1491 }
1492 
1493 
GetZoneAttachment(FileStream_s * FileStream,short IVersion,EntIndex_t * Z,Boolean_t * IsAttached,Boolean_t * IsOk)1494 static void GetZoneAttachment(FileStream_s *FileStream,
1495                               short         IVersion,
1496                               EntIndex_t   *Z,
1497                               Boolean_t    *IsAttached,
1498                               Boolean_t    *IsOk)
1499 {
1500     REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
1501     REQUIRE(VALID_REF(Z));
1502     REQUIRE(VALID_REF(IsAttached));
1503     REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
1504 
1505     if (IVersion >= 47)
1506         *Z = (EntIndex_t)GetIoFileInt(FileStream, IVersion, -1, MAXZONEMAP, IsOk);
1507     else
1508         *Z = 0;
1509 
1510     if (IVersion < 70)
1511         (*Z)--;
1512 
1513     if (*Z == -1)
1514     {
1515         *Z          = 0;
1516         *IsAttached = FALSE;
1517     }
1518     else
1519         *IsAttached = TRUE;
1520 
1521     ENSURE(VALID_BOOLEAN(*IsAttached));
1522     ENSURE(VALID_BOOLEAN(*IsOk));
1523     ENSURE(*Z >= 0);
1524 }
1525 
1526 
ReadMacroFunctionCommand(FileStream_s * FileStream,short IVersion,Boolean_t OkToLoad,char ** MacroFunctionCommand)1527 static Boolean_t ReadMacroFunctionCommand(FileStream_s  *FileStream,
1528                                           short          IVersion,
1529                                           Boolean_t      OkToLoad,
1530                                           char         **MacroFunctionCommand)
1531 {
1532     Boolean_t Result = FALSE;
1533     REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
1534     REQUIRE(IVersion > 0);
1535     REQUIRE(VALID_BOOLEAN(OkToLoad));
1536     REQUIRE(VALID_REF(MacroFunctionCommand));
1537 
1538     Result = ReadInString(FileStream, IVersion, 0, MacroFunctionCommand, OkToLoad);
1539 
1540     ENSURE(VALID_BOOLEAN(Result));
1541     return (Result);
1542 }
1543 
1544 
1545 /*
1546  *  Pass1 for Geometries simply acknowledges that a geometry was
1547  *  parsed and skips over the geometry.
1548  */
ReadInGeometry(FileStream_s * FileStream,short IVersion,Boolean_t OkToLoad,Geom_s * Geom,LgIndex_t MaxDataPts)1549 Boolean_t ReadInGeometry(FileStream_s *FileStream,
1550                          short         IVersion,
1551                          Boolean_t     OkToLoad,
1552                          Geom_s       *Geom,
1553                          LgIndex_t     MaxDataPts)
1554 {
1555     LgIndex_t        I;
1556     LgIndex_t        S;
1557     FieldDataType_e  FFT;
1558     Boolean_t        IsOk = TRUE;
1559     TranslatedString ErrMsgString = translate("Invalid geometry record");
1560 
1561     REQUIRE(VALID_REF(Geom));
1562 
1563     if (IVersion < 70)
1564         FFT = FieldDataType_Float;
1565     else
1566         FFT = FieldDataType_Double;
1567 
1568     if (IVersion < 101)
1569         I = GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
1570     else
1571         I = GetIoFileInt(FileStream, IVersion, 0, 4, &IsOk);
1572 
1573     if (I == 0)
1574         Geom->PositionCoordSys = CoordSys_Grid;
1575     else if (I == 1)
1576         Geom->PositionCoordSys = CoordSys_Frame;
1577     /*
1578      * I == 2 is for CoordSys_FrameOffset and is not used currently
1579      *
1580      * I == 3 is for the old window coordinate system
1581      */
1582     else if (I == 4)
1583         Geom->PositionCoordSys = CoordSys_Grid3D;
1584     else
1585     {
1586         ErrMsgString = translate("Invalid geometry coordinate system");
1587         IsOk = FALSE;
1588     }
1589 
1590     Geom->Scope = (Scope_e)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
1591     if (IVersion >= 102)
1592         Geom->DrawOrder = (DrawOrder_e)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
1593     Geom->AnchorPos.Generic.V1 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
1594     Geom->AnchorPos.Generic.V2 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
1595     if (IVersion >= 45)
1596         Geom->AnchorPos.Generic.V3 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
1597     else
1598         Geom->AnchorPos.Generic.V3 = 0.0;
1599 
1600     GetZoneAttachment(FileStream, IVersion, &Geom->Zone, &Geom->AttachToZone, &IsOk);
1601 
1602     Geom->BColor = (SmInteger_t)GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk);
1603 
1604     AdjustCustomColor(IVersion, &Geom->BColor);
1605 
1606     if (IVersion > 47)
1607     {
1608         Geom->FillBColor = (SmInteger_t)GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk);
1609         Geom->IsFilled  = (Boolean_t)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
1610         AdjustCustomColor(IVersion, &Geom->FillBColor);
1611     }
1612     else
1613     {
1614         Geom->FillBColor = Geom->BColor;
1615         Geom->IsFilled  = FALSE;
1616     }
1617 
1618     if (IVersion < 101)
1619     {
1620         Geom->GeomType = (GeomType_e)GetIoFileInt(FileStream, IVersion, 0, 5, &IsOk);
1621         if (Geom->GeomType == GeomType_LineSegs3D)
1622         {
1623             /*
1624              * GeomType_LineSegs3D is deprecated, converter to GeomType_LineSegs
1625              * with CoordSys_Grid3D instead
1626              */
1627             Geom->GeomType         = GeomType_LineSegs;
1628             Geom->PositionCoordSys = CoordSys_Grid3D; /*...should have been anyway */
1629         }
1630     }
1631     else
1632     {
1633         Geom->GeomType = (GeomType_e)GetIoFileInt(FileStream, IVersion, 0, 4, &IsOk);
1634     }
1635 
1636     /*
1637      * Check geom coord sys versus geom type
1638      */
1639     if (Geom->PositionCoordSys == CoordSys_Grid3D &&
1640         Geom->GeomType != GeomType_LineSegs)
1641     {
1642         ErrMsgString = translate("Mismatch between geometry coordinate system and geometry type");
1643         IsOk = FALSE;
1644     }
1645 
1646     if (IVersion > 41)
1647     {
1648         Geom->LinePattern  = (LinePattern_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)LinePattern_DashDotDot, &IsOk);
1649     }
1650     else
1651     {
1652         Geom->LinePattern  = (LinePattern_e)((int)Geom->GeomType % 2);
1653         Geom->GeomType     = (GeomType_e)((int)Geom->GeomType / 10);
1654     }
1655 
1656     if ((IVersion < 49) && ((short)(Geom->GeomType) == 2))
1657     {
1658         Geom->GeomType = GeomType_Rectangle;
1659         Geom->IsFilled = TRUE;
1660     }
1661 
1662     if ((IVersion < 70) && ((short)(Geom->GeomType) > 1))
1663         Geom->GeomType = (GeomType_e)((short)Geom->GeomType + 1);
1664 
1665     ResetString(&Geom->MacroFunctionCommand, NULL, TRUE);
1666 
1667     Geom->ImageResizeFilter = ImageResizeFilter_Texture;
1668 
1669     if (IVersion >= 70)
1670     {
1671         Geom->PatternLength       = GetNextValue(FileStream, FFT,
1672                                                  PatternLengthInputSpec.Min,
1673                                                  PatternLengthInputSpec.Max,
1674                                                  &IsOk);
1675         Geom->LineThickness       = GetNextValue(FileStream, FFT,
1676                                                  LineThicknessInputSpec.Min,
1677                                                  LineThicknessInputSpec.Max,
1678                                                  &IsOk);
1679         Geom->NumEllipsePts       = (SmInteger_t)GetIoFileInt(FileStream, IVersion, 2, MaxPtsCircleOrEllipse, &IsOk);
1680         Geom->ArrowheadStyle      = (ArrowheadStyle_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)ArrowheadStyle_Hollow, &IsOk);
1681         Geom->ArrowheadAttachment = (ArrowheadAttachment_e)GetIoFileInt(FileStream, IVersion,
1682                                                                         0,
1683                                                                         (LgIndex_t)ArrowheadAttachment_AtBothEnds,
1684                                                                         &IsOk);
1685 
1686         Geom->ArrowheadSize  = GetNextValue(FileStream, FFT,
1687                                             ArrowheadSizeInputSpec.Min,
1688                                             ArrowheadSizeInputSpec.Max,
1689                                             &IsOk);
1690         Geom->ArrowheadAngle = GetNextValue(FileStream, FFT,
1691                                             ArrowheadAngleInputSpec.Min,
1692                                             ArrowheadAngleInputSpec.Max,
1693                                             &IsOk);
1694 
1695         if (IVersion >= 75)
1696         {
1697             IsOk = ReadMacroFunctionCommand(FileStream,
1698                                             IVersion,
1699                                             OkToLoad,
1700                                             &Geom->MacroFunctionCommand);
1701         } /* version >= 75 */
1702     } /* version >= 70 */
1703     else
1704     {
1705         Geom->LineThickness        = 0.001;
1706         Geom->PatternLength        = 0.02;
1707         Geom->ArrowheadStyle       = ArrowheadStyle_Plain;
1708         Geom->ArrowheadAttachment  = ArrowheadAttachment_None;
1709         Geom->ArrowheadSize        = 0.05;
1710         Geom->ArrowheadAngle       = 12.0 / DEGPERRADIANS;
1711     }
1712 
1713     if (IVersion < 41)
1714     {
1715         GetNextValue(FileStream, FieldDataType_Float, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
1716         GetNextValue(FileStream, FieldDataType_Float, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
1717         GetNextValue(FileStream, FieldDataType_Float, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
1718     }
1719 
1720     if (IVersion < 70)
1721         Geom->DataType = FieldDataType_Float;
1722     else
1723         Geom->DataType = (FieldDataType_e)GetIoFileInt(FileStream, IVersion, 1, 2, &IsOk);
1724     CHECK(VALID_GEOM_FIELD_DATA_TYPE(Geom->DataType));
1725 
1726     Geom->Clipping = Clipping_ClipToViewport; /* default value for pre 101 versions */
1727     if (IVersion >= 101)
1728     {
1729         Geom->Clipping = (Clipping_e)GetIoFileInt(FileStream, IVersion, 0, 2, &IsOk);
1730         /*
1731          * The second clipping value was deprecated during v10 development and thus removed.
1732          * This moved Clipping_ClipToFrame to the 2nd position from the 3rd, so we convert
1733          * value 2 to ClipToFrame to support files made during v10 developement.
1734          */
1735         if (Geom->Clipping == (Clipping_e)2)
1736             Geom->Clipping = Clipping_ClipToFrame;
1737     }
1738 
1739     if (IVersion < 50 ||
1740         Geom->GeomType == GeomType_LineSegs)
1741     {
1742         Geom->NumSegments = (SmInteger_t)GetIoFileInt(FileStream, IVersion, 1, MaxGeoSegments, &IsOk);
1743 #if defined TECPLOTKERNEL
1744 /* CORE SOURCE CODE REMOVED */
1745 #endif
1746         S = -1;
1747         I = 0;
1748         while ((S + 1 < Geom->NumSegments) &&
1749                !feof(FileStream->File) && IsOk)
1750         {
1751             S++;
1752             Geom->NumSegPts[S] = GetIoFileInt(FileStream, IVersion, 1, MAXINDEX, &IsOk);
1753             if ((I + Geom->NumSegPts[S] > MaxDataPts) && OkToLoad)
1754             {
1755                 ErrMsgString = translate("Geometry is too big");
1756                 IsOk = FALSE;
1757             }
1758             else
1759             {
1760                 ReadBlock(FileStream, Geom->GeomData.Generic.V1Base, OkToLoad, Geom->DataType, I, I + Geom->NumSegPts[S] - 1, &IsOk);
1761                 ReadBlock(FileStream, Geom->GeomData.Generic.V2Base, OkToLoad, Geom->DataType, I, I + Geom->NumSegPts[S] - 1, &IsOk);
1762                 if (Geom->PositionCoordSys == CoordSys_Grid3D)
1763                     ReadBlock(FileStream, Geom->GeomData.Generic.V3Base, OkToLoad, Geom->DataType, I, I + Geom->NumSegPts[S] - 1, &IsOk);
1764                 I += Geom->NumSegPts[S];
1765             }
1766         }
1767         if (IsOk && (Geom->GeomType == GeomType_Rectangle))     /* IVersion < 50 */
1768         {
1769             if (OkToLoad)
1770             {
1771                 CopyFieldValue(Geom->GeomData.Generic.V1Base, 0, Geom->GeomData.Generic.V1Base, 2);
1772                 CopyFieldValue(Geom->GeomData.Generic.V2Base, 0, Geom->GeomData.Generic.V2Base, 2);
1773             }
1774         }
1775     }
1776     else if (Geom->GeomType == GeomType_Rectangle ||
1777              Geom->GeomType == GeomType_Ellipse)
1778     {
1779         double XX, YY;
1780         XX = GetNextValue(FileStream, Geom->DataType, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
1781         YY = GetNextValue(FileStream, Geom->DataType, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
1782         if (OkToLoad)
1783         {
1784             SetFieldValue(Geom->GeomData.XYZ.XBase, 0, XX);
1785             SetFieldValue(Geom->GeomData.XYZ.YBase, 0, YY);
1786         }
1787         Geom->NumSegments = 1;
1788         Geom->NumSegPts[0]   = 1;
1789     }
1790     else
1791     {
1792         double XX;
1793         CHECK((Geom->GeomType == GeomType_Square) ||
1794               (Geom->GeomType == GeomType_Circle));
1795         XX = GetNextValue(FileStream, Geom->DataType, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
1796         if (OkToLoad)
1797         {
1798             SetFieldValue(Geom->GeomData.XYZ.XBase, 0, XX);
1799         }
1800         Geom->NumSegments  = 1;
1801         Geom->NumSegPts[0] = 1;
1802     }
1803 
1804     if (!IsOk)
1805         ErrMsg(ErrMsgString);
1806 
1807     return (IsOk);
1808 }
1809 
1810 /*
1811  *  Pass1 for text simply acknowledges that a text was
1812  *  parsed and skips over the text.
1813  */
ReadInText(FileStream_s * FileStream,short IVersion,Boolean_t OkToLoad,Text_s * Text,LgIndex_t MaxTextLen)1814 Boolean_t ReadInText(FileStream_s *FileStream,
1815                      short         IVersion,
1816                      Boolean_t     OkToLoad,
1817                      Text_s       *Text,
1818                      LgIndex_t     MaxTextLen)
1819 {
1820     LgIndex_t        I;
1821     FieldDataType_e  FFT;
1822     SmInteger_t      TextLength = 0;
1823     Boolean_t        IsOk = TRUE;
1824     TranslatedString ErrMsgString = translate("Invalid text record");
1825 
1826     REQUIRE(VALID_REF(Text));
1827 
1828     if (IVersion < 70)
1829         FFT = FieldDataType_Float;
1830     else
1831         FFT = FieldDataType_Double;
1832 
1833     if (IVersion < 101)
1834         I = GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
1835     else
1836         I = GetIoFileInt(FileStream, IVersion, 0, 4, &IsOk);
1837 
1838     if (I == 0)
1839         Text->PositionCoordSys = CoordSys_Grid;
1840     else if (I == 1)
1841         Text->PositionCoordSys = CoordSys_Frame;
1842     /*
1843      * I == 2 is for CoordSys_FrameOffset and is not used currently
1844      *
1845      * I == 3 is for the old window coordinate system
1846      */
1847     else if (I == 4)
1848         Text->PositionCoordSys = CoordSys_Grid3D;
1849     else
1850     {
1851         ErrMsgString = translate("Invalid text coordinate system.");
1852         IsOk = FALSE;
1853     }
1854 
1855     Text->Scope   = (Scope_e)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
1856     Text->AnchorPos.Generic.V1 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
1857     Text->AnchorPos.Generic.V2 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
1858     if (IVersion >= 101)
1859         Text->AnchorPos.Generic.V3 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
1860     else
1861         Text->AnchorPos.Generic.V3 = 0.0; /* default value for pre 101 versions */
1862 
1863     if (IVersion > 40)
1864     {
1865         #if defined TECPLOTKERNEL
1866 /* CORE SOURCE CODE REMOVED */
1867         #else
1868             Text->TextShape.Font = (Font_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)Font_CourierBold, &IsOk);
1869         #endif
1870     }
1871     else
1872     {
1873         #if defined TECPLOTKERNEL
1874 /* CORE SOURCE CODE REMOVED */
1875         #else
1876             Text->TextShape.Font = Font_Helvetica;
1877         #endif
1878     }
1879     if (IVersion < 43)
1880         GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
1881     if (IVersion < 70)
1882     {
1883         if (Text->PositionCoordSys == CoordSys_Grid)
1884             Text->TextShape.SizeUnits = Units_Grid;
1885         else
1886             Text->TextShape.SizeUnits = Units_Frame;
1887     }
1888     else
1889         Text->TextShape.SizeUnits = (Units_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)Units_Point, &IsOk);
1890 
1891     Text->TextShape.Height = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
1892     if (IVersion > 47)
1893     {
1894         Text->Box.BoxType = (TextBox_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)TextBox_Hollow, &IsOk);
1895         if (IVersion < 70)
1896         {
1897             if (Text->Box.BoxType == TextBox_Hollow)
1898                 Text->Box.BoxType = TextBox_Filled;
1899             else if (Text->Box.BoxType == TextBox_Filled)
1900                 Text->Box.BoxType = TextBox_Hollow;
1901         }
1902         Text->Box.Margin     = GetNextValue(FileStream, FFT,
1903                                             TextBoxMarginInputSpec.Min,
1904                                             TextBoxMarginInputSpec.Max,
1905                                             &IsOk);
1906         if (IVersion >= 70)
1907             Text->Box.LineThickness = GetNextValue(FileStream, FFT,
1908                                                    LineThicknessInputSpec.Min,
1909                                                    LineThicknessInputSpec.Max,
1910                                                    &IsOk);
1911         else
1912             Text->Box.LineThickness = 0.01;
1913         Text->Box.BColor     = (ColorIndex_t)GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk);
1914         Text->Box.FillBColor = (ColorIndex_t)GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk);
1915         AdjustCustomColor(IVersion, &Text->Box.BColor);
1916         AdjustCustomColor(IVersion, &Text->Box.FillBColor);
1917     }
1918     else
1919     {
1920         Text->Box.BoxType    = TextBox_None;
1921         Text->Box.Margin     = 0.0;
1922         Text->Box.BColor     = White_C;
1923         Text->Box.FillBColor = Black_C;
1924     }
1925     if (IVersion < 70)
1926     {
1927         Text->Angle       = GetIoFileInt(FileStream, IVersion, -720, 720, &IsOk) / DEGPERRADIANS;
1928         Text->LineSpacing = 1;
1929         Text->Anchor      = TextAnchor_Left;
1930     }
1931     else
1932     {
1933         Text->Angle       = GetNextValue(FileStream, FFT,
1934                                          TextAngleInputSpec.Min,
1935                                          TextAngleInputSpec.Max,
1936                                          &IsOk);
1937         Text->LineSpacing = GetNextValue(FileStream, FFT,
1938                                          TextLineSpacingInputSpec.Min,
1939                                          TextLineSpacingInputSpec.Max,
1940                                          &IsOk);
1941         Text->Anchor      = (TextAnchor_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)TextAnchor_HeadRight, &IsOk);
1942     }
1943 
1944     GetZoneAttachment(FileStream, IVersion, &Text->Zone, &Text->AttachToZone, &IsOk);
1945 
1946     Text->BColor   = (ColorIndex_t)GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk);
1947     AdjustCustomColor(IVersion, &Text->BColor);
1948     if (IVersion < 70)
1949         TextLength = (short)GetIoFileInt(FileStream, IVersion, 0, 5000, &IsOk);
1950 
1951     ResetString(&Text->MacroFunctionCommand, NULL, TRUE);
1952 
1953     Text->Clipping = Clipping_ClipToViewport; /* default value for pre 101 versions */
1954 
1955     if (IVersion < 70)
1956     {
1957         short I, S;
1958         for (I = 0; I < TextLength; I++)
1959         {
1960             S = (short)GetIoFileInt(FileStream, IVersion, 0, 1000, &IsOk);
1961             if (OkToLoad && (I <= MaxTextLen))
1962                 Text->Text[I] = (char)S;
1963         }
1964         if (OkToLoad)
1965             Text->Text[MIN(TextLength, MaxTextLen)] = '\0';
1966     }
1967     else
1968     {
1969         char *S = NULL;
1970 
1971         if (IVersion >= 75)
1972         {
1973             IsOk = ReadMacroFunctionCommand(FileStream,
1974                                             IVersion,
1975                                             OkToLoad,
1976                                             &Text->MacroFunctionCommand);
1977         } /* IVersion >= 75 */
1978 
1979         if (IVersion >= 101)
1980         {
1981             /*
1982              * The second clipping value was deprecated during v10 development and thus removed.
1983              * This moved Clipping_ClipToFrame to the 2nd position from the 3rd, so we convert
1984              * value 2 to ClipToFrame to support files made during v10 developement.
1985              */
1986             Text->Clipping = (Clipping_e)GetIoFileInt(FileStream, IVersion, 0, 2, &IsOk);
1987             if (Text->Clipping == (Clipping_e)2)
1988                 Text->Clipping = Clipping_ClipToFrame;
1989         }
1990 
1991         if (ReadInString(FileStream,
1992                          IVersion,
1993                          MaxTextLen,
1994                          &S,
1995                          OkToLoad))
1996         {
1997             REQUIRE(!(S || OkToLoad) || VALID_REF(Text->Text));
1998             if (S)
1999             {
2000 #if defined TECPLOTKERNEL
2001 /* CORE SOURCE CODE REMOVED */
2002 #endif /* TECPLOTKERNEL */
2003                 if (IsOk)
2004                 {
2005                     strcpy(Text->Text, S);
2006                 }
2007                 FREE_ARRAY(S, "Release temp string for new text label");
2008             }
2009             else if (OkToLoad)
2010                 Text->Text[0] = '\0';
2011         }
2012         else
2013             IsOk = FALSE;
2014     }
2015 
2016     if (!IsOk)
2017         ErrMsg(ErrMsgString);
2018 
2019     return (IsOk);
2020 }
2021 
2022 
CompareVersion(float Version,char * VersionString,Boolean_t IsByteOrderNative)2023 static Boolean_t CompareVersion(float      Version,
2024                                 char      *VersionString,
2025                                 Boolean_t  IsByteOrderNative)
2026 {
2027     char *VersionBuf = (char *) & Version;
2028 
2029     REQUIRE(VALID_REF(VersionString));
2030 
2031     if (IsByteOrderNative)
2032         return ((VersionString[0] == VersionBuf[0]) &&
2033                 (VersionString[1] == VersionBuf[1]) &&
2034                 (VersionString[2] == VersionBuf[2]) &&
2035                 (VersionString[3] == VersionBuf[3]));
2036     else
2037         return ((VersionString[3] == VersionBuf[0]) &&
2038                 (VersionString[2] == VersionBuf[1]) &&
2039                 (VersionString[1] == VersionBuf[2]) &&
2040                 (VersionString[0] == VersionBuf[3]));
2041 }
2042 
2043 static float ValidVersions[] = {7.0F,
2044                                 6.3F, 6.2F, 6.1F, 6.0F,
2045                                 5.0F,
2046                                 4.7F, 4.6F, 4.5F, 4.4F, 4.3F, 4.2F, 4.1F, 4.0F
2047                                };
2048 #define NUMVALIDVERSIONS ((int)(sizeof(ValidVersions)/sizeof(ValidVersions[0])))
2049 
2050 
2051 /*
2052  * Extra caution taken here in case value read is invalid float
2053  */
GetDoubleVersion(char * VersionString,float * FInputVersion,Boolean_t IsByteOrderNative)2054 static Boolean_t GetDoubleVersion(char      *VersionString,
2055                                   float     *FInputVersion,
2056                                   Boolean_t  IsByteOrderNative)
2057 {
2058     int  I;
2059     REQUIRE(VALID_REF(FInputVersion));
2060 
2061     for (I = 0; I < NUMVALIDVERSIONS; I++)
2062         if (CompareVersion(ValidVersions[I], VersionString, IsByteOrderNative))
2063         {
2064             *FInputVersion = ValidVersions[I];
2065             return (TRUE);
2066         }
2067     return (FALSE);
2068 }
2069 
2070 
GetNewInputVersion(FileStream_s * FileStream)2071 static short GetNewInputVersion(FileStream_s *FileStream)
2072 {
2073     /*
2074      *
2075      */
2076     char       Buf[4];
2077     short      IVersion = 0;
2078     short      I;
2079     LgIndex_t  OneValue;
2080     Boolean_t  IsOk = TRUE;
2081 
2082     REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
2083     REQUIRE(FileStream->IsByteOrderNative);
2084 
2085     if (TP_FREAD(Buf, 4, 1, FileStream->File) != 1)
2086         return (0);
2087 
2088     if (strncmp(Buf, "#!TD", 4))
2089         return (0);
2090 
2091     if (TP_FREAD(Buf, 4, 1, FileStream->File) != 1)
2092         return (0);
2093 
2094     if (Buf[0] != 'V')
2095         return (0);
2096 
2097     I = 1;
2098     while ((I < 4) && tecplot::isdigit(Buf[I]))
2099         IVersion = IVersion * 10 + Buf[I++] - '0';
2100 
2101     if (IVersion < 70)
2102         return (0);
2103     else if (IVersion > TecplotBinaryFileVersion)
2104     {
2105         ErrMsg(translate("Binary file version newer than Tecplot version. "
2106                          "Upgrade Tecplot or use an older Preplot to produce "
2107                          "the datafile."));
2108         return (IVersion);
2109     }
2110 
2111     /*
2112      * Determine Byte Order.
2113      */
2114 
2115     OneValue = GetIoFileInt(FileStream,
2116                             IVersion,
2117                             -MAXINDEX,
2118                             MAXINDEX,
2119                             &IsOk);
2120 
2121     if (!IsOk)
2122         return (0);
2123 
2124     FileStream->IsByteOrderNative = (OneValue == 1);
2125 
2126     return (IVersion);
2127 }
2128 
2129 /**
2130  * Return value of zero is to be considered as an invalid
2131  * tecplot binary datafile header.  Actually binary files
2132  * older than version 4.0 (return value of 40) are not supported
2133  * (See notes in preplot.c).
2134  */
GetInputVersion(FileStream_s * FileStream)2135 short GetInputVersion(FileStream_s *FileStream)
2136 {
2137     Boolean_t    IsOk = TRUE;
2138     float        FInputVersion;
2139     short        IVersion;
2140     char         VersionString[4];
2141     FileOffset_t StartOffset = 0;
2142 
2143     /*
2144      * First check to see if file uses new
2145      * input version format.
2146      */
2147 
2148     /* keep track of our start offset */
2149     StartOffset = TP_FTELL(FileStream->File);
2150 
2151     IVersion = GetNewInputVersion(FileStream);
2152 
2153     if (IVersion > TecplotBinaryFileVersion)
2154         return IVersion; /* unsupported version */
2155     else if (IVersion == 0)
2156     {
2157         /* rewind to clear any errors and seek to the start offset */
2158         rewind(FileStream->File);
2159         IsOk = (TP_FSEEK(FileStream->File, StartOffset, SEEK_SET) == 0);
2160 
2161         if (IsOk && TP_FREAD(VersionString, 4, 1, FileStream->File) == 1)
2162         {
2163             /* try both native and foreign versions numbers */
2164             if (!GetDoubleVersion(VersionString, &FInputVersion, FileStream->IsByteOrderNative))
2165             {
2166                 FileStream->IsByteOrderNative = !FileStream->IsByteOrderNative; /* ...reverse the byte order */
2167                 IsOk = GetDoubleVersion(VersionString, &FInputVersion, FileStream->IsByteOrderNative);
2168             }
2169             if (IsOk)
2170                 IVersion = ROUNDS(FInputVersion * 10);
2171         }
2172     }
2173 
2174     if (IsOk)
2175         return (IVersion);
2176     else
2177         return ((short)0);
2178 }
2179 
2180 #if defined TECPLOTKERNEL
2181 /* CORE SOURCE CODE REMOVED */
2182 #if !defined ENGINE /* TODO(RMS)-H 12/12/2005: ENGINE: refactor to use just the Interrupted flag as-is */
2183 #else
2184 #endif
2185 #endif
2186 
2187 
2188 
2189 /**********************************************************************
2190  **********************************************************************
2191  **********************        OUTPUT        **************************
2192  **********************************************************************
2193  **********************************************************************/
2194 
2195 
2196 /**
2197  * Byte blocks cannot be unaligned or reversed in bytes
2198  */
WriteBinaryByteBlock(FileStream_s * FileStream,const Byte_t * ByteValues,const HgIndex_t NumValues)2199 Boolean_t WriteBinaryByteBlock(FileStream_s    *FileStream,
2200                                const Byte_t    *ByteValues,
2201                                const HgIndex_t  NumValues)
2202 {
2203     REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
2204     REQUIRE(VALID_REF(ByteValues));
2205     REQUIRE(NumValues >= 0);
2206 
2207     Boolean_t IsOk = TP_FWRITE(ByteValues,
2208                                sizeof(Byte_t),
2209                                (size_t)NumValues,
2210                                FileStream->File) == (size_t)NumValues;
2211 
2212     ENSURE(VALID_BOOLEAN(IsOk));
2213     return IsOk;
2214 }
2215 
2216 /**
2217  * Type Byte_t cannot be unaligned or reversed in byte order
2218  */
WriteBinaryByte(FileStream_s * FileStream,Byte_t ByteValue)2219 static inline Boolean_t WriteBinaryByte(FileStream_s *FileStream,
2220                                         Byte_t        ByteValue)
2221 {
2222     REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
2223     Boolean_t IsOk = WriteBinaryByteBlock(FileStream, &ByteValue, 1);
2224     ENSURE(VALID_BOOLEAN(IsOk));
2225     return IsOk;
2226 }
2227 
2228 /**
2229  */
2230 template <typename T>
CopyAndReverseUnalignedBytes(T * DstBuffer,const Byte_t * SrcBuffer)2231 void CopyAndReverseUnalignedBytes(T            *DstBuffer,
2232                                   const Byte_t *SrcBuffer)
2233 {
2234     REQUIRE(VALID_REF(DstBuffer));
2235     REQUIRE(VALID_REF(SrcBuffer));
2236     size_t typeSize = sizeof(T);
2237     for (size_t ii = 0; ii < typeSize; ii++)
2238         ((Byte_t *)(DstBuffer))[ii] = ((Byte_t *)(SrcBuffer))[typeSize-1-ii];
2239 }
2240 
2241 /**
2242  */
2243 template <typename T>
CopyUnalignedBytes(T * DstBuffer,const Byte_t * SrcBuffer)2244 void CopyUnalignedBytes(T            *DstBuffer,
2245                         const Byte_t *SrcBuffer)
2246 {
2247     REQUIRE(VALID_REF(DstBuffer));
2248     REQUIRE(VALID_REF(SrcBuffer));
2249     for (size_t ii = 0; ii < sizeof(T); ii++)
2250         ((Byte_t *)(DstBuffer))[ii] = ((Byte_t *)(SrcBuffer))[ii];
2251 }
2252 
2253 /**
2254  */
2255 template <typename T>
WriteBinaryDataUnaligned(FileStream_s * FileStream,const Byte_t * ValueBuffer,const Boolean_t ValueInNativeOrder)2256 Boolean_t WriteBinaryDataUnaligned(FileStream_s    *FileStream,
2257                                    const Byte_t    *ValueBuffer,
2258                                    const Boolean_t  ValueInNativeOrder)
2259 {
2260     REQUIRE(VALID_REF(FileStream) && VALID_FILE_HANDLE(FileStream->File));
2261     REQUIRE(VALID_REF(ValueBuffer));
2262     REQUIRE(VALID_BOOLEAN(ValueInNativeOrder));
2263 
2264     T DataValue;
2265     if (ValueInNativeOrder != FileStream->IsByteOrderNative)
2266         CopyAndReverseUnalignedBytes<T>(&DataValue, ValueBuffer);
2267     else
2268         CopyUnalignedBytes<T>(&DataValue, ValueBuffer);
2269 
2270     Boolean_t IsOk = TP_FWRITE(&DataValue, sizeof(T), 1, FileStream->File) == 1;
2271 
2272     ENSURE(VALID_BOOLEAN(IsOk));
2273     return IsOk;
2274 }
2275 
2276 
2277 /**
2278  * This is used in many places and requires the value be in proper order.
2279  */
WriteBinaryInt16(FileStream_s * FileStream,Int16_t Value)2280 Boolean_t WriteBinaryInt16(FileStream_s *FileStream,
2281                            Int16_t       Value)
2282 {
2283     Boolean_t IsOk;
2284     REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
2285     REQUIRE("Value can be any Int16_t");
2286     IsOk = WriteBinaryDataUnaligned<Int16_t>(FileStream, (Byte_t *) & Value, TRUE/*ValueInNativeOrder*/);
2287     ENSURE(VALID_BOOLEAN(IsOk));
2288     return IsOk;
2289 }
2290 
2291 /**
2292  * This is used in many places and requires the value be in proper order.
2293  */
WriteBinaryInt32(FileStream_s * FileStream,Int32_t Value)2294 Boolean_t WriteBinaryInt32(FileStream_s *FileStream,
2295                            Int32_t       Value)
2296 {
2297     Boolean_t IsOk;
2298     REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
2299     REQUIRE("Value can be any Int32_t");
2300     IsOk = WriteBinaryDataUnaligned<Int32_t>(FileStream, (Byte_t *) & Value, TRUE/*ValueInNativeOrder*/);
2301     ENSURE(VALID_BOOLEAN(IsOk));
2302     return IsOk;
2303 }
2304 
2305 /**
2306  */
2307 template <typename T>
WriteBinaryBlockUnaligned(FileStream_s * FileStream,const Byte_t * Values,const HgIndex_t NumValues,const Boolean_t ValuesInNativeOrdering)2308 Boolean_t WriteBinaryBlockUnaligned(FileStream_s    *FileStream,
2309                                     const Byte_t    *Values,
2310                                     const HgIndex_t  NumValues,
2311                                     const Boolean_t  ValuesInNativeOrdering)
2312 {
2313     Boolean_t IsOk = TRUE;
2314     Boolean_t WriteEachValueSeparately;
2315 
2316     REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
2317     REQUIRE(VALID_REF(Values));
2318     REQUIRE(NumValues >= 0);
2319     REQUIRE(VALID_BOOLEAN(ValuesInNativeOrdering));
2320 
2321     WriteEachValueSeparately = (ValuesInNativeOrdering != FileStream->IsByteOrderNative);
2322 
2323     if (WriteEachValueSeparately)
2324     {
2325         for (HgIndex_t NIndex = 0; IsOk && NIndex < NumValues; NIndex++)
2326         {
2327             IsOk = WriteBinaryDataUnaligned<T>(FileStream, Values + NIndex * sizeof(T), ValuesInNativeOrdering);
2328         }
2329     }
2330     else
2331     {
2332 #if 1
2333         size_t NumBytesToWrite = NumValues * sizeof(T);
2334         size_t NumBytesWritten = TP_FWRITE(Values, sizeof(Byte_t), NumBytesToWrite, FileStream->File);
2335         IsOk = NumBytesToWrite == NumBytesWritten;
2336 #else
2337         IsOk = WriteBinaryByteBlock(FileStream, Values, NumValues * sizeof(T));
2338 #endif
2339     }
2340 
2341     ENSURE(VALID_BOOLEAN(IsOk));
2342     return IsOk;
2343 }
2344 
2345 
2346 /**
2347  * Use Byte_t instead of Int16_t to support unaligned values
2348  */
WriteBinaryInt16BlockUnaligned(FileStream_s * FileStream,Byte_t * Int16Values,HgIndex_t NumValues,Boolean_t ValuesInNativeOrdering)2349 Boolean_t WriteBinaryInt16BlockUnaligned(FileStream_s *FileStream,
2350                                          Byte_t       *Int16Values,
2351                                          HgIndex_t     NumValues,
2352                                          Boolean_t     ValuesInNativeOrdering)
2353 {
2354     REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
2355     REQUIRE(VALID_REF(Int16Values));
2356     REQUIRE(NumValues >= 0);
2357     REQUIRE(VALID_BOOLEAN(ValuesInNativeOrdering));
2358 
2359     Boolean_t IsOk = WriteBinaryBlockUnaligned<Int16_t>(FileStream,
2360                                                         Int16Values,
2361                                                         NumValues,
2362                                                         ValuesInNativeOrdering);
2363     ENSURE(VALID_BOOLEAN(IsOk));
2364     return IsOk;
2365 }
2366 
2367 
2368 /**
2369  * Use Byte_t instead of Int32_t to support unaligned values
2370  */
WriteBinaryInt32BlockUnaligned(FileStream_s * FileStream,Byte_t * Int32Values,HgIndex_t NumValues,Boolean_t ValuesInNativeOrdering)2371 Boolean_t WriteBinaryInt32BlockUnaligned(FileStream_s *FileStream,
2372                                          Byte_t       *Int32Values,
2373                                          HgIndex_t     NumValues,
2374                                          Boolean_t     ValuesInNativeOrdering)
2375 {
2376     REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
2377     REQUIRE(VALID_REF(Int32Values));
2378     REQUIRE(NumValues >= 0);
2379     REQUIRE(VALID_BOOLEAN(ValuesInNativeOrdering));
2380 
2381     Boolean_t IsOk = WriteBinaryBlockUnaligned<Int32_t>(FileStream,
2382                                                         Int32Values,
2383                                                         NumValues,
2384                                                         ValuesInNativeOrdering);
2385     ENSURE(VALID_BOOLEAN(IsOk));
2386     return IsOk;
2387 }
2388 
2389 
2390 
2391 /**
2392  */
WriteBinaryReal(FileStream_s * FileStream,double RR,FieldDataType_e FieldDataType)2393 Boolean_t WriteBinaryReal(FileStream_s    *FileStream,
2394                           double           RR,
2395                           FieldDataType_e  FieldDataType)
2396 {
2397     Boolean_t IsOk = FALSE; /* ...quite compiler */
2398 
2399     REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
2400     REQUIRE((FieldDataType == FieldDataType_Float)  ||
2401             (FieldDataType == FieldDataType_Double) ||
2402             (FieldDataType == FieldDataType_Byte));
2403 
2404     switch (FieldDataType)
2405     {
2406         case FieldDataType_Float :
2407         {
2408             float FloatVal = CONVERT_DOUBLE_TO_FLOAT(RR);
2409             IsOk = WriteBinaryDataUnaligned<float>(FileStream, (Byte_t *) & FloatVal, TRUE/*NativeOrdering*/);
2410         } break;
2411         case FieldDataType_Double :
2412         {
2413             double DoubleVal = CLAMP_DOUBLE(RR);
2414             IsOk = WriteBinaryDataUnaligned<double>(FileStream, (Byte_t *) & DoubleVal, TRUE/*NativeOrdering*/);
2415         } break;
2416         case FieldDataType_Byte :
2417         {
2418             /* Note: type Byte cannot be unaligned or reversed in bytes */
2419             Byte_t B;
2420             if (RR > 255)
2421                 B = 255;
2422             else if (RR < 0)
2423                 B = 0;
2424             else
2425                 B = (Byte_t)RR;
2426             IsOk = WriteBinaryByte(FileStream, B);
2427         } break;
2428         default: CHECK(FALSE); break;
2429     }
2430 
2431     ENSURE(VALID_BOOLEAN(IsOk));
2432     return IsOk;
2433 }
2434 
2435 
WriteFieldDataType(FileStream_s * FileStream,FieldDataType_e FDT,Boolean_t WriteBinary)2436 Boolean_t WriteFieldDataType(FileStream_s    *FileStream,
2437                              FieldDataType_e  FDT,
2438                              Boolean_t        WriteBinary)
2439 {
2440     if (WriteBinary)
2441         return (WriteBinaryInt32(FileStream, (LgIndex_t)FDT));
2442     else
2443     {
2444         short S = 0;
2445         switch (FDT)
2446         {
2447             case FieldDataType_Float :  S = fprintf(FileStream->File, "SINGLE "); break;
2448             case FieldDataType_Double : S = fprintf(FileStream->File, "DOUBLE "); break;
2449             case FieldDataType_Int32 :  S = fprintf(FileStream->File, "LONGINT "); break;
2450             case FieldDataType_Int16 :  S = fprintf(FileStream->File, "SHORTINT "); break;
2451             case FieldDataType_Byte :   S = fprintf(FileStream->File, "BYTE "); break;
2452             case FieldDataType_Bit :    S = fprintf(FileStream->File, "BIT "); break;
2453             default: CHECK(FALSE);
2454         }
2455         return (FPRINTFOK(S));
2456     }
2457 }
2458 
2459 /**
2460  */
2461 template <typename T>
WriteBinaryChecksumByteValues(FileStream_s * FileStream,const Byte_t * ByteValues,const HgIndex_t NumValues)2462 Boolean_t WriteBinaryChecksumByteValues(FileStream_s   *FileStream,
2463                                         const Byte_t   *ByteValues,
2464                                         const HgIndex_t NumValues)
2465 {
2466     REQUIRE(VALID_REF(FileStream) && VALID_FILE_HANDLE(FileStream->File));
2467     REQUIRE(VALID_REF(ByteValues));
2468     REQUIRE(NumValues >= 1);
2469 
2470     Boolean_t IsOk;
2471     if (NumValues == 1)
2472         IsOk = WriteBinaryDataUnaligned<T>(FileStream, ByteValues, TRUE);
2473     else
2474         IsOk = WriteBinaryBlockUnaligned<T>(FileStream, ByteValues, NumValues, TRUE);
2475 
2476 #if defined TECPLOTKERNEL
2477 /* CORE SOURCE CODE REMOVED */
2478 #endif
2479     ENSURE(VALID_BOOLEAN(IsOk));
2480     return IsOk;
2481 }
2482 
2483 /**
2484  * For FieldData of Type Bit, use WriteBinaryFieldDataBlockOfTypeBit instead.
2485  */
2486 template <typename T>
WriteBinaryFieldDataBlockOfType(FileStream_s * FileStream,const FieldData_pa FieldData,const LgIndex_t StartOffset,const LgIndex_t NumValues)2487 Boolean_t WriteBinaryFieldDataBlockOfType(FileStream_s      *FileStream,
2488                                           const FieldData_pa FieldData,
2489                                           const LgIndex_t    StartOffset,
2490                                           const LgIndex_t    NumValues)
2491 {
2492 #if defined TECPLOTKERNEL
2493 /* CORE SOURCE CODE REMOVED */
2494 #endif
2495 
2496     Boolean_t IsOk = FALSE;
2497     if (IsFieldDataDirectAccessAllowed(FieldData))
2498     {
2499         Byte_t *ByteArray = GetFieldDataBytePtr(FieldData) + StartOffset * sizeof(T);
2500         IsOk = WriteBinaryChecksumByteValues<T>(FileStream, ByteArray, (HgIndex_t)NumValues);
2501     }
2502     else
2503     {
2504         for (LgIndex_t Offset = StartOffset; Offset < NumValues; Offset++)
2505         {
2506             T         ValueBuffer = (T)GetFieldValue(FieldData, Offset);
2507             Byte_t   *ByteValue = (Byte_t *) & ValueBuffer;
2508             IsOk = WriteBinaryChecksumByteValues<T>(FileStream, ByteValue, 1);
2509         }
2510     }
2511     ENSURE(VALID_BOOLEAN(IsOk));
2512     return IsOk;
2513 }
2514 
WriteBinaryFieldDataBlockOfTypeBit(FileStream_s * FileStream,const FieldData_pa FieldData,const LgIndex_t StartOffset,const LgIndex_t NumValues)2515 static Boolean_t WriteBinaryFieldDataBlockOfTypeBit(FileStream_s      *FileStream,
2516                                                     const FieldData_pa FieldData,
2517                                                     const LgIndex_t    StartOffset, /* Not used */
2518                                                     const LgIndex_t    NumValues)
2519 {
2520 #if defined TECPLOTKERNEL
2521 /* CORE SOURCE CODE REMOVED */
2522 #endif
2523 
2524     Boolean_t IsOk = FALSE;
2525     size_t NumBytes = 1 + (NumValues - 1) / 8;
2526     if (IsFieldDataDirectAccessAllowed(FieldData))
2527     {
2528         Byte_t *ByteArray = GetFieldDataBytePtr(FieldData);
2529         IsOk = WriteBinaryChecksumByteValues<Byte_t>(FileStream, ByteArray, (HgIndex_t)NumBytes);
2530     }
2531     else
2532     {
2533         // Bits are written out a Byte at a time and since we only come in here every 8th
2534         // bit, make sure to assemble a Byte value from the next 8 bits.
2535         for (LgIndex_t Offset = 0; Offset < NumValues; Offset += 8)
2536         {
2537             Byte_t ValueBuffer = 0;
2538             for (int ii = 0; ii < 8; ii++)
2539             {
2540                 Byte_t CurBit = (Byte_t)GetFieldValue(FieldData, Offset + ii);
2541                 ValueBuffer |= (CurBit << ii);
2542             }
2543             IsOk = WriteBinaryChecksumByteValues<Byte_t>(FileStream, &ValueBuffer, 1);
2544         }
2545     }
2546     ENSURE(VALID_BOOLEAN(IsOk));
2547     return IsOk;
2548 }
2549 
2550 /*
2551  */
WriteBinaryFieldDataBlock(FileStream_s * FileStream,FieldData_pa FieldData,LgIndex_t StartOffset,LgIndex_t NumValues)2552 Boolean_t WriteBinaryFieldDataBlock(FileStream_s *FileStream,
2553                                     FieldData_pa  FieldData,
2554                                     LgIndex_t     StartOffset,
2555                                     LgIndex_t     NumValues)
2556 {
2557 #if defined TECPLOTKERNEL
2558 /* CORE SOURCE CODE REMOVED */
2559 #endif
2560 
2561     Boolean_t IsOk = FALSE;
2562     switch (GetFieldDataType(FieldData))
2563     {
2564         case FieldDataType_Float  : IsOk = WriteBinaryFieldDataBlockOfType<float>(FileStream, FieldData, StartOffset, NumValues); break;
2565         case FieldDataType_Double : IsOk = WriteBinaryFieldDataBlockOfType<double>(FileStream, FieldData, StartOffset, NumValues); break;
2566         case FieldDataType_Int32  : IsOk = WriteBinaryFieldDataBlockOfType<Int32_t>(FileStream, FieldData, StartOffset, NumValues); break;
2567         case FieldDataType_Int16  : IsOk = WriteBinaryFieldDataBlockOfType<Int16_t>(FileStream, FieldData, StartOffset, NumValues); break;
2568         case FieldDataType_Byte   : IsOk = WriteBinaryFieldDataBlockOfType<Byte_t>(FileStream, FieldData, StartOffset, NumValues); break;
2569         case FieldDataType_Bit    : IsOk = WriteBinaryFieldDataBlockOfTypeBit(FileStream, FieldData, StartOffset, NumValues); break;
2570         default: CHECK(FALSE); break;
2571     }
2572 
2573     ENSURE(VALID_BOOLEAN(IsOk));
2574     return IsOk;
2575 }
2576 
2577 
WriteASCIIFieldDataValue(FileStream_s * FileStream,FieldData_pa FieldData,LgIndex_t Offset,SmInteger_t AsciiPrecision)2578 static Boolean_t WriteASCIIFieldDataValue(FileStream_s* FileStream,
2579                                           FieldData_pa  FieldData,
2580                                           LgIndex_t     Offset,
2581                                           SmInteger_t   AsciiPrecision)
2582 {
2583 #if defined TECPLOTKERNEL
2584 /* CORE SOURCE CODE REMOVED */
2585 #endif
2586 
2587     double V = GetFieldValue(FieldData, Offset);
2588 
2589     char buffer[100*MAX_SIZEOFUTF8CHAR];
2590     switch (GetFieldDataType(FieldData))
2591     {
2592         case FieldDataType_Float :
2593         case FieldDataType_Double :
2594             sprintf(buffer, " %.*E", (int)AsciiPrecision, V);
2595             break;
2596         case FieldDataType_Int32 :
2597             sprintf(buffer, " %*d", (int)AsciiPrecision, ROUNDL(V));
2598             break;
2599         case FieldDataType_Int16 :
2600             sprintf(buffer, " %6d", ROUND2(V));
2601             break;
2602         case FieldDataType_Byte :
2603             sprintf(buffer, " %3d", ROUNDS(V));
2604             break;
2605         case FieldDataType_Bit :
2606             sprintf(buffer, " %c", ((V == 0) ? '0' : '1'));
2607             break;
2608         default: CHECK(FALSE); break;
2609     }
2610 
2611     Boolean_t IsOk = FPRINTFOK(fprintf(FileStream->File, "%s", buffer));
2612 #if defined TECPLOTKERNEL
2613 /* CORE SOURCE CODE REMOVED */
2614 #endif
2615     ENSURE(VALID_BOOLEAN(IsOk));
2616     return IsOk;
2617 }
2618 
2619 
2620 /**
2621  */
WriteCCFieldDataBlock(FileStream_s * FileStream,FieldData_pa FieldData,Boolean_t IsOrderedData,LgIndex_t NumIPts,LgIndex_t NumJPts,LgIndex_t NumKPts,Boolean_t WriteBinary,SmInteger_t AsciiPrecision)2622 Boolean_t WriteCCFieldDataBlock(FileStream_s *FileStream,
2623                                 FieldData_pa  FieldData,
2624                                 Boolean_t     IsOrderedData,
2625                                 LgIndex_t     NumIPts,
2626                                 LgIndex_t     NumJPts,
2627                                 LgIndex_t     NumKPts,
2628                                 Boolean_t     WriteBinary,
2629                                 SmInteger_t   AsciiPrecision)
2630 {
2631     Boolean_t IsOk = TRUE;
2632     LgIndex_t NumValues;
2633     LgIndex_t I, J, K;
2634     LgIndex_t NumIJPts = -1;
2635     LgIndex_t IEnd     = -1;
2636     LgIndex_t JEnd     = -1;
2637     LgIndex_t KEnd     = -1;
2638     Boolean_t IsLinear = -1;
2639 
2640     REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
2641     REQUIRE(VALID_REF(FieldData));
2642     REQUIRE(VALID_BOOLEAN(IsOrderedData));
2643     REQUIRE(NumIPts >= 0);
2644     REQUIRE(NumJPts >= 0);
2645     REQUIRE(NumKPts >= 0);
2646     REQUIRE(VALID_BOOLEAN(WriteBinary));
2647     REQUIRE(IMPLICATION(!WriteBinary, AsciiPrecision >= 0));
2648 
2649     /*
2650      * As of version 103 Tecplot writes binary data files so that ordered cell
2651      * centered field data includes the ghost cells. This makes it much easier
2652      * for Tecplot to map the data when reading by simply writing out
2653      * FieldData->NumValues. As of version 104 the ghost cells of the slowest
2654      * moving index are not included but that does effect the output as it is
2655      * still FieldData->NumValues.
2656      */
2657     if (IsOrderedData && !WriteBinary)
2658     {
2659         /*
2660          * Ordered ASCII output is always layed out using
2661          * DataValueStructure_Classic format.
2662          */
2663         NumIJPts  = NumIPts * NumJPts;
2664         IEnd      = MAX(NumIPts - 1, 1);
2665         JEnd      = MAX(NumJPts - 1, 1);
2666         KEnd      = MAX(NumKPts - 1, 1);
2667         NumValues = (IEnd * JEnd * KEnd);
2668         IsLinear  = ((NumJPts == 1 && NumKPts == 1) ||
2669                      (NumIPts == 1 && NumKPts == 1) ||
2670                      (NumIPts == 1 && NumJPts == 1));
2671     }
2672     else
2673     {
2674         NumValues = GetFieldDataNumValues(FieldData);
2675     }
2676 
2677     if (WriteBinary)
2678     {
2679         IsOk = WriteBinaryFieldDataBlock(FileStream, FieldData, 0, NumValues);
2680     }
2681     else
2682     {
2683         LgIndex_t NumValuesPerLine = 80 / (AsciiPrecision + 5);
2684         if (IsOrderedData && !IsLinear)
2685         {
2686             LgIndex_t ValueIndex = 0;
2687             for (K = 0; K < KEnd && IsOk; K++)
2688                 for (J = 0; J < JEnd && IsOk; J++)
2689                     for (I = 0; I < IEnd && IsOk; I++)
2690                     {
2691                         LgIndex_t CellIndex = I + (J * NumIPts) + (K * NumIJPts);
2692                         IsOk = WriteASCIIFieldDataValue(FileStream,
2693                                                         FieldData,
2694                                                         CellIndex,
2695                                                         AsciiPrecision);
2696                         if ((ValueIndex + 1) % NumValuesPerLine == 0 || ValueIndex == NumValues - 1)
2697                             IsOk = (fputc('\n', FileStream->File) != EOF);
2698                         ValueIndex++;
2699                     }
2700         }
2701         else
2702         {
2703             for (I = 0; I < NumValues && IsOk; I++)
2704             {
2705                 IsOk = WriteASCIIFieldDataValue(FileStream,
2706                                                 FieldData,
2707                                                 I,
2708                                                 AsciiPrecision);
2709                 if ((I + 1) % NumValuesPerLine == 0 || I == NumValues - 1)
2710                     IsOk = (fputc('\n', FileStream->File) != EOF);
2711             }
2712         }
2713     }
2714 
2715     ENSURE(VALID_BOOLEAN(IsOk));
2716     return IsOk;
2717 }
2718 
2719 
DumpDatafileString(FileStream_s * FileStream,const char * S,Boolean_t WriteBinary)2720 Boolean_t DumpDatafileString(FileStream_s *FileStream,
2721                              const char   *S,
2722                              Boolean_t     WriteBinary)
2723 {
2724     Boolean_t IsOk = TRUE;
2725     const char *CPtr = S;
2726     if (WriteBinary)
2727     {
2728         const char *CPtr = S;
2729         while (IsOk && CPtr && *CPtr)
2730             IsOk = WriteBinaryInt32(FileStream, (LgIndex_t)(unsigned char) * CPtr++);
2731         if (IsOk)
2732             IsOk = WriteBinaryInt32(FileStream, 0);
2733     }
2734     else
2735     {
2736         fputc('"', FileStream->File);
2737         while (CPtr && *CPtr)
2738         {
2739             if (*CPtr == '\n')
2740             {
2741                 CPtr++;
2742                 fputc('\\', FileStream->File);
2743                 fputc('\\', FileStream->File);
2744                 fputc('n', FileStream->File);
2745             }
2746             else
2747             {
2748                 if ((*CPtr == '"') || (*CPtr == '\\'))
2749                     fputc('\\', FileStream->File);
2750                 fputc(*CPtr++, FileStream->File);
2751             }
2752         }
2753         fputc('"', FileStream->File);
2754         IsOk = (fputc('\n', FileStream->File) != EOF);
2755     }
2756     return (IsOk);
2757 }
2758 
2759 
WriteAsciiColor(FILE * File,ColorIndex_t Color)2760 static void WriteAsciiColor(FILE        *File,
2761                             ColorIndex_t Color)
2762 {
2763     if (Color >= FirstCustomColor && Color <= LastCustomColor)
2764         fprintf(File, "CUST%1d ", Color - FirstCustomColor + 1);
2765     else
2766     {
2767         switch (Color)
2768         {
2769             case Black_C  : fprintf(File, "BLACK "); break;
2770             case Red_C    : fprintf(File, "RED "); break;
2771             case Green_C  : fprintf(File, "GREEN "); break;
2772             case Blue_C   : fprintf(File, "BLUE "); break;
2773             case Cyan_C   : fprintf(File, "CYAN "); break;
2774             case Yellow_C : fprintf(File, "YELLOW "); break;
2775             case Purple_C : fprintf(File, "PURPLE "); break;
2776             case White_C  : fprintf(File, "WHITE "); break;
2777         }
2778     }
2779 }
2780 
WriteAsciiTextGeomBasics(FILE * File,CoordSys_e CoordSys,Boolean_t AttachToZone,EntIndex_t Zone,ColorIndex_t Color,Scope_e Scope,Boolean_t IncludeZ,Boolean_t WriteGridDataAsPolar,AnchorPos_u const * AnchorPos,double ScaleFact)2781 static void WriteAsciiTextGeomBasics(FILE*              File,
2782                                      CoordSys_e         CoordSys,
2783                                      Boolean_t          AttachToZone,
2784                                      EntIndex_t         Zone,
2785                                      ColorIndex_t       Color,
2786                                      Scope_e            Scope,
2787                                      Boolean_t          IncludeZ,
2788                                      Boolean_t          WriteGridDataAsPolar,
2789                                      AnchorPos_u const* AnchorPos,
2790                                      double             ScaleFact)
2791 {
2792     REQUIRE(VALID_REF(File));
2793     REQUIRE(VALID_TEXT_COORDSYS(CoordSys) || VALID_GEOM_COORDSYS(CoordSys));
2794     REQUIRE(VALID_BOOLEAN(AttachToZone));
2795     REQUIRE(IMPLICATION(AttachToZone, Zone >= 0));
2796     REQUIRE(VALID_ENUM(Scope, Scope_e));
2797     REQUIRE(VALID_BOOLEAN(IncludeZ));
2798     REQUIRE(VALID_BOOLEAN(WriteGridDataAsPolar));
2799     REQUIRE(VALID_REF(AnchorPos));
2800 
2801     fprintf(File, "CS=");
2802     if (CoordSys == CoordSys_Frame)
2803         fprintf(File, "FRAME");
2804     else if (CoordSys == CoordSys_Grid)
2805         fprintf(File, "GRID");
2806     /*
2807      * Not currently used
2808      *
2809     else if (CoordSys == CoordSys_FrameOffset)
2810       fprintf(File,"FRAMEOFFSET");
2811      */
2812     else if (CoordSys == CoordSys_Grid3D)
2813         fprintf(File, "GRID3D");
2814     else
2815         CHECK(FALSE);
2816 
2817     if (CoordSys == CoordSys_Grid && !IncludeZ && WriteGridDataAsPolar)
2818     {
2819         fprintf(File, "\nTHETA=%.12G,R=%.12G",
2820                 ScaleFact*AnchorPos->ThetaR.Theta,
2821                 ScaleFact*AnchorPos->ThetaR.R);
2822         CHECK(!IncludeZ);
2823     }
2824     else
2825     {
2826         fprintf(File, "\nX=%.12G,Y=%.12G",
2827                 ScaleFact*AnchorPos->XYZ.X,
2828                 ScaleFact*AnchorPos->XYZ.Y);
2829         if (IncludeZ)
2830             fprintf(File, ",Z=%.12G", ScaleFact*AnchorPos->XYZ.Z);
2831     }
2832 
2833     if (AttachToZone)
2834         fprintf(File, "\nZN=%d", Zone + 1);
2835 
2836     fprintf(File, "\nC=");
2837     WriteAsciiColor(File, Color);
2838 
2839     fprintf(File, "\nS=");
2840     if (Scope == Scope_Global)
2841         fprintf(File, "GLOBAL");
2842     else if (Scope == Scope_Local)
2843         fprintf(File, "LOCAL");
2844     else
2845         CHECK(FALSE);
2846 
2847     fputc('\n', File);
2848 }
2849 
2850 
DumpGeometry(FileStream_s * FileStream,Geom_s const * Geom,Boolean_t WriteBinary,Boolean_t WriteGridDataAsPolar)2851 bool DumpGeometry(FileStream_s* FileStream,
2852                   Geom_s const* Geom,
2853                   Boolean_t     WriteBinary,
2854                   Boolean_t     WriteGridDataAsPolar)
2855 {
2856     LgIndex_t       I, Index;
2857     LgIndex_t       SegIndex;
2858     bool            IsOk = TRUE;
2859     FieldDataType_e FDT;
2860 
2861     REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
2862     REQUIRE(VALID_REF(Geom));
2863     REQUIRE(Geom->GeomType != GeomType_Image);
2864 
2865     if (WriteBinary)
2866     {
2867         WriteBinaryReal(FileStream, GeomMarker, FieldDataType_Float);
2868         if (Geom->PositionCoordSys == CoordSys_Grid)
2869             WriteBinaryInt32(FileStream, 0);
2870         else if (Geom->PositionCoordSys == CoordSys_Frame)
2871             WriteBinaryInt32(FileStream, 1);
2872 #if 0 /*
2873         * Not currently used
2874         */
2875         else if (Geom->PositionCoordSys == CoordSys_FrameOffset)
2876             WriteBinaryInt32(FileStream, 2);
2877 #endif
2878         /*
2879          * PositionCoordSys == 3 is for old window coordinate system
2880          */
2881         else if (Geom->PositionCoordSys == CoordSys_Grid3D)
2882             WriteBinaryInt32(FileStream, 4);
2883         else
2884             CHECK(FALSE);
2885 
2886         WriteBinaryInt32(FileStream, (LgIndex_t)Geom->Scope);
2887         WriteBinaryInt32(FileStream, (LgIndex_t)Geom->DrawOrder);
2888         WriteBinaryReal(FileStream, Geom->AnchorPos.Generic.V1, FieldDataType_Double);
2889         WriteBinaryReal(FileStream, Geom->AnchorPos.Generic.V2, FieldDataType_Double);
2890         WriteBinaryReal(FileStream, Geom->AnchorPos.Generic.V3, FieldDataType_Double);
2891         if (Geom->AttachToZone)
2892             WriteBinaryInt32(FileStream, (LgIndex_t)Geom->Zone);
2893         else
2894             WriteBinaryInt32(FileStream, (LgIndex_t) - 1);
2895         WriteBinaryInt32(FileStream, (LgIndex_t)Geom->BColor);
2896         WriteBinaryInt32(FileStream, (LgIndex_t)Geom->FillBColor);
2897         WriteBinaryInt32(FileStream, (LgIndex_t)Geom->IsFilled);
2898         CHECK(Geom->GeomType != GeomType_LineSegs3D); /* deprecated */
2899         WriteBinaryInt32(FileStream, (LgIndex_t)Geom->GeomType);
2900         WriteBinaryInt32(FileStream, (LgIndex_t)Geom->LinePattern);
2901         WriteBinaryReal(FileStream, Geom->PatternLength, FieldDataType_Double);
2902         WriteBinaryReal(FileStream, Geom->LineThickness, FieldDataType_Double);
2903         WriteBinaryInt32(FileStream, (LgIndex_t)Geom->NumEllipsePts);
2904         WriteBinaryInt32(FileStream, (LgIndex_t)Geom->ArrowheadStyle);
2905         WriteBinaryInt32(FileStream, (LgIndex_t)Geom->ArrowheadAttachment);
2906         WriteBinaryReal(FileStream, Geom->ArrowheadSize, FieldDataType_Double);
2907 
2908         WriteBinaryReal(FileStream, Geom->ArrowheadAngle, FieldDataType_Double);
2909 
2910         /* MACRO FUNCTION COMMAND */
2911         DumpDatafileString(FileStream, Geom->MacroFunctionCommand, TRUE);
2912 
2913         /*
2914          *  Assume geometry has X,Y (and Z) all using same field
2915          *  data type.
2916          */
2917         FDT = GetGeomFieldDataType(Geom);
2918         WriteFieldDataType(FileStream, FDT, TRUE);
2919         WriteBinaryInt32(FileStream, (LgIndex_t)Geom->Clipping);
2920 
2921         if (Geom->GeomType == GeomType_LineSegs)
2922         {
2923             short S;
2924             WriteBinaryInt32(FileStream, Geom->NumSegments);
2925             I = 0;
2926             for (S = 0; IsOk && (S < Geom->NumSegments); S++)
2927             {
2928                 WriteBinaryInt32(FileStream, Geom->NumSegPts[S]);
2929                 WriteBinaryFieldDataBlock(FileStream, Geom->GeomData.Generic.V1Base, I, Geom->NumSegPts[S]);
2930                 IsOk = WriteBinaryFieldDataBlock(FileStream, Geom->GeomData.Generic.V2Base, I, Geom->NumSegPts[S]) == TRUE;
2931                 if (Geom->PositionCoordSys == CoordSys_Grid3D)
2932                     IsOk = WriteBinaryFieldDataBlock(FileStream, Geom->GeomData.Generic.V3Base, I, Geom->NumSegPts[S]) == TRUE;
2933                 I += Geom->NumSegPts[S];
2934             }
2935         }
2936         else if (Geom->GeomType == GeomType_Rectangle ||
2937                  Geom->GeomType == GeomType_Ellipse)
2938         {
2939             WriteBinaryReal(FileStream, GetFieldValue(Geom->GeomData.XYZ.XBase, 0), FDT);
2940             IsOk = WriteBinaryReal(FileStream, GetFieldValue(Geom->GeomData.XYZ.YBase, 0), FDT) == TRUE;
2941         }
2942         else
2943         {
2944             CHECK((Geom->GeomType == GeomType_Square) ||
2945                   (Geom->GeomType == GeomType_Circle));
2946             IsOk = WriteBinaryReal(FileStream, GetFieldValue(Geom->GeomData.XYZ.XBase, 0), FDT) == TRUE;
2947         }
2948 
2949     }
2950     else
2951     {
2952         double ScaleFact;
2953         if (Geom->PositionCoordSys == CoordSys_Frame)
2954             ScaleFact = 100.0;
2955         else
2956             ScaleFact = 1.0;
2957 
2958         fprintf(FileStream->File, "GEOMETRY\nF=POINT\n");
2959         WriteAsciiTextGeomBasics(FileStream->File,
2960                                  Geom->PositionCoordSys,
2961                                  Geom->AttachToZone,
2962                                  Geom->Zone,
2963                                  Geom->BColor,
2964                                  Geom->Scope,
2965                                  TRUE,
2966                                  WriteGridDataAsPolar,
2967                                  &Geom->AnchorPos,
2968                                  ScaleFact);
2969 
2970         switch (Geom->LinePattern)
2971         {
2972             case LinePattern_Solid      : fprintf(FileStream->File, "L=SOLID\n"); break;
2973             case LinePattern_Dashed     : fprintf(FileStream->File, "L=DASHED\n"); break;
2974             case LinePattern_DashDot    : fprintf(FileStream->File, "L=DASHDOT\n"); break;
2975             case LinePattern_Dotted     : fprintf(FileStream->File, "L=DOTTED\n"); break;
2976             case LinePattern_LongDash   : fprintf(FileStream->File, "L=LONGDASH\n"); break;
2977             case LinePattern_DashDotDot : fprintf(FileStream->File, "L=DASHDOTDOT\n"); break;
2978             default: CHECK(FALSE); break;
2979         }
2980         fprintf(FileStream->File, "PL=%.12G\n",
2981                 Geom->PatternLength*PatternLengthInputSpec.InterfaceAdjust.ScaleFact);
2982         fprintf(FileStream->File, "LT=%.12G\n",
2983                 Geom->LineThickness*LineThicknessInputSpec.InterfaceAdjust.ScaleFact);
2984 
2985         if (Geom->IsFilled)
2986         {
2987             fprintf(FileStream->File, "FC=");
2988             WriteAsciiColor(FileStream->File, Geom->FillBColor);
2989         }
2990 
2991         if (Geom->Clipping == Clipping_ClipToViewport)
2992             fprintf(FileStream->File, "CLIPPING=CLIPTOVIEWPORT\n");
2993         else if (Geom->Clipping == Clipping_ClipToFrame)
2994             fprintf(FileStream->File, "CLIPPING=CLIPTOFRAME\n");
2995         else
2996             CHECK(FALSE);
2997 
2998         if (Geom->DrawOrder == DrawOrder_AfterData)
2999             fprintf(FileStream->File, "DRAWORDER=AFTERDATA\n");
3000         else if (Geom->DrawOrder == DrawOrder_BeforeData)
3001             fprintf(FileStream->File, "DRAWORDER=BEFOREDATA\n");
3002         else
3003             CHECK(FALSE);
3004 
3005         /* Macro function command */
3006         fprintf(FileStream->File, "MFC=");
3007         DumpDatafileString(FileStream, Geom->MacroFunctionCommand, FALSE);
3008 
3009         if ((Geom->GeomType == GeomType_Circle) || (Geom->GeomType == GeomType_Ellipse))
3010             fprintf(FileStream->File, "EP=%ld\n", (long)Geom->NumEllipsePts);
3011 
3012         if (Geom->GeomType == GeomType_LineSegs && Geom->PositionCoordSys != CoordSys_Grid3D)
3013         {
3014             switch (Geom->ArrowheadStyle)
3015             {
3016                 case ArrowheadStyle_Plain  : fprintf(FileStream->File, "AST=PLAIN\n"); break;
3017                 case ArrowheadStyle_Filled : fprintf(FileStream->File, "AST=FILLED\n"); break;
3018                 case ArrowheadStyle_Hollow : fprintf(FileStream->File, "AST=HOLLOW\n"); break;
3019                 default: CHECK(FALSE); break;
3020             }
3021 
3022             switch (Geom->ArrowheadAttachment)
3023             {
3024                 case ArrowheadAttachment_None        : break;
3025                 case ArrowheadAttachment_AtBeginning : fprintf(FileStream->File, "AAT=BEGINNING\n"); break;
3026                 case ArrowheadAttachment_AtEnd       : fprintf(FileStream->File, "AAT=END\n"); break;
3027                 case ArrowheadAttachment_AtBothEnds  : fprintf(FileStream->File, "AAT=BOTH\n"); break;
3028                 default: CHECK(FALSE); break;
3029             }
3030             if (Geom->ArrowheadAttachment != ArrowheadAttachment_None)
3031             {
3032                 fprintf(FileStream->File, "ASZ=%.12G\n",
3033                         Geom->ArrowheadSize*ArrowheadSizeInputSpec.InterfaceAdjust.ScaleFact);
3034                 fprintf(FileStream->File, "AAN=%.12G\n",
3035                         Geom->ArrowheadAngle*ArrowheadAngleInputSpec.InterfaceAdjust.ScaleFact);
3036             }
3037         }
3038 
3039         switch (Geom->GeomType)
3040         {
3041             case GeomType_LineSegs :
3042             {
3043                 fprintf(FileStream->File, "T=LINE\n");
3044                 fprintf(FileStream->File, "DT=");
3045                 WriteFieldDataType(FileStream, GetFieldDataType(Geom->GeomData.Generic.V1Base), FALSE);
3046                 fputc('\n', FileStream->File);
3047                 fprintf(FileStream->File, "%d\n", (int)Geom->NumSegments);
3048                 SegIndex = 0;
3049                 for (I = 0; IsOk && (I < Geom->NumSegments); I++)
3050                 {
3051                     fprintf(FileStream->File, "%ld\n", (long)Geom->NumSegPts[I]);
3052                     for (Index = 0; Index < Geom->NumSegPts[I]; Index++)
3053                     {
3054                         fprintf(FileStream->File, "%.12G ", GetFieldValue(Geom->GeomData.Generic.V1Base, SegIndex + Index)*ScaleFact);
3055                         fprintf(FileStream->File, "%.12G", GetFieldValue(Geom->GeomData.Generic.V2Base, SegIndex + Index)*ScaleFact);
3056                         if (Geom->PositionCoordSys == CoordSys_Grid3D)
3057                             IsOk = FPRINTFOK(fprintf(FileStream->File, " %.12G\n", GetFieldValue(Geom->GeomData.Generic.V3Base, SegIndex + Index)));
3058                         else
3059                             IsOk = (Boolean_t)(fputc('\n', FileStream->File) != EOF);
3060                     }
3061                     SegIndex += Geom->NumSegPts[I];
3062                 }
3063             } break;
3064             case GeomType_Rectangle :
3065             {
3066                 fprintf(FileStream->File, "T=RECTANGLE %.12G %.12G\n",
3067                         GetFieldValue(Geom->GeomData.XYZ.XBase, 0)*ScaleFact,
3068                         GetFieldValue(Geom->GeomData.XYZ.YBase, 0)*ScaleFact);
3069             } break;
3070             case GeomType_Square :
3071             {
3072                 fprintf(FileStream->File, "T=SQUARE %.12G\n",
3073                         GetFieldValue(Geom->GeomData.XYZ.XBase, 0)*ScaleFact);
3074             } break;
3075             case GeomType_Circle :
3076             {
3077                 fprintf(FileStream->File, "T=CIRCLE %.12G\n",
3078                         GetFieldValue(Geom->GeomData.XYZ.XBase, 0)*ScaleFact);
3079             } break;
3080             case GeomType_Ellipse :
3081             {
3082                 fprintf(FileStream->File, "T=ELLIPSE %.12G %.12G\n",
3083                         GetFieldValue(Geom->GeomData.XYZ.XBase, 0)*ScaleFact,
3084                         GetFieldValue(Geom->GeomData.XYZ.YBase, 0)*ScaleFact);
3085             } break;
3086             default: CHECK(FALSE);
3087         }
3088     }
3089     return IsOk;
3090 }
3091 
3092 /**
3093  */
DumpText(FileStream_s * FileStream,Text_s const * Text,Boolean_t WriteBinary,Boolean_t WriteGridDataAsPolar)3094 bool DumpText(FileStream_s* FileStream,
3095               Text_s const* Text,
3096               Boolean_t     WriteBinary,
3097               Boolean_t     WriteGridDataAsPolar)
3098 {
3099     REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
3100     REQUIRE(VALID_REF(Text));
3101     REQUIRE(VALID_BOOLEAN(WriteBinary));
3102     REQUIRE(VALID_BOOLEAN(WriteGridDataAsPolar));
3103 
3104     if (WriteBinary)
3105     {
3106         WriteBinaryReal(FileStream, TextMarker, FieldDataType_Float);
3107         if (Text->PositionCoordSys == CoordSys_Grid)
3108             WriteBinaryInt32(FileStream, 0);
3109         else if (Text->PositionCoordSys == CoordSys_Frame)
3110             WriteBinaryInt32(FileStream, 1);
3111 #if 0 /*
3112         * Not currently used
3113         */
3114         else if (Geom->PositionCoordSys == CoordSys_FrameOffset)
3115             WriteBinaryInt32(FileStream, 2);
3116 #endif
3117         /*
3118          * 3 is used for old window coordinate system
3119          */
3120         else if (Text->PositionCoordSys == CoordSys_Grid3D)
3121             WriteBinaryInt32(FileStream, 4);
3122         else
3123             CHECK(FALSE);
3124 
3125         WriteBinaryInt32(FileStream, (LgIndex_t)Text->Scope);
3126         WriteBinaryReal(FileStream, Text->AnchorPos.Generic.V1, FieldDataType_Double);
3127         WriteBinaryReal(FileStream, Text->AnchorPos.Generic.V2, FieldDataType_Double);
3128         WriteBinaryReal(FileStream, Text->AnchorPos.Generic.V3, FieldDataType_Double);
3129         #if defined TECPLOTKERNEL
3130 /* CORE SOURCE CODE REMOVED */
3131         #else
3132         {
3133             WriteBinaryInt32(FileStream, static_cast<LgIndex_t>(Text->TextShape.Font));
3134         }
3135         #endif
3136         WriteBinaryInt32(FileStream, (LgIndex_t)Text->TextShape.SizeUnits);
3137         WriteBinaryReal(FileStream, Text->TextShape.Height, FieldDataType_Double);
3138         WriteBinaryInt32(FileStream, (LgIndex_t)Text->Box.BoxType);
3139         WriteBinaryReal(FileStream, Text->Box.Margin, FieldDataType_Double);
3140         WriteBinaryReal(FileStream, Text->Box.LineThickness, FieldDataType_Double);
3141         WriteBinaryInt32(FileStream, (LgIndex_t)Text->Box.BColor);
3142         WriteBinaryInt32(FileStream, (LgIndex_t)Text->Box.FillBColor);
3143         WriteBinaryReal(FileStream, Text->Angle, FieldDataType_Double);
3144         WriteBinaryReal(FileStream, Text->LineSpacing, FieldDataType_Double);
3145         WriteBinaryInt32(FileStream, (LgIndex_t)Text->Anchor);
3146         if (Text->AttachToZone)
3147             WriteBinaryInt32(FileStream, (LgIndex_t)Text->Zone);
3148         else
3149             WriteBinaryInt32(FileStream, (LgIndex_t) - 1);
3150         WriteBinaryInt32(FileStream, (LgIndex_t)Text->BColor);
3151     }
3152     else
3153     {
3154         double ScaleFact;
3155         Boolean_t IncludeZ = Text->PositionCoordSys == CoordSys_Grid3D;
3156         if (Text->PositionCoordSys == CoordSys_Frame)
3157             ScaleFact = 100.0;
3158         else
3159             ScaleFact = 1.0;
3160         fprintf(FileStream->File, "TEXT\n");
3161         WriteAsciiTextGeomBasics(FileStream->File,
3162                                  Text->PositionCoordSys,
3163                                  Text->AttachToZone,
3164                                  Text->Zone,
3165                                  Text->BColor,
3166                                  Text->Scope,
3167                                  IncludeZ,
3168                                  WriteGridDataAsPolar,
3169                                  &Text->AnchorPos,
3170                                  ScaleFact);
3171         fprintf(FileStream->File, "HU=");
3172         switch (Text->TextShape.SizeUnits)
3173         {
3174             case Units_Grid  : fprintf(FileStream->File, "GRID\n"); break;
3175             case Units_Frame : fprintf(FileStream->File, "FRAME\n"); break;
3176             case Units_Point : fprintf(FileStream->File, "POINT\n"); break;
3177             case Units_AxisPercentage : /* Not allowed */
3178             default: CHECK(FALSE); break;
3179         }
3180 
3181         fprintf(FileStream->File, "LS=%.4G ", Text->LineSpacing);
3182 
3183         fprintf(FileStream->File, "AN=");
3184         switch (Text->Anchor)
3185         {
3186             case TextAnchor_Left       : fprintf(FileStream->File, "LEFT\n");        break;
3187             case TextAnchor_Center     : fprintf(FileStream->File, "CENTER\n");      break;
3188             case TextAnchor_Right      : fprintf(FileStream->File, "RIGHT\n");       break;
3189             case TextAnchor_MidLeft    : fprintf(FileStream->File, "MIDLEFT\n");     break;
3190             case TextAnchor_MidCenter  : fprintf(FileStream->File, "MIDCENTER\n");   break;
3191             case TextAnchor_MidRight   : fprintf(FileStream->File, "MIDRIGHT\n");    break;
3192             case TextAnchor_HeadLeft   : fprintf(FileStream->File, "HEADLEFT\n");    break;
3193             case TextAnchor_HeadCenter : fprintf(FileStream->File, "HEADCENTER\n");  break;
3194             case TextAnchor_HeadRight  : fprintf(FileStream->File, "HEADRIGHT\n");   break;
3195             default: CHECK(FALSE); break;
3196         }
3197 
3198         switch (Text->Box.BoxType)
3199         {
3200             case TextBox_Hollow : fprintf(FileStream->File, "BX=Hollow "); break;
3201             case TextBox_Filled : fprintf(FileStream->File, "BX=Filled "); break;
3202             default :;
3203         }
3204         fprintf(FileStream->File, "BXM=%.4G ", Text->Box.Margin*100);
3205         fprintf(FileStream->File, "LT=%.4G ", Text->Box.LineThickness*100.0);
3206         fprintf(FileStream->File, "BXO="); WriteAsciiColor(FileStream->File, Text->Box.BColor);
3207         fprintf(FileStream->File, "BXF="); WriteAsciiColor(FileStream->File, Text->Box.FillBColor);
3208 
3209         fprintf(FileStream->File, "\nF=");
3210 
3211         Font_e font;
3212         #if defined TECPLOTKERNEL
3213 /* CORE SOURCE CODE REMOVED */
3214         #else
3215         {
3216             font = Text->TextShape.Font;
3217         }
3218         #endif
3219         switch (font)
3220         {
3221             case Font_Helvetica     :   fprintf(FileStream->File, "HELV");         break;
3222             case Font_HelveticaBold :   fprintf(FileStream->File, "HELV-BOLD");    break;
3223             case Font_Times    :        fprintf(FileStream->File, "TIMES");        break;
3224             case Font_TimesBold:        fprintf(FileStream->File, "TIMES-BOLD");   break;
3225             case Font_TimesItalic :     fprintf(FileStream->File, "TIMES-ITALIC"); break;
3226             case Font_TimesItalicBold : fprintf(FileStream->File, "TIMES-ITALIC-BOLD"); break;
3227             case Font_Courier  :        fprintf(FileStream->File, "COURIER");      break;
3228             case Font_CourierBold  :    fprintf(FileStream->File, "COURIER-BOLD"); break;
3229             case Font_Greek    :        fprintf(FileStream->File, "GREEK");        break;
3230             case Font_Math     :        fprintf(FileStream->File, "MATH");         break;
3231             case Font_UserDefined  :    fprintf(FileStream->File, "USER-DEF");     break;
3232             default: CHECK(FALSE); break;
3233         }
3234         if (Text->TextShape.SizeUnits == Units_Frame)
3235             ScaleFact = 100.0;
3236         else
3237             ScaleFact = 1.0;
3238         fprintf(FileStream->File, "\nH=%.12G A=%.12G",
3239                 Text->TextShape.Height*ScaleFact,
3240                 Text->Angle*DEGPERRADIANS);
3241     }
3242 
3243 
3244     if (!WriteBinary)
3245         fprintf(FileStream->File, "\nMFC=");
3246 
3247     DumpDatafileString(FileStream, Text->MacroFunctionCommand, WriteBinary);
3248 
3249     if (!WriteBinary)
3250     {
3251         if (Text->Clipping == Clipping_ClipToViewport)
3252             fprintf(FileStream->File, "CLIPPING=CLIPTOVIEWPORT\n");
3253         else if (Text->Clipping == Clipping_ClipToFrame)
3254             fprintf(FileStream->File, "CLIPPING=CLIPTOFRAME\n");
3255         else
3256             CHECK(FALSE);
3257     }
3258     else
3259     {
3260         WriteBinaryInt32(FileStream, (LgIndex_t)Text->Clipping);
3261     }
3262 
3263     if (!WriteBinary)
3264         fprintf(FileStream->File, "T=");
3265 
3266     return DumpDatafileString(FileStream, Text->Text, WriteBinary) == TRUE;
3267 }
3268 
DumpCustomAxisLabels(FileStream_s * FileStream,Boolean_t WriteBinary,StringList_pa LabelBase)3269 Boolean_t DumpCustomAxisLabels(FileStream_s  *FileStream,
3270                                Boolean_t      WriteBinary,
3271                                StringList_pa  LabelBase)
3272 {
3273     Boolean_t IsOk = TRUE;
3274     LgIndex_t Index = 0;
3275     LgIndex_t Count = 0;
3276 
3277     REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
3278     REQUIRE(VALID_BOOLEAN(WriteBinary));
3279     REQUIRE(StringListValid(LabelBase));
3280 
3281     Count = StringListCount(LabelBase);
3282     if (WriteBinary)
3283     {
3284         WriteBinaryReal(FileStream, CustomLabelMarker, FieldDataType_Float);
3285         WriteBinaryInt32(FileStream, Count);
3286     }
3287     else
3288     {
3289         fprintf(FileStream->File, " CUSTOMLABELS = \n");
3290     }
3291 
3292     for (Index = 0, IsOk = TRUE; Index < Count && IsOk; Index++)
3293     {
3294         const char *CurLabel = StringListGetStringRef(LabelBase, Index);
3295         IsOk = DumpDatafileString(FileStream, CurLabel, WriteBinary);
3296     }
3297 
3298     ENSURE(VALID_BOOLEAN(IsOk));
3299     return IsOk;
3300 }
3301 
3302 /**
3303  */
WriteBinaryMagic(FileStream_s * FileStream)3304 Boolean_t WriteBinaryMagic(FileStream_s *FileStream)
3305 {
3306     /*
3307      * Write an integer value of 1 to the file.  This is used
3308      * by the reader to determine byte order of the file.
3309      */
3310     return (WriteBinaryInt32(FileStream, 1));
3311 }
3312 
3313 /**
3314  */
writeBinaryVersionNumber(FileStream_s & fileStream,int versionNumber)3315 bool writeBinaryVersionNumber(FileStream_s& fileStream,
3316                               int           versionNumber)
3317 {
3318     char buffer[5];
3319     sprintf(buffer,
3320             "V%-3d",
3321             versionNumber);
3322     CHECK(strlen(buffer) == 4);
3323     return fprintf(fileStream.File,
3324                    "#!TD%s",
3325                    buffer) > 0;
3326 }
3327 
3328 #if defined TECPLOTKERNEL
3329 /* CORE SOURCE CODE REMOVED */
3330 #if !defined SUN
3331 #else
3332 #endif
3333 #if !defined NO_ASSERTS
3334 #endif
3335             #if defined ALLOW_USERDEF_NO_NEIGHBORING_ELEMENT
3336             #else
3337             #endif
3338 #if 0 /* not used yet */
3339 #endif
3340 #endif
3341