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