/* * NOTICE and LICENSE for Tecplot Input/Output Library (TecIO) - OpenFOAM * * Copyright (C) 1988-2009 Tecplot, Inc. All rights reserved worldwide. * * Tecplot hereby grants OpenCFD limited authority to distribute without * alteration the source code to the Tecplot Input/Output library, known * as TecIO, as part of its distribution of OpenFOAM and the * OpenFOAM_to_Tecplot converter. Users of this converter are also hereby * granted access to the TecIO source code, and may redistribute it for the * purpose of maintaining the converter. However, no authority is granted * to alter the TecIO source code in any form or manner. * * This limited grant of distribution does not supersede Tecplot, Inc.'s * copyright in TecIO. Contact Tecplot, Inc. for further information. * * Tecplot, Inc. * 3535 Factoria Blvd, Ste. 550 * Bellevue, WA 98006, USA * Phone: +1 425 653 1200 * http://www.tecplot.com/ * */ #include "stdafx.h" #include "MASTER.h" #define TECPLOTENGINEMODULE /* ****************************************************************** ****************************************************************** ******* ******** ****** (C) 1988-2008 Tecplot, Inc. ******* ******* ******** ****************************************************************** ****************************************************************** */ #define DATAIO4MODULE #include "GLOBAL.h" #include "TASSERT.h" #include "Q_UNICODE.h" #include "ALLOC.h" #include "AUXDATA.h" #include "DATASET.h" #include "FILESTREAM.h" #if defined TECPLOTKERNEL /* CORE SOURCE CODE REMOVED */ #endif #include "GEOM2.h" #include "GEOM.h" #include "INPUT.h" #include "SET.h" #include "TEXT.h" #include "DATAIO4.h" #include "DATASET0.h" #include "STRUTIL.h" #include "ARRLIST.h" #include "STRLIST.h" #include "Q_MSG.h" #if defined IRIS #include #endif using namespace tecplot::strutil; #if !defined(TECPLOTKERNEL) && defined(MSWIN) # pragma warning(disable : 4244) #endif /*END HEADER*/ /* * This module contains mostly low level i/o functions. */ #if defined DECALPHA || defined COMPAQALPHA #define _IEEE_FP_INEXACT #define _IEEE_FP #endif #if defined SUN41 #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2 #endif #if defined TECPLOTKERNEL /* CORE SOURCE CODE REMOVED */ #endif /********************************************************************** ********************************************************************** ********************** INPUT ************************** ********************************************************************** **********************************************************************/ static char FilterFloatChar(float X) { char C; if (((X >= 32.0) && (X <= 127.0)) || ((X >= 160.0) && (X <= 255.0)) || (X == 0.0)) C = (char)X; else C = '?'; return (C); } double GetNextValue(FileStream_s *FileStream, FieldDataType_e FieldDataType, double VMin, double VMax, Boolean_t *IsOk) { double X = 0.0; REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk)); REQUIRE(!(*IsOk) || VALID_FIELD_DATA_TYPE(FieldDataType)); REQUIRE(!(*IsOk) || VALID_REF(FileStream)); if (*IsOk) { switch (FieldDataType) { case FieldDataType_Float : { float XX; *IsOk = (TP_FREAD(&XX, 4, 1, FileStream->File) == 1); if (!FileStream->IsByteOrderNative) REVERSE_4_BYTES(&XX); if (*IsOk) X = XX; else X = 0.0; } break; case FieldDataType_Double : { double XX; *IsOk = (TP_FREAD(&XX, sizeof(double), 1, FileStream->File) == 1); if (!FileStream->IsByteOrderNative) REVERSE_8_BYTES(&XX); if (*IsOk) X = XX; else X = 0.0; } break; case FieldDataType_Int32 : { Int32_t L; *IsOk = (TP_FREAD(&L, sizeof(Int32_t), 1, FileStream->File) == 1); if (!FileStream->IsByteOrderNative) REVERSE_4_BYTES(&L); if (*IsOk) X = (double)L; } break; case FieldDataType_Int16 : { Int16_t S; *IsOk = (TP_FREAD(&S, sizeof(Int16_t), 1, FileStream->File) == 1); if (!FileStream->IsByteOrderNative) REVERSE_2_BYTES(&S); if (*IsOk) X = (double)S; } break; case FieldDataType_Byte : { Byte_t B; *IsOk = (TP_FREAD(&B, sizeof(Byte_t), 1, FileStream->File) == 1); if (*IsOk) X = (double)B; } break; case FieldDataType_Bit : { /* * Important note: * Reading bit data a value at a time is only valid for a * single bit value. If the file contains a block of more than * one bit value and you attempt to read it a bit at a time it * will not work as Tecplot does not buffer the read. In order * to read a block of bits you must perform a block read. */ Byte_t B; *IsOk = (TP_FREAD(&B, sizeof(Byte_t), 1, FileStream->File) == 1); if (*IsOk) X = (double)(B & (Byte_t)01); } break; default: CHECK(FALSE); break; } if (*IsOk) { if ((X < VMin) || (X > VMax)) { *IsOk = FALSE; } } } return X; } LgIndex_t GetNextI(FileStream_s *FileStream, Boolean_t *IsOk) { LgIndex_t I = 0; REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk)); REQUIRE(!(*IsOk) || (VALID_REF(FileStream) && VALID_REF(FileStream->File))); if (*IsOk) { Int32_t Int32Val; *IsOk = (TP_FREAD((void *) & Int32Val, 4, 1, FileStream->File) == 1); if (!FileStream->IsByteOrderNative) REVERSE_4_BYTES(&Int32Val); I = Int32Val; } return I; } LgIndex_t GetIoFileInt(FileStream_s *FileStream, short Version, LgIndex_t IMin, LgIndex_t IMax, Boolean_t *IsOk) { LgIndex_t I = 0; REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk)); REQUIRE(!(*IsOk) || (0 < Version && Version <= TecplotBinaryFileVersion)); REQUIRE(!(*IsOk) || (VALID_REF(FileStream) && VALID_REF(FileStream->File))); REQUIRE(!(*IsOk) || IMin <= IMax); if (!(*IsOk)) return (0); if (Version <= 63) { float X; if (*IsOk) { X = (float)GetNextValue(FileStream, FieldDataType_Float, (double)IMin - 1.0e-10, (double)IMax + 1.0e-10, IsOk); if (*IsOk) { if (ABS(X) < (float)MAXINDEX) I = (LgIndex_t)X; else *IsOk = FALSE; } else *IsOk = FALSE; } } else { I = GetNextI(FileStream, IsOk); } if ((I < IMin) || (I > IMax)) *IsOk = FALSE; return (I); } /** * Basically this is "realloc" but apparently "realloc" doesn't behave reliably * on all platforms. */ static Boolean_t ReallocString(char **String, LgIndex_t NewLength) { Boolean_t IsOk; char *NewString; REQUIRE(VALID_REF(String)); REQUIRE(*String == NULL || VALID_REF(*String)); REQUIRE((*String != NULL && NewLength >= (LgIndex_t)strlen(*String)) || (*String == NULL && NewLength >= 0)); NewString = ALLOC_ARRAY(NewLength + 1, char, "reallocated string"); IsOk = (NewString != NULL); if (IsOk) { if (*String == NULL) { NewString[0] = '\0'; } else { strcpy(NewString, *String); FREE_ARRAY(*String, "old string"); } *String = NewString; } ENSURE(VALID_BOOLEAN(IsOk)); ENSURE(IMPLICATION(IsOk, VALID_REF(*String))); return IsOk; } /** * Reads a string from all versions of a binary plt file. * * param FileStream * Open file stream positioned at the string to read. * param IVersion * Binary file version number. * param MaxCharacters * IVersion < 63 * This value is exactly the number of characters (actually floats, each * one representing a character's ordinal value) to read from the file. * IVersion >= 63 and ProcessData == TRUE * If non-zero, this value represents the largest string to be returned. * In other words, larger strings are read from the file but an allocated * string of up to MaxCharacters is returned. A zero value indicates that * the string size is unlimited and determined only by the actual length * of the string in the file. * param TargetStr * Pointer to hold the allocated string if ProcessData == TRUE. * param ProcessData * Indicates if the read string should be retrieved. * * return * TRUE if the read was successful with an allocated string *TargetStr * containing the string read (no larger than requested or necessary), * FALSE otherwise. */ Boolean_t ReadInString(FileStream_s *FileStream, short IVersion, int MaxCharacters, char **TargetStr, Boolean_t ProcessData) { Boolean_t IsOk = TRUE; REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File)); REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion); REQUIRE(IMPLICATION(IVersion < 63 || ProcessData, MaxCharacters >= 0)); REQUIRE(IMPLICATION(ProcessData, VALID_REF(TargetStr))); REQUIRE(VALID_BOOLEAN(ProcessData)); if (IVersion < 63) { /* * One word per character. Read Exactly "MaxCharacters" number of words. */ float X; if (ProcessData) { *TargetStr = ALLOC_ARRAY(MaxCharacters + 1, char, "target string"); IsOk = (*TargetStr != NULL); } if (IsOk) { LgIndex_t I; for (I = 0; IsOk && I < MaxCharacters; I++) { X = (float)GetNextValue(FileStream, FieldDataType_Float, 0.0, 127.0, &IsOk); if (!IsOk) break; if (ProcessData) (*TargetStr)[I] = FilterFloatChar(X); } if (ProcessData) (*TargetStr)[I] = '\0'; } else { ErrMsg(translate("Cannot allocate memory for string during read", "'string' meaning the computer science data type")); } } else { #define MAX_STRBUFFER_LEN 4095 static char StrBuffer[MAX_STRBUFFER_LEN+1]; LgIndex_t StrBufferLen = 0; LgIndex_t TargetStrLen = 0; LgIndex_t I = 0; LgIndex_t CharValue = 0; if (ProcessData) *TargetStr = NULL; do { CharValue = GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk); if (IsOk && ProcessData) { /* massage the character if necessary */ if ((CharValue < 32 && CharValue != '\0' && CharValue != '\n') || (CharValue >= 128 && CharValue < 160)) CharValue = ' '; /* * if the limit is not exceded, stuff the * character into the buffer */ if (CharValue != '\0' && (I < MaxCharacters || MaxCharacters == 0)) { StrBuffer[StrBufferLen] = (char)CharValue; StrBufferLen++; } if (CharValue == '\0' || StrBufferLen == MAX_STRBUFFER_LEN) { if (StrBufferLen != 0 || *TargetStr == NULL) { StrBuffer[StrBufferLen] = '\0'; TargetStrLen += StrBufferLen; IsOk = ReallocString(TargetStr, TargetStrLen); if (IsOk) strcat(*TargetStr, StrBuffer); StrBufferLen = 0; /* reset the string buffer */ } } } I++; } while (IsOk && (char)CharValue != '\0'); /* if we failed cleanup if necessary */ if (!IsOk && ProcessData && *TargetStr != NULL) { FREE_ARRAY(*TargetStr, "failed read string"); *TargetStr = NULL; } } ENSURE(IMPLICATION(ProcessData, (VALID_REF(*TargetStr) || *TargetStr == NULL))); ENSURE(VALID_BOOLEAN(IsOk)); return (IsOk); } /** */ static void ReadDoubleBlock(FileStream_s *FileStream, Boolean_t DoRead, double *Buffer, LgIndex_t StartIndex, LgIndex_t NumValues, Boolean_t *IsOk) { if (DoRead) { double *DPtr = Buffer + StartIndex; *IsOk = (TP_FREAD(DPtr, sizeof(double), NumValues, FileStream->File) == (size_t)NumValues); if (!FileStream->IsByteOrderNative && *IsOk) { LgIndex_t N; for (N = 0; N < NumValues; N++) REVERSE_8_BYTES(&DPtr[N]); } } else *IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(double), SEEK_CUR) == 0); } /** */ static void ReadFloatBlock(FileStream_s *FileStream, Boolean_t DoRead, float *Buffer, LgIndex_t StartIndex, LgIndex_t NumValues, Boolean_t *IsOk) { if (DoRead) { float *FPtr = Buffer + StartIndex; *IsOk = (TP_FREAD(FPtr, sizeof(float), NumValues, FileStream->File) == (size_t)NumValues); if (!FileStream->IsByteOrderNative && *IsOk) { LgIndex_t N; for (N = 0; N < NumValues; N++) REVERSE_4_BYTES(&FPtr[N]); } } else *IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(float), SEEK_CUR) == 0); } /** */ static void ReadBitBlock(FileStream_s *FileStream, Boolean_t DoRead, Byte_t *Buffer, LgIndex_t NumValues, Boolean_t *IsOk) { /* * Do not allow reading of bit values if startindex is not 0. * (This means geometries cannot use bit data. */ LgIndex_t NumBytes = (NumValues + 7) / 8; if (DoRead) { *IsOk = (TP_FREAD(Buffer, sizeof(Byte_t), NumBytes, FileStream->File) == (size_t)NumBytes); } else *IsOk = (TP_FSEEK(FileStream->File, NumBytes * sizeof(Byte_t), SEEK_CUR) == 0); } /** */ void ReadByteBlock(FileStream_s *FileStream, Boolean_t DoRead, Byte_t *Buffer, HgIndex_t StartIndex, HgIndex_t NumValues, Boolean_t *IsOk) { if (DoRead) { *IsOk = (TP_FREAD(Buffer + StartIndex, sizeof(Byte_t), NumValues, FileStream->File) == (size_t)NumValues); } else *IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(Byte_t), SEEK_CUR) == 0); } /** */ void ReadInt16Block(FileStream_s *FileStream, Boolean_t DoRead, Int16_t *Buffer, HgIndex_t StartIndex, HgIndex_t NumValues, Boolean_t *IsOk) { if (DoRead) { Int16_t *IntPtr = Buffer + StartIndex; *IsOk = (TP_FREAD(IntPtr, sizeof(Int16_t), NumValues, FileStream->File) == (size_t)NumValues); if (!FileStream->IsByteOrderNative && *IsOk) { LgIndex_t N; for (N = 0; N < NumValues; N++) REVERSE_2_BYTES(&IntPtr[N]); } } else *IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(Int16_t), SEEK_CUR) == 0); } /** */ void ReadInt16BlockToInt32(FileStream_s *FileStream, Boolean_t DoRead, Int32_t *Buffer, HgIndex_t StartIndex, HgIndex_t NumValues, Boolean_t *IsOk) { REQUIRE(VALID_REF(FileStream)); REQUIRE(VALID_BOOLEAN(DoRead)); REQUIRE(VALID_REF(Buffer)); REQUIRE(StartIndex >= 0); REQUIRE(NumValues >= 0); REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk)); if (DoRead) { HgIndex_t EndIndex = StartIndex + NumValues; for (HgIndex_t ValueIndex = StartIndex; *IsOk && ValueIndex < EndIndex; ValueIndex++) { Int16_t Value; *IsOk = (TP_FREAD(&Value, sizeof(Int16_t), 1, FileStream->File) == 1); if (!FileStream->IsByteOrderNative && *IsOk) REVERSE_2_BYTES(&Value); Buffer[ValueIndex] = (Int32_t)Value; } } else *IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(Int16_t), SEEK_CUR) == 0); } /** */ void ReadInt32Block(FileStream_s *FileStream, Boolean_t DoRead, Int32_t *Buffer, HgIndex_t StartIndex, HgIndex_t NumValues, Boolean_t *IsOk) { if (DoRead) { Int32_t *IntPtr = Buffer + StartIndex; *IsOk = (TP_FREAD(IntPtr, sizeof(Int32_t), NumValues, FileStream->File) == (size_t)NumValues); if (!FileStream->IsByteOrderNative && *IsOk) { LgIndex_t N; for (N = 0; N < NumValues; N++) REVERSE_4_BYTES(&IntPtr[N]); } } else *IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(Int32_t), SEEK_CUR) == 0); } /** */ void ReadPureBlock(FileStream_s *FileStream, Boolean_t DoRead, void *Buffer, FieldDataType_e FieldDataType, HgIndex_t StartIndex, HgIndex_t NumValues, Boolean_t *IsOk) { REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File)); REQUIRE(VALID_BOOLEAN(DoRead)); REQUIRE(!DoRead || VALID_REF(Buffer)); REQUIRE(VALID_FIELD_DATA_TYPE(FieldDataType)); REQUIRE(StartIndex >= 0); REQUIRE(NumValues >= 0); REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk)); switch (FieldDataType) { case FieldDataType_Float : { ReadFloatBlock(FileStream, DoRead, (float *)Buffer, StartIndex, NumValues, IsOk); } break; case FieldDataType_Double : { ReadDoubleBlock(FileStream, DoRead, (double *)Buffer, StartIndex, NumValues, IsOk); } break; case FieldDataType_Bit : { if (StartIndex != 0) { ErrMsg(translate("Internal Error: Attempt to read bit data at non-zero offset", "see Tecplot User's manual for a definition of 'bit' data")); *IsOk = FALSE; } else ReadBitBlock(FileStream, DoRead, (Byte_t *)Buffer, NumValues, IsOk); } break; case FieldDataType_Byte : { ReadByteBlock(FileStream, DoRead, (Byte_t *)Buffer, StartIndex, NumValues, IsOk); } break; case FieldDataType_Int16 : { ReadInt16Block(FileStream, DoRead, (Int16_t *)Buffer, StartIndex, NumValues, IsOk); } break; case FieldDataType_Int32 : { ReadInt32Block(FileStream, DoRead, (Int32_t *)Buffer, StartIndex, NumValues, IsOk); } break; case FieldDataType_IJKFunction : /* Not used yet */ case FieldDataType_Int64 : /* Not used yet */ default: CHECK(FALSE); break; } ENSURE(VALID_BOOLEAN(*IsOk)); } /** */ void ReadBlock(FileStream_s *FileStream, FieldData_pa FieldData, Boolean_t DoRead, FieldDataType_e FieldDataTypeInFile, HgIndex_t StartIndex, HgIndex_t EndIndex, Boolean_t *IsOk) { REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk)); REQUIRE(IMPLICATION(IsOk, VALID_REF(FileStream))); REQUIRE(IMPLICATION(IsOk, VALID_FIELD_DATA_TYPE(FieldDataTypeInFile))); REQUIRE(VALID_BOOLEAN(DoRead)); REQUIRE(IMPLICATION(DoRead, VALID_REF(FieldData))); /* * Bit data is packed into bytes. Since Tecplot doesn't buffer reads it can * not perform bit by bit value reads and therefore must only perform block * reads of bit data. */ Boolean_t ReadByBlock = IMPLICATION(DoRead, GetFieldDataType(FieldData) == FieldDataTypeInFile); REQUIRE(ReadByBlock || (FieldDataTypeInFile != FieldDataType_Bit)); if (*IsOk) { LgIndex_t NumValues = EndIndex - StartIndex + 1; if (ReadByBlock) { void *data_array; if (DoRead) data_array = GetFieldDataVoidPtr(FieldData); else data_array = NULL; ReadPureBlock(FileStream, DoRead, data_array, FieldDataTypeInFile, StartIndex, NumValues, IsOk); } else { LgIndex_t N; for (N = 0; *IsOk && (N < NumValues); N++) { double D = GetNextValue(FileStream, FieldDataTypeInFile, -LARGEDOUBLE, LARGEDOUBLE, IsOk); if (DoRead) SetFieldValue(FieldData, N + StartIndex, D); } } } } /** */ void ReadClassicOrderedCCBlock(FileStream_s *DataFileStream, FieldData_pa FieldData, FieldDataType_e FieldDataTypeInFile, LgIndex_t NumIPtsInFile, LgIndex_t NumJPtsInFile, LgIndex_t NumKPtsInFile, Boolean_t *IsOk) { REQUIRE(IMPLICATION(*IsOk, VALID_REF(DataFileStream))); REQUIRE(IMPLICATION(*IsOk, VALID_FIELD_DATA_TYPE(FieldDataTypeInFile))); REQUIRE(VALID_REF(FieldData)); REQUIRE(NumIPtsInFile >= 0); REQUIRE(NumJPtsInFile >= 0); REQUIRE(NumKPtsInFile >= 0); REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk)); if (*IsOk) { LgIndex_t J, K; LgIndex_t NumIJPts = NumIPtsInFile * NumJPtsInFile; LgIndex_t IEnd = MAX(NumIPtsInFile - 1, 1); LgIndex_t JEnd = MAX(NumJPtsInFile - 1, 1); LgIndex_t KEnd = MAX(NumKPtsInFile - 1, 1); LgIndex_t NumValues = (IEnd * JEnd * KEnd); Boolean_t IsLinear = ((NumJPtsInFile == 1 && NumKPtsInFile == 1) || (NumIPtsInFile == 1 && NumKPtsInFile == 1) || (NumIPtsInFile == 1 && NumJPtsInFile == 1)); if (IsLinear) ReadBlock(DataFileStream, FieldData, TRUE, FieldDataTypeInFile, 0, NumValues - 1, IsOk); else for (K = 0; K < KEnd && IsOk; K++) for (J = 0; J < JEnd && IsOk; J++) { LgIndex_t CellIndex = 0 + (J * NumIPtsInFile) + (K * NumIJPts); ReadBlock(DataFileStream, FieldData, TRUE, FieldDataTypeInFile, CellIndex, CellIndex + IEnd - 1, IsOk); } } ENSURE(VALID_BOOLEAN(*IsOk)); } /** */ static void AdjustCustomColor(short IVersion, ColorIndex_t *BColor) { REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion); REQUIRE(VALID_REF(BColor)); if ((IVersion < 70) && (*BColor >= 15) && (*BColor <= 22)) *BColor -= 7; } /* * ReadInDataFileTypeTitleAndVarNames replaces ReadInDataFileTitleAndVarNames * and reads in the filetype as well in files with version >= 109. */ Boolean_t ReadInDataFileTypeTitleAndVarNames(FileStream_s *FileStream, short IVersion, char **DataSetTitle, DataFileType_e *FileType, int *NumVars, StringList_pa *VarNames) { EntIndex_t CurVar; Boolean_t IsOk = TRUE; REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File)); REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion); REQUIRE(VALID_REF(DataSetTitle) || (DataSetTitle == NULL)); REQUIRE(VALID_REF(FileType) || (FileType == NULL)); REQUIRE(VALID_REF(NumVars)); REQUIRE(VALID_REF(VarNames) || (VarNames == NULL)); *NumVars = 0; if (DataSetTitle) *DataSetTitle = NULL; if (IVersion >= 109) { if (FileType) *FileType = (DataFileType_e)GetIoFileInt(FileStream, IVersion, 0, DataFileType_Solution, &IsOk); else GetIoFileInt(FileStream, IVersion, 0, DataFileType_Solution, &IsOk); } if (ReadInString(FileStream, IVersion, ((IVersion < 63) ? 80 : MaxChrsDatasetTitle), DataSetTitle, (Boolean_t)(DataSetTitle != NULL))) { if (DataSetTitle) TrimLeadAndTrailSpaces(*DataSetTitle); *NumVars = GetIoFileInt(FileStream, IVersion, 0, MAXZONEMAP, &IsOk); } else IsOk = FALSE; if (IsOk && (*NumVars > MaxNumZonesOrVars)) { ErrMsg(translate("Too many variables")); IsOk = FALSE; } if (IsOk && VarNames) { if (*NumVars > 0) { /* allocate a string list filled with NULL's */ *VarNames = StringListAlloc(); IsOk = (*VarNames != NULL); if (IsOk) IsOk = StringListSetString(*VarNames, *NumVars - 1, NULL); if (!IsOk) { if (*VarNames != NULL) StringListDealloc(VarNames); ErrMsg(translate("Out of space while allocating var names")); } } } for (CurVar = 0; IsOk && (CurVar < *NumVars); CurVar++) { char *VName = NULL; IsOk = ReadInString(FileStream, IVersion, ((IVersion < 63) ? 5 : MaxChrsVarName), VarNames ? &VName : NULL, (Boolean_t)(VarNames != NULL)); if (IsOk && VarNames) { if (VName == NULL) { /* NULL variable names are converted to empty names */ VName = ALLOC_ARRAY(1, char, "empty variable name"); strcpy(VName, ""); } TrimLeadAndTrailSpaces(VName); /* * variables are not allowed to have litteral new line characters * within them but they can sneek in from ASCII data files so * convert any to their appropriate two character representation */ IsOk = ReplaceNewlineWithBackslashN(&VName); IsOk = IsOk && StringListSetString(*VarNames, CurVar, VName); if (VName != NULL) FREE_ARRAY(VName, "variable name"); } if (!IsOk) { if (VarNames && *VarNames) StringListDealloc(VarNames); ErrMsg(translate("Out of space while allocating variable names")); } } ENSURE(VALID_BOOLEAN(IsOk)); return (IsOk); } /** */ static Boolean_t ReadInPresetZoneColor(FileStream_s *FileStream, short IVersion, ZoneSpec_s *ZoneSpec) { Boolean_t IsOk = TRUE; LgIndex_t ZoneColor; REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File)); REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion); REQUIRE(VALID_REF(ZoneSpec)); ZoneColor = GetIoFileInt(FileStream, IVersion, -1, LastBasicColor, &IsOk); if (IsOk) { if (VALID_BASIC_COLOR(ZoneColor)) { ZoneSpec->ZoneLoadInfo.PresetZoneColor = (EntIndex_t)ZoneColor; AdjustCustomColor(IVersion, &ZoneSpec->ZoneLoadInfo.PresetZoneColor); } else if (ZoneColor != -1) IsOk = FALSE; } ENSURE(VALID_BOOLEAN(IsOk)); return IsOk; } /** */ static void ConvertCommonTimeToSolutionTime(ZoneSpec_s *ZoneSpec) { REQUIRE(VALID_REF(ZoneSpec)); REQUIRE(ZoneSpec->AuxData == NULL || VALID_REF(ZoneSpec->AuxData)); LgIndex_t ItemIndex; if (ZoneSpec->AuxData != NULL && AuxDataGetItemIndex(ZoneSpec->AuxData, AuxData_Common_Time, &ItemIndex)) { const char *SameName; ArbParam_t Value; AuxDataType_e Type; Boolean_t Retain; AuxDataGetItemByIndex(ZoneSpec->AuxData, ItemIndex, &SameName, &Value, &Type, &Retain); CHECK(ustrcmp(AuxData_Common_Time, SameName) == 0); CHECK(Type == AuxDataType_String); char *EndPtr = NULL; double SolutionTime = strtod((const char *)Value, &EndPtr); if (EndPtr != (char *)Value) { /* we only allow white space to trail a value */ while (isspace(*EndPtr)) EndPtr++; } if (EndPtr != (char *)Value && *EndPtr == '\0') { ZoneSpec->SolutionTime = SolutionTime; ZoneSpec->StrandID = STRAND_ID_PENDING; AuxDataDeleteItemByIndex(ZoneSpec->AuxData, ItemIndex); } } } /* * Pass1 for a zone reads in and initializes the zone structures. * These structures are released later if the user elects to not read them * in. */ Boolean_t ReadInZoneHeader(FileStream_s *FileStream, short IVersion, ZoneSpec_s *ZoneSpec, Set_pa IsVarCellCentered, EntIndex_t NumVars, Boolean_t *IsRawFNAvailable, LgIndex_t *FNNumBndryConns) { EntIndex_t Var; Boolean_t IsOk = TRUE; LgIndex_t I1; REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File)); REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion); REQUIRE(VALID_REF(ZoneSpec)); REQUIRE(IsVarCellCentered == NULL || VALID_REF(IsVarCellCentered)); REQUIRE(NumVars >= 0); REQUIRE(VALID_REF(IsRawFNAvailable)); REQUIRE(VALID_REF(FNNumBndryConns)); SetZoneSpecDefaults(ZoneSpec); if (IsVarCellCentered != NULL) { /* assign default variable value location: nodal */ ClearSet(IsVarCellCentered); IsOk = ExpandSet(IsVarCellCentered, NumVars, FALSE); } if (IsOk) IsOk = ReadInString(FileStream, IVersion, ((IVersion < 63) ? 10 : MaxChrsZnTitle), &ZoneSpec->Name, TRUE); if (IsOk && ZoneSpec->Name == NULL) { /* NULL zone names are converted to empty names */ ZoneSpec->Name = ALLOC_ARRAY(1, char, "empty zone name"); IsOk = (ZoneSpec->Name != NULL); if (IsOk) strcpy(ZoneSpec->Name, ""); } if (IsOk) TrimLeadAndTrailSpaces(ZoneSpec->Name); if (IVersion < 101) { Boolean_t IsZoneFinite; DataFormat_e ZoneDataFormat; I1 = GetIoFileInt(FileStream, IVersion, 0, 3, &IsOk); if ((I1 < 0) || (I1 > 3)) { return (FALSE); } ZoneDataFormat = (DataFormat_e)I1; IsZoneFinite = (ZoneDataFormat == DataFormat_FEPoint || ZoneDataFormat == DataFormat_FEBlock); ZoneSpec->ZoneLoadInfo.IsInBlockFormat = (ZoneDataFormat == DataFormat_IJKBlock || ZoneDataFormat == DataFormat_FEBlock); if (IVersion > 62) IsOk = ReadInPresetZoneColor(FileStream, IVersion, ZoneSpec); if (IVersion < 60) GetNextValue(FileStream, FieldDataType_Float, -LARGEDOUBLE, LARGEDOUBLE, &IsOk); /* Old ZPlane Value */ if (IsOk) { ZoneSpec->NumPtsI = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk); ZoneSpec->NumPtsJ = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk); if (IVersion >= 60) ZoneSpec->NumPtsK = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk); else ZoneSpec->NumPtsK = 1; } if (IsOk) { /* If IMax,JMax, & KMax are all zero then this zone was "zombied" by a partial read to make layout files align. */ if (!((ZoneSpec->NumPtsI == 0) && (ZoneSpec->NumPtsJ == 0) && (ZoneSpec->NumPtsK == 0)) && ((ZoneSpec->NumPtsI <= 0) || (ZoneSpec->NumPtsJ <= 0) || (ZoneSpec->NumPtsK < 0) || ((!IsZoneFinite && (ZoneSpec->NumPtsK == 0))))) { ErrMsg(translate("Datafile is corrupted")); IsOk = FALSE; } if (IsZoneFinite) { if (IVersion >= 61) { ZoneSpec->Type = (ZoneType_e)(ZoneSpec->NumPtsK + 1); switch (ZoneSpec->Type) { case ZoneType_FETriangle: ZoneSpec->NumPtsK = 3; break; case ZoneType_FEQuad: ZoneSpec->NumPtsK = 4; break; case ZoneType_FETetra: ZoneSpec->NumPtsK = 4; break; case ZoneType_FEBrick: ZoneSpec->NumPtsK = 8; break; case ZoneType_FELineSeg: ZoneSpec->NumPtsK = 2; break; default: { ErrMsg(translate("Datafile corrupted: Invalid element type for FE DataSet")); IsOk = FALSE; } } } else { ZoneSpec->Type = ZoneType_FEQuad; ZoneSpec->NumPtsK = 4; } } else { ZoneSpec->Type = ZoneType_Ordered; ZoneSpec->ICellDim = ZoneSpec->NumPtsI - 1; ZoneSpec->JCellDim = ZoneSpec->NumPtsJ - 1; ZoneSpec->KCellDim = ZoneSpec->NumPtsK - 1; } } /* * Raw and user defined boundary face neighbors connections were not in * this or previous versions of the binary data files. */ *IsRawFNAvailable = FALSE; *FNNumBndryConns = 0; } else { if (IsOk && (IVersion >= 107)) { ZoneSpec->ParentZone = GetIoFileInt(FileStream, IVersion, -1, MAXZONEMAP - 1, &IsOk); if (!IsOk) ErrMsg(translate("Invalid datafile: parent zone assignment must be to an existing zone within the same datafile.")); } if (IsOk && (IVersion >= 106)) { /* Strand ID and solution time. Strand ID's of STRAND_ID_PENDING, -2, instruct Tecplot to generate strand ID's */ ZoneSpec->StrandID = GetIoFileInt(FileStream, IVersion, -2, MAXZONEMAP - 1, &IsOk); ZoneSpec->SolutionTime = GetNextValue(FileStream, FieldDataType_Double, -LARGEDOUBLE, LARGEDOUBLE, &IsOk); if (!IsOk) ErrMsg(translate("Invalid datafile: bad StrandID or SolutionTime")); } /* preset zone color */ IsOk = IsOk && ReadInPresetZoneColor(FileStream, IVersion, ZoneSpec); /* ZoneType */ I1 = (ZoneType_e)GetIoFileInt(FileStream, IVersion, 0, 7, &IsOk); switch (I1) { case 0: ZoneSpec->Type = ZoneType_Ordered; break; case 1: ZoneSpec->Type = ZoneType_FELineSeg; break; case 2: ZoneSpec->Type = ZoneType_FETriangle; break; case 3: ZoneSpec->Type = ZoneType_FEQuad; break; case 4: ZoneSpec->Type = ZoneType_FETetra; break; case 5: ZoneSpec->Type = ZoneType_FEBrick; break; case 6: ZoneSpec->Type = ZoneType_FEPolygon; break; case 7: ZoneSpec->Type = ZoneType_FEPolyhedron; break; default: { ErrMsg(translate("Invalid datafile: unknown zone type.")); IsOk = FALSE; } break; } /* DataPacking (Always BLOCK starting with file version 112 so removed from binary format) */ if (IVersion < 112) ZoneSpec->ZoneLoadInfo.IsInBlockFormat = ((DataPacking_e)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk) == DataPacking_Block); else ZoneSpec->ZoneLoadInfo.IsInBlockFormat = TRUE; /* is the variable value location specified? */ if ((Boolean_t)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk) && IsOk) { /* Variable Value Location foreach Var */ for (Var = 0; Var < NumVars && IsOk; Var++) { if ((Boolean_t)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk) && IsOk && IsVarCellCentered != NULL) { IsOk = (ZoneSpec->ZoneLoadInfo.IsInBlockFormat); if (IsOk) IsOk = AddToSet(IsVarCellCentered, Var, FALSE); else ErrMsg(translate("Invalid datafile: cell centered " "variable must be in block format.", "See the Tecplot User's Manual for a definition of 'block format'")); } } } /* are raw face neighbors supplied in the data section? */ if (IVersion >= 108 && IsOk) { *IsRawFNAvailable = GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk); if (*IsRawFNAvailable && (ZoneSpec->Type == ZoneType_Ordered || ZoneSpec->Type == ZoneType_FELineSeg)) { IsOk = FALSE; ErrMsg(translate("Invalid datafile: raw face neighbors may not be " "supplied for ordered or FE line segment zones.")); } } else *IsRawFNAvailable = FALSE; /* * If raw face neighbors are available in the datafile then Tecplot * should not auto-assign the neighbors after the load. */ ZoneSpec->FNAreCellFaceNbrsSupplied = *IsRawFNAvailable; /* miscellaneous face neighbor info */ *FNNumBndryConns = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk); if (*FNNumBndryConns != 0) ZoneSpec->FNMode = (FaceNeighborMode_e)GetIoFileInt(FileStream, IVersion, 0, 3, &IsOk); if (IVersion >= 108 && IsOk) { Boolean_t FaceNeighborsComplete = FALSE; if (*FNNumBndryConns != 0 && ZoneSpec->Type != ZoneType_Ordered) FaceNeighborsComplete = (Boolean_t)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk); /* * If the user defined face neighbors completely specify all the * face neighbors then we don't want to auto-assign the cell face * neighbors after loading. If they are not complete then leave the * setting (as set above) dependent on the availability of the raw * face neighbors. * * NOTE: * This is a rather inefficient way to specify face neighbors. */ if (FaceNeighborsComplete) ZoneSpec->FNAreCellFaceNbrsSupplied = TRUE; } if (ZoneSpec->Type == ZoneType_Ordered) { /* IMax, JMax, KMax */ ZoneSpec->NumPtsI = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk); ZoneSpec->NumPtsJ = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk); ZoneSpec->NumPtsK = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk); /* * if not a zombie zone (zombie zone: points in all dimensions are * zero) then points in each direction must be specified */ if (IsOk && !(ZoneSpec->NumPtsI == 0 && ZoneSpec->NumPtsJ == 0 && ZoneSpec->NumPtsK == 0) && (ZoneSpec->NumPtsI == 0 || ZoneSpec->NumPtsJ == 0 || ZoneSpec->NumPtsK == 0)) { ErrMsg(translate("Invalid data file: incorrect specification of " "I, J, or K points for ordered data set.")); IsOk = FALSE; } } else { ZoneSpec->NumPtsI = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk); if (ZoneSpec->Type == ZoneType_FEPolygon || ZoneSpec->Type == ZoneType_FEPolyhedron) { ZoneSpec->NumPtsK = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk); // ...NumFaces if (IVersion >= 111) { ZoneSpec->NumFaceNodes = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk); ZoneSpec->NumFaceBndryFaces = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk); ZoneSpec->NumFaceBndryItems = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk); } } else { switch (ZoneSpec->Type) { case ZoneType_FETriangle: ZoneSpec->NumPtsK = 3; break; case ZoneType_FEQuad: ZoneSpec->NumPtsK = 4; break; case ZoneType_FETetra: ZoneSpec->NumPtsK = 4; break; case ZoneType_FEBrick: ZoneSpec->NumPtsK = 8; break; case ZoneType_FELineSeg: ZoneSpec->NumPtsK = 2; break; default : { ErrMsg(translate("Invalid data file: invalid element type for FE data set.")); IsOk = FALSE; } } } ZoneSpec->NumPtsJ = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk); ZoneSpec->ICellDim = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk); ZoneSpec->JCellDim = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk); ZoneSpec->KCellDim = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk); } /* Zone Auxiliary Data indicator followed by Zone Auxiliary Data */ for (I1 = GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk); IsOk && I1 != 0; I1 = GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk)) { if (ZoneSpec->AuxData == NULL) ZoneSpec->AuxData = AuxDataAlloc(); IsOk = (ZoneSpec->AuxData != NULL); if (IsOk) IsOk = ReadInAuxData(FileStream, IVersion, ZoneSpec->AuxData); } } /* * Convert AuxZone's Common.Time from non-time aware data files to zone * solution time if it exists. */ if (IVersion < 106 && IsOk) ConvertCommonTimeToSolutionTime(ZoneSpec); ENSURE(VALID_BOOLEAN(IsOk)); return (IsOk); } /* * Pass1 for Custom labels simply acknowledges that a custom label was * parsed and skips over the labels. */ Boolean_t ReadInCustomLabels(FileStream_s *FileStream, short IVersion, Boolean_t OkToLoad, StringList_pa *CustomLabelBase) { LgIndex_t NumLabels; short I; Boolean_t IsOk = TRUE; REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File)); REQUIRE(IVersion > 0); REQUIRE(VALID_BOOLEAN(OkToLoad)); REQUIRE(!(OkToLoad) || VALID_REF(CustomLabelBase)); NumLabels = (short)GetIoFileInt(FileStream, IVersion, 1, MAXINDEX, &IsOk); if (IsOk && NumLabels != 0 && OkToLoad) { *CustomLabelBase = StringListAlloc(); IsOk = (*CustomLabelBase != NULL); if (!IsOk) ErrMsg(translate("Cannot allocate memory for Custom Labels.")); } for (I = 0; IsOk && (I < NumLabels); I++) { char *TLabel = NULL; IsOk = ReadInString(FileStream, IVersion, 1024, &TLabel, OkToLoad); TrimLeadAndTrailSpaces(TLabel); if (IsOk && OkToLoad) { #if defined TECPLOTKERNEL /* CORE SOURCE CODE REMOVED */ #endif IsOk = StringListAppendString(*CustomLabelBase, TLabel); if (TLabel != NULL) FREE_ARRAY(TLabel, "custom label"); if (!IsOk) ErrMsg(translate("Cannot allocate memory for Custom Label.")); } } if (!IsOk) ErrMsg(translate("Invalid custom axis label record in binary datafile")); ENSURE(VALID_BOOLEAN(IsOk)); ENSURE(!(IsOk && NumLabels != 0 && OkToLoad) || StringListValid(*CustomLabelBase)); return IsOk; } Boolean_t ReadInUserRec(FileStream_s *FileStream, short IVersion, int MaxCharactersAllowed, char **UserRec) /* NULL if to ignore */ { if (!ReadInString(FileStream, IVersion, MaxCharactersAllowed, UserRec, (Boolean_t)(UserRec != NULL))) { ErrMsg(translate("Invalid USERREC record in binary datafile")); return (FALSE); } return (TRUE); } /** */ Boolean_t ReadInAuxData(FileStream_s *FileStream, short IVersion, AuxData_pa AuxData) { Boolean_t IsOk; Boolean_t DoCollectData; char *AuxName = NULL; LgIndex_t AuxValueType; char *AuxValue = NULL; REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File)); REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion); REQUIRE(AuxData == NULL || VALID_REF(AuxData)); DoCollectData = (AuxData != NULL); IsOk = ReadInString(FileStream, IVersion, MaxChrsVarName, /* ... seems reasonable */ &AuxName, DoCollectData); if (IsOk && DoCollectData && !AuxDataIsValidName(AuxName)) { ErrMsg(translate("Invalid auxiliary data name.")); IsOk = FALSE; } /* * currently only one value type is supported * 0: AuxiliaryValueFormat_String */ if (IsOk) { AuxValueType = GetIoFileInt(FileStream, IVersion, 0, 0, &IsOk); if (IsOk && (AuxValueType != (LgIndex_t)AuxDataType_String)) { ErrMsg(translate("Unsupported auxiliary data type")); IsOk = FALSE; } } if (IsOk) IsOk = ReadInString(FileStream, IVersion, MaxChrsAuxValueString, &AuxValue, DoCollectData); if (IsOk && DoCollectData) IsOk = AuxDataSetItem(AuxData, AuxName, (ArbParam_t)AuxValue, AuxDataType_String, TRUE); /* Retain */ /* cleanup: auxiliary data made a copy of the name and value */ if (AuxName != NULL) FREE_ARRAY(AuxName, "data set auxiliary data item name"); if (AuxValue != NULL) FREE_ARRAY(AuxValue, "data set auxiliary data item value"); ENSURE(VALID_BOOLEAN(IsOk)); return IsOk; } static void GetZoneAttachment(FileStream_s *FileStream, short IVersion, EntIndex_t *Z, Boolean_t *IsAttached, Boolean_t *IsOk) { REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File)); REQUIRE(VALID_REF(Z)); REQUIRE(VALID_REF(IsAttached)); REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk)); if (IVersion >= 47) *Z = (EntIndex_t)GetIoFileInt(FileStream, IVersion, -1, MAXZONEMAP, IsOk); else *Z = 0; if (IVersion < 70) (*Z)--; if (*Z == -1) { *Z = 0; *IsAttached = FALSE; } else *IsAttached = TRUE; ENSURE(VALID_BOOLEAN(*IsAttached)); ENSURE(VALID_BOOLEAN(*IsOk)); ENSURE(*Z >= 0); } static Boolean_t ReadMacroFunctionCommand(FileStream_s *FileStream, short IVersion, Boolean_t OkToLoad, char **MacroFunctionCommand) { Boolean_t Result = FALSE; REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File)); REQUIRE(IVersion > 0); REQUIRE(VALID_BOOLEAN(OkToLoad)); REQUIRE(VALID_REF(MacroFunctionCommand)); Result = ReadInString(FileStream, IVersion, 0, MacroFunctionCommand, OkToLoad); ENSURE(VALID_BOOLEAN(Result)); return (Result); } /* * Pass1 for Geometries simply acknowledges that a geometry was * parsed and skips over the geometry. */ Boolean_t ReadInGeometry(FileStream_s *FileStream, short IVersion, Boolean_t OkToLoad, Geom_s *Geom, LgIndex_t MaxDataPts) { LgIndex_t I; LgIndex_t S; FieldDataType_e FFT; Boolean_t IsOk = TRUE; TranslatedString ErrMsgString = translate("Invalid geometry record"); REQUIRE(VALID_REF(Geom)); if (IVersion < 70) FFT = FieldDataType_Float; else FFT = FieldDataType_Double; if (IVersion < 101) I = GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk); else I = GetIoFileInt(FileStream, IVersion, 0, 4, &IsOk); if (I == 0) Geom->PositionCoordSys = CoordSys_Grid; else if (I == 1) Geom->PositionCoordSys = CoordSys_Frame; /* * I == 2 is for CoordSys_FrameOffset and is not used currently * * I == 3 is for the old window coordinate system */ else if (I == 4) Geom->PositionCoordSys = CoordSys_Grid3D; else { ErrMsgString = translate("Invalid geometry coordinate system"); IsOk = FALSE; } Geom->Scope = (Scope_e)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk); if (IVersion >= 102) Geom->DrawOrder = (DrawOrder_e)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk); Geom->AnchorPos.Generic.V1 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk); Geom->AnchorPos.Generic.V2 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk); if (IVersion >= 45) Geom->AnchorPos.Generic.V3 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk); else Geom->AnchorPos.Generic.V3 = 0.0; GetZoneAttachment(FileStream, IVersion, &Geom->Zone, &Geom->AttachToZone, &IsOk); Geom->BColor = (SmInteger_t)GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk); AdjustCustomColor(IVersion, &Geom->BColor); if (IVersion > 47) { Geom->FillBColor = (SmInteger_t)GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk); Geom->IsFilled = (Boolean_t)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk); AdjustCustomColor(IVersion, &Geom->FillBColor); } else { Geom->FillBColor = Geom->BColor; Geom->IsFilled = FALSE; } if (IVersion < 101) { Geom->GeomType = (GeomType_e)GetIoFileInt(FileStream, IVersion, 0, 5, &IsOk); if (Geom->GeomType == GeomType_LineSegs3D) { /* * GeomType_LineSegs3D is deprecated, converter to GeomType_LineSegs * with CoordSys_Grid3D instead */ Geom->GeomType = GeomType_LineSegs; Geom->PositionCoordSys = CoordSys_Grid3D; /*...should have been anyway */ } } else { Geom->GeomType = (GeomType_e)GetIoFileInt(FileStream, IVersion, 0, 4, &IsOk); } /* * Check geom coord sys versus geom type */ if (Geom->PositionCoordSys == CoordSys_Grid3D && Geom->GeomType != GeomType_LineSegs) { ErrMsgString = translate("Mismatch between geometry coordinate system and geometry type"); IsOk = FALSE; } if (IVersion > 41) { Geom->LinePattern = (LinePattern_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)LinePattern_DashDotDot, &IsOk); } else { Geom->LinePattern = (LinePattern_e)((int)Geom->GeomType % 2); Geom->GeomType = (GeomType_e)((int)Geom->GeomType / 10); } if ((IVersion < 49) && ((short)(Geom->GeomType) == 2)) { Geom->GeomType = GeomType_Rectangle; Geom->IsFilled = TRUE; } if ((IVersion < 70) && ((short)(Geom->GeomType) > 1)) Geom->GeomType = (GeomType_e)((short)Geom->GeomType + 1); ResetString(&Geom->MacroFunctionCommand, NULL, TRUE); Geom->ImageResizeFilter = ImageResizeFilter_Texture; if (IVersion >= 70) { Geom->PatternLength = GetNextValue(FileStream, FFT, PatternLengthInputSpec.Min, PatternLengthInputSpec.Max, &IsOk); Geom->LineThickness = GetNextValue(FileStream, FFT, LineThicknessInputSpec.Min, LineThicknessInputSpec.Max, &IsOk); Geom->NumEllipsePts = (SmInteger_t)GetIoFileInt(FileStream, IVersion, 2, MaxPtsCircleOrEllipse, &IsOk); Geom->ArrowheadStyle = (ArrowheadStyle_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)ArrowheadStyle_Hollow, &IsOk); Geom->ArrowheadAttachment = (ArrowheadAttachment_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)ArrowheadAttachment_AtBothEnds, &IsOk); Geom->ArrowheadSize = GetNextValue(FileStream, FFT, ArrowheadSizeInputSpec.Min, ArrowheadSizeInputSpec.Max, &IsOk); Geom->ArrowheadAngle = GetNextValue(FileStream, FFT, ArrowheadAngleInputSpec.Min, ArrowheadAngleInputSpec.Max, &IsOk); if (IVersion >= 75) { IsOk = ReadMacroFunctionCommand(FileStream, IVersion, OkToLoad, &Geom->MacroFunctionCommand); } /* version >= 75 */ } /* version >= 70 */ else { Geom->LineThickness = 0.001; Geom->PatternLength = 0.02; Geom->ArrowheadStyle = ArrowheadStyle_Plain; Geom->ArrowheadAttachment = ArrowheadAttachment_None; Geom->ArrowheadSize = 0.05; Geom->ArrowheadAngle = 12.0 / DEGPERRADIANS; } if (IVersion < 41) { GetNextValue(FileStream, FieldDataType_Float, -LARGEDOUBLE, LARGEDOUBLE, &IsOk); GetNextValue(FileStream, FieldDataType_Float, -LARGEDOUBLE, LARGEDOUBLE, &IsOk); GetNextValue(FileStream, FieldDataType_Float, -LARGEDOUBLE, LARGEDOUBLE, &IsOk); } if (IVersion < 70) Geom->DataType = FieldDataType_Float; else Geom->DataType = (FieldDataType_e)GetIoFileInt(FileStream, IVersion, 1, 2, &IsOk); CHECK(VALID_GEOM_FIELD_DATA_TYPE(Geom->DataType)); Geom->Clipping = Clipping_ClipToViewport; /* default value for pre 101 versions */ if (IVersion >= 101) { Geom->Clipping = (Clipping_e)GetIoFileInt(FileStream, IVersion, 0, 2, &IsOk); /* * The second clipping value was deprecated during v10 development and thus removed. * This moved Clipping_ClipToFrame to the 2nd position from the 3rd, so we convert * value 2 to ClipToFrame to support files made during v10 developement. */ if (Geom->Clipping == (Clipping_e)2) Geom->Clipping = Clipping_ClipToFrame; } if (IVersion < 50 || Geom->GeomType == GeomType_LineSegs) { Geom->NumSegments = (SmInteger_t)GetIoFileInt(FileStream, IVersion, 1, MaxGeoSegments, &IsOk); #if defined TECPLOTKERNEL /* CORE SOURCE CODE REMOVED */ #endif S = -1; I = 0; while ((S + 1 < Geom->NumSegments) && !feof(FileStream->File) && IsOk) { S++; Geom->NumSegPts[S] = GetIoFileInt(FileStream, IVersion, 1, MAXINDEX, &IsOk); if ((I + Geom->NumSegPts[S] > MaxDataPts) && OkToLoad) { ErrMsgString = translate("Geometry is too big"); IsOk = FALSE; } else { ReadBlock(FileStream, Geom->GeomData.Generic.V1Base, OkToLoad, Geom->DataType, I, I + Geom->NumSegPts[S] - 1, &IsOk); ReadBlock(FileStream, Geom->GeomData.Generic.V2Base, OkToLoad, Geom->DataType, I, I + Geom->NumSegPts[S] - 1, &IsOk); if (Geom->PositionCoordSys == CoordSys_Grid3D) ReadBlock(FileStream, Geom->GeomData.Generic.V3Base, OkToLoad, Geom->DataType, I, I + Geom->NumSegPts[S] - 1, &IsOk); I += Geom->NumSegPts[S]; } } if (IsOk && (Geom->GeomType == GeomType_Rectangle)) /* IVersion < 50 */ { if (OkToLoad) { CopyFieldValue(Geom->GeomData.Generic.V1Base, 0, Geom->GeomData.Generic.V1Base, 2); CopyFieldValue(Geom->GeomData.Generic.V2Base, 0, Geom->GeomData.Generic.V2Base, 2); } } } else if (Geom->GeomType == GeomType_Rectangle || Geom->GeomType == GeomType_Ellipse) { double XX, YY; XX = GetNextValue(FileStream, Geom->DataType, -LARGEDOUBLE, LARGEDOUBLE, &IsOk); YY = GetNextValue(FileStream, Geom->DataType, -LARGEDOUBLE, LARGEDOUBLE, &IsOk); if (OkToLoad) { SetFieldValue(Geom->GeomData.XYZ.XBase, 0, XX); SetFieldValue(Geom->GeomData.XYZ.YBase, 0, YY); } Geom->NumSegments = 1; Geom->NumSegPts[0] = 1; } else { double XX; CHECK((Geom->GeomType == GeomType_Square) || (Geom->GeomType == GeomType_Circle)); XX = GetNextValue(FileStream, Geom->DataType, -LARGEDOUBLE, LARGEDOUBLE, &IsOk); if (OkToLoad) { SetFieldValue(Geom->GeomData.XYZ.XBase, 0, XX); } Geom->NumSegments = 1; Geom->NumSegPts[0] = 1; } if (!IsOk) ErrMsg(ErrMsgString); return (IsOk); } /* * Pass1 for text simply acknowledges that a text was * parsed and skips over the text. */ Boolean_t ReadInText(FileStream_s *FileStream, short IVersion, Boolean_t OkToLoad, Text_s *Text, LgIndex_t MaxTextLen) { LgIndex_t I; FieldDataType_e FFT; SmInteger_t TextLength = 0; Boolean_t IsOk = TRUE; TranslatedString ErrMsgString = translate("Invalid text record"); REQUIRE(VALID_REF(Text)); if (IVersion < 70) FFT = FieldDataType_Float; else FFT = FieldDataType_Double; if (IVersion < 101) I = GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk); else I = GetIoFileInt(FileStream, IVersion, 0, 4, &IsOk); if (I == 0) Text->PositionCoordSys = CoordSys_Grid; else if (I == 1) Text->PositionCoordSys = CoordSys_Frame; /* * I == 2 is for CoordSys_FrameOffset and is not used currently * * I == 3 is for the old window coordinate system */ else if (I == 4) Text->PositionCoordSys = CoordSys_Grid3D; else { ErrMsgString = translate("Invalid text coordinate system."); IsOk = FALSE; } Text->Scope = (Scope_e)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk); Text->AnchorPos.Generic.V1 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk); Text->AnchorPos.Generic.V2 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk); if (IVersion >= 101) Text->AnchorPos.Generic.V3 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk); else Text->AnchorPos.Generic.V3 = 0.0; /* default value for pre 101 versions */ if (IVersion > 40) Text->TextShape.Font = (Font_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)Font_CourierBold, &IsOk); else Text->TextShape.Font = Font_Helvetica; if (IVersion < 43) GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk); if (IVersion < 70) { if (Text->PositionCoordSys == CoordSys_Grid) Text->TextShape.SizeUnits = Units_Grid; else Text->TextShape.SizeUnits = Units_Frame; } else Text->TextShape.SizeUnits = (Units_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)Units_Point, &IsOk); Text->TextShape.Height = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk); if (IVersion > 47) { Text->Box.BoxType = (TextBox_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)TextBox_Hollow, &IsOk); if (IVersion < 70) { if (Text->Box.BoxType == TextBox_Hollow) Text->Box.BoxType = TextBox_Filled; else if (Text->Box.BoxType == TextBox_Filled) Text->Box.BoxType = TextBox_Hollow; } Text->Box.Margin = GetNextValue(FileStream, FFT, TextBoxMarginInputSpec.Min, TextBoxMarginInputSpec.Max, &IsOk); if (IVersion >= 70) Text->Box.LineThickness = GetNextValue(FileStream, FFT, LineThicknessInputSpec.Min, LineThicknessInputSpec.Max, &IsOk); else Text->Box.LineThickness = 0.01; Text->Box.BColor = (ColorIndex_t)GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk); Text->Box.FillBColor = (ColorIndex_t)GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk); AdjustCustomColor(IVersion, &Text->Box.BColor); AdjustCustomColor(IVersion, &Text->Box.FillBColor); } else { Text->Box.BoxType = TextBox_None; Text->Box.Margin = 0.0; Text->Box.BColor = White_C; Text->Box.FillBColor = Black_C; } if (IVersion < 70) { Text->Angle = GetIoFileInt(FileStream, IVersion, -720, 720, &IsOk) / DEGPERRADIANS; Text->LineSpacing = 1; Text->Anchor = TextAnchor_Left; } else { Text->Angle = GetNextValue(FileStream, FFT, TextAngleInputSpec.Min, TextAngleInputSpec.Max, &IsOk); Text->LineSpacing = GetNextValue(FileStream, FFT, TextLineSpacingInputSpec.Min, TextLineSpacingInputSpec.Max, &IsOk); Text->Anchor = (TextAnchor_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)TextAnchor_HeadRight, &IsOk); } GetZoneAttachment(FileStream, IVersion, &Text->Zone, &Text->AttachToZone, &IsOk); Text->BColor = (ColorIndex_t)GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk); AdjustCustomColor(IVersion, &Text->BColor); if (IVersion < 70) TextLength = (short)GetIoFileInt(FileStream, IVersion, 0, 5000, &IsOk); ResetString(&Text->MacroFunctionCommand, NULL, TRUE); Text->Clipping = Clipping_ClipToViewport; /* default value for pre 101 versions */ if (IVersion < 70) { short I, S; for (I = 0; I < TextLength; I++) { S = (short)GetIoFileInt(FileStream, IVersion, 0, 1000, &IsOk); if (OkToLoad && (I <= MaxTextLen)) Text->Text[I] = (char)S; } if (OkToLoad) Text->Text[MIN(TextLength, MaxTextLen)] = '\0'; } else { char *S = NULL; if (IVersion >= 75) { IsOk = ReadMacroFunctionCommand(FileStream, IVersion, OkToLoad, &Text->MacroFunctionCommand); } /* IVersion >= 75 */ if (IVersion >= 101) { /* * The second clipping value was deprecated during v10 development and thus removed. * This moved Clipping_ClipToFrame to the 2nd position from the 3rd, so we convert * value 2 to ClipToFrame to support files made during v10 developement. */ Text->Clipping = (Clipping_e)GetIoFileInt(FileStream, IVersion, 0, 2, &IsOk); if (Text->Clipping == (Clipping_e)2) Text->Clipping = Clipping_ClipToFrame; } if (ReadInString(FileStream, IVersion, MaxTextLen, &S, OkToLoad)) { REQUIRE(!(S || OkToLoad) || VALID_REF(Text->Text)); if (S) { #if defined TECPLOTKERNEL /* CORE SOURCE CODE REMOVED */ #endif /* TECPLOTKERNEL */ if (IsOk) { strcpy(Text->Text, S); } FREE_ARRAY(S, "Release temp string for new text label"); } else if (OkToLoad) Text->Text[0] = '\0'; } else IsOk = FALSE; } if (!IsOk) ErrMsg(ErrMsgString); return (IsOk); } static Boolean_t CompareVersion(float Version, char *VersionString, Boolean_t IsByteOrderNative) { char *VersionBuf = (char *) & Version; REQUIRE(VALID_REF(VersionString)); if (IsByteOrderNative) return ((VersionString[0] == VersionBuf[0]) && (VersionString[1] == VersionBuf[1]) && (VersionString[2] == VersionBuf[2]) && (VersionString[3] == VersionBuf[3])); else return ((VersionString[3] == VersionBuf[0]) && (VersionString[2] == VersionBuf[1]) && (VersionString[1] == VersionBuf[2]) && (VersionString[0] == VersionBuf[3])); } static float ValidVersions[] = {7.0F, 6.3F, 6.2F, 6.1F, 6.0F, 5.0F, 4.7F, 4.6F, 4.5F, 4.4F, 4.3F, 4.2F, 4.1F, 4.0F }; #define NUMVALIDVERSIONS ((int)(sizeof(ValidVersions)/sizeof(ValidVersions[0]))) /* * Extra caution taken here in case value read is invalid float */ static Boolean_t GetDoubleVersion(char *VersionString, float *FInputVersion, Boolean_t IsByteOrderNative) { int I; REQUIRE(VALID_REF(FInputVersion)); for (I = 0; I < NUMVALIDVERSIONS; I++) if (CompareVersion(ValidVersions[I], VersionString, IsByteOrderNative)) { *FInputVersion = ValidVersions[I]; return (TRUE); } return (FALSE); } static short GetNewInputVersion(FileStream_s *FileStream) { /* * */ char Buf[4]; short IVersion = 0; short I; LgIndex_t OneValue; Boolean_t IsOk = TRUE; REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File)); REQUIRE(FileStream->IsByteOrderNative); if (TP_FREAD(Buf, 4, 1, FileStream->File) != 1) return (0); if (strncmp(Buf, "#!TD", 4)) return (0); if (TP_FREAD(Buf, 4, 1, FileStream->File) != 1) return (0); if (Buf[0] != 'V') return (0); I = 1; while ((I < 4) && isdigit(Buf[I])) IVersion = IVersion * 10 + Buf[I++] - '0'; if (IVersion < 70) return (0); else if (IVersion > TecplotBinaryFileVersion) { ErrMsg(translate("Binary file version newer than Tecplot version. " "Upgrade Tecplot or use an older Preplot to produce " "the datafile.")); return (IVersion); } /* * Determine Byte Order. */ OneValue = GetIoFileInt(FileStream, IVersion, -MAXINDEX, MAXINDEX, &IsOk); if (!IsOk) return (0); FileStream->IsByteOrderNative = (OneValue == 1); return (IVersion); } /** * Return value of zero is to be considered as an invalid * tecplot binary datafile header. Actually binary files * older than version 4.0 (return value of 40) are not supported * (See notes in preplot.c). */ short GetInputVersion(FileStream_s *FileStream) { Boolean_t IsOk = TRUE; float FInputVersion; short IVersion; char VersionString[4]; FileOffset_t StartOffset = 0; /* * First check to see if file uses new * input version format. */ /* keep track of our start offset */ StartOffset = TP_FTELL(FileStream->File); IVersion = GetNewInputVersion(FileStream); if (IVersion > TecplotBinaryFileVersion) return IVersion; /* unsupported version */ else if (IVersion == 0) { /* rewind to clear any errors and seek to the start offset */ rewind(FileStream->File); IsOk = (TP_FSEEK(FileStream->File, StartOffset, SEEK_SET) == 0); if (IsOk && TP_FREAD(VersionString, 4, 1, FileStream->File) == 1) { /* try both native and foreign versions numbers */ if (!GetDoubleVersion(VersionString, &FInputVersion, FileStream->IsByteOrderNative)) { FileStream->IsByteOrderNative = !FileStream->IsByteOrderNative; /* ...reverse the byte order */ IsOk = GetDoubleVersion(VersionString, &FInputVersion, FileStream->IsByteOrderNative); } if (IsOk) IVersion = ROUNDS(FInputVersion * 10); } } if (IsOk) return (IVersion); else return ((short)0); } #if defined TECPLOTKERNEL /* CORE SOURCE CODE REMOVED */ #if !defined ENGINE /* TODO(RMS)-H 12/12/2005: ENGINE: refactor to use just the Interrupted flag as-is */ #else #endif #endif /********************************************************************** ********************************************************************** ********************** OUTPUT ************************** ********************************************************************** **********************************************************************/ /** * Byte blocks cannot be unaligned or reversed in bytes */ Boolean_t WriteBinaryByteBlock(FileStream_s *FileStream, const Byte_t *ByteValues, const HgIndex_t NumValues) { REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File)); REQUIRE(VALID_REF(ByteValues)); REQUIRE(NumValues >= 0); Boolean_t IsOk = TP_FWRITE(ByteValues, sizeof(Byte_t), (size_t)NumValues, FileStream->File) == (size_t)NumValues; ENSURE(VALID_BOOLEAN(IsOk)); return IsOk; } /** * Type Byte_t cannot be unaligned or reversed in byte order */ static inline Boolean_t WriteBinaryByte(FileStream_s *FileStream, Byte_t ByteValue) { REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File)); Boolean_t IsOk = WriteBinaryByteBlock(FileStream, &ByteValue, 1); ENSURE(VALID_BOOLEAN(IsOk)); return IsOk; } /** */ template void CopyAndReverseUnalignedBytes(T *DstBuffer, const Byte_t *SrcBuffer) { REQUIRE(VALID_REF(DstBuffer)); REQUIRE(VALID_REF(SrcBuffer)); size_t typeSize = sizeof(T); for (size_t ii = 0; ii < typeSize; ii++) ((Byte_t *)(DstBuffer))[ii] = ((Byte_t *)(SrcBuffer))[typeSize-1-ii]; } /** */ template void CopyUnalignedBytes(T *DstBuffer, const Byte_t *SrcBuffer) { REQUIRE(VALID_REF(DstBuffer)); REQUIRE(VALID_REF(SrcBuffer)); for (size_t ii = 0; ii < sizeof(T); ii++) ((Byte_t *)(DstBuffer))[ii] = ((Byte_t *)(SrcBuffer))[ii]; } /** */ template Boolean_t WriteBinaryDataUnaligned(FileStream_s *FileStream, const Byte_t *ValueBuffer, const Boolean_t ValueInNativeOrder) { REQUIRE(VALID_REF(FileStream) && VALID_FILE_HANDLE(FileStream->File)); REQUIRE(VALID_REF(ValueBuffer)); REQUIRE(VALID_BOOLEAN(ValueInNativeOrder)); T DataValue; if (ValueInNativeOrder != FileStream->IsByteOrderNative) CopyAndReverseUnalignedBytes(&DataValue, ValueBuffer); else CopyUnalignedBytes(&DataValue, ValueBuffer); Boolean_t IsOk = TP_FWRITE(&DataValue, sizeof(T), 1, FileStream->File) == 1; ENSURE(VALID_BOOLEAN(IsOk)); return IsOk; } /** * This is used in many places and requires the value be in proper order. */ Boolean_t WriteBinaryInt16(FileStream_s *FileStream, Int16_t Value) { Boolean_t IsOk; REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File)); REQUIRE("Value can be any Int16_t"); IsOk = WriteBinaryDataUnaligned(FileStream, (Byte_t *) & Value, TRUE/*ValueInNativeOrder*/); ENSURE(VALID_BOOLEAN(IsOk)); return IsOk; } /** * This is used in many places and requires the value be in proper order. */ Boolean_t WriteBinaryInt32(FileStream_s *FileStream, Int32_t Value) { Boolean_t IsOk; REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File)); REQUIRE("Value can be any Int32_t"); IsOk = WriteBinaryDataUnaligned(FileStream, (Byte_t *) & Value, TRUE/*ValueInNativeOrder*/); ENSURE(VALID_BOOLEAN(IsOk)); return IsOk; } /** */ template Boolean_t WriteBinaryBlockUnaligned(FileStream_s *FileStream, const Byte_t *Values, const HgIndex_t NumValues, const Boolean_t ValuesInNativeOrdering) { Boolean_t IsOk = TRUE; Boolean_t WriteEachValueSeparately; REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File)); REQUIRE(VALID_REF(Values)); REQUIRE(NumValues >= 0); REQUIRE(VALID_BOOLEAN(ValuesInNativeOrdering)); WriteEachValueSeparately = (ValuesInNativeOrdering != FileStream->IsByteOrderNative); if (WriteEachValueSeparately) { for (HgIndex_t NIndex = 0; IsOk && NIndex < NumValues; NIndex++) { IsOk = WriteBinaryDataUnaligned(FileStream, Values + NIndex * sizeof(T), ValuesInNativeOrdering); } } else { #if 1 size_t NumBytesToWrite = NumValues * sizeof(T); size_t NumBytesWritten = TP_FWRITE(Values, sizeof(Byte_t), NumBytesToWrite, FileStream->File); IsOk = NumBytesToWrite == NumBytesWritten; #else IsOk = WriteBinaryByteBlock(FileStream, Values, NumValues * sizeof(T)); #endif } ENSURE(VALID_BOOLEAN(IsOk)); return IsOk; } /** * Use Byte_t instead of Int16_t to support unaligned values */ Boolean_t WriteBinaryInt16BlockUnaligned(FileStream_s *FileStream, Byte_t *Int16Values, HgIndex_t NumValues, Boolean_t ValuesInNativeOrdering) { REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File)); REQUIRE(VALID_REF(Int16Values)); REQUIRE(NumValues >= 0); REQUIRE(VALID_BOOLEAN(ValuesInNativeOrdering)); Boolean_t IsOk = WriteBinaryBlockUnaligned(FileStream, Int16Values, NumValues, ValuesInNativeOrdering); ENSURE(VALID_BOOLEAN(IsOk)); return IsOk; } /** * Use Byte_t instead of Int32_t to support unaligned values */ Boolean_t WriteBinaryInt32BlockUnaligned(FileStream_s *FileStream, Byte_t *Int32Values, HgIndex_t NumValues, Boolean_t ValuesInNativeOrdering) { REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File)); REQUIRE(VALID_REF(Int32Values)); REQUIRE(NumValues >= 0); REQUIRE(VALID_BOOLEAN(ValuesInNativeOrdering)); Boolean_t IsOk = WriteBinaryBlockUnaligned(FileStream, Int32Values, NumValues, ValuesInNativeOrdering); ENSURE(VALID_BOOLEAN(IsOk)); return IsOk; } /** */ Boolean_t WriteBinaryReal(FileStream_s *FileStream, double RR, FieldDataType_e FieldDataType) { Boolean_t IsOk = FALSE; /* ...quite compiler */ REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File)); REQUIRE((FieldDataType == FieldDataType_Float) || (FieldDataType == FieldDataType_Double) || (FieldDataType == FieldDataType_Byte)); switch (FieldDataType) { case FieldDataType_Float : { float FloatVal = CONVERT_DOUBLE_TO_FLOAT(RR); IsOk = WriteBinaryDataUnaligned(FileStream, (Byte_t *) & FloatVal, TRUE/*NativeOrdering*/); } break; case FieldDataType_Double : { double DoubleVal = CLAMP_DOUBLE(RR); IsOk = WriteBinaryDataUnaligned(FileStream, (Byte_t *) & DoubleVal, TRUE/*NativeOrdering*/); } break; case FieldDataType_Byte : { /* Note: type Byte cannot be unaligned or reversed in bytes */ Byte_t B; if (RR > 255) B = 255; else if (RR < 0) B = 0; else B = (Byte_t)RR; IsOk = WriteBinaryByte(FileStream, B); } break; default: CHECK(FALSE); break; } ENSURE(VALID_BOOLEAN(IsOk)); return IsOk; } Boolean_t WriteFieldDataType(FileStream_s *FileStream, FieldDataType_e FDT, Boolean_t WriteBinary) { if (WriteBinary) return (WriteBinaryInt32(FileStream, (LgIndex_t)FDT)); else { short S = 0; switch (FDT) { case FieldDataType_Float : S = fprintf(FileStream->File, "SINGLE "); break; case FieldDataType_Double : S = fprintf(FileStream->File, "DOUBLE "); break; case FieldDataType_Int32 : S = fprintf(FileStream->File, "LONGINT "); break; case FieldDataType_Int16 : S = fprintf(FileStream->File, "SHORTINT "); break; case FieldDataType_Byte : S = fprintf(FileStream->File, "BYTE "); break; case FieldDataType_Bit : S = fprintf(FileStream->File, "BIT "); break; default: CHECK(FALSE); } return (FPRINTFOK(S)); } } /** */ template Boolean_t WriteBinaryChecksumByteValues(FileStream_s *FileStream, const Byte_t *ByteValues, const HgIndex_t NumValues) { REQUIRE(VALID_REF(FileStream) && VALID_FILE_HANDLE(FileStream->File)); REQUIRE(VALID_REF(ByteValues)); REQUIRE(NumValues >= 1); Boolean_t IsOk; if (NumValues == 1) IsOk = WriteBinaryDataUnaligned(FileStream, ByteValues, TRUE); else IsOk = WriteBinaryBlockUnaligned(FileStream, ByteValues, NumValues, TRUE); #if defined TECPLOTKERNEL /* CORE SOURCE CODE REMOVED */ #endif ENSURE(VALID_BOOLEAN(IsOk)); return IsOk; } /** * For FieldData of Type Bit, use WriteBinaryFieldDataBlockOfTypeBit instead. */ template Boolean_t WriteBinaryFieldDataBlockOfType(FileStream_s *FileStream, const FieldData_pa FieldData, const LgIndex_t StartOffset, const LgIndex_t NumValues) { #if defined TECPLOTKERNEL /* CORE SOURCE CODE REMOVED */ #endif Boolean_t IsOk = FALSE; if (IsFieldDataDirectAccessAllowed(FieldData)) { Byte_t *ByteArray = GetFieldDataBytePtr(FieldData) + StartOffset * sizeof(T); IsOk = WriteBinaryChecksumByteValues(FileStream, ByteArray, (HgIndex_t)NumValues); } else { for (LgIndex_t Offset = StartOffset; Offset < NumValues; Offset++) { T ValueBuffer = (T)GetFieldValue(FieldData, Offset); Byte_t *ByteValue = (Byte_t *) & ValueBuffer; IsOk = WriteBinaryChecksumByteValues(FileStream, ByteValue, 1); } } ENSURE(VALID_BOOLEAN(IsOk)); return IsOk; } static Boolean_t WriteBinaryFieldDataBlockOfTypeBit(FileStream_s *FileStream, const FieldData_pa FieldData, const LgIndex_t StartOffset, /* Not used */ const LgIndex_t NumValues) { #if defined TECPLOTKERNEL /* CORE SOURCE CODE REMOVED */ #endif Boolean_t IsOk = FALSE; size_t NumBytes = 1 + (NumValues - 1) / 8; if (IsFieldDataDirectAccessAllowed(FieldData)) { Byte_t *ByteArray = GetFieldDataBytePtr(FieldData); IsOk = WriteBinaryChecksumByteValues(FileStream, ByteArray, (HgIndex_t)NumBytes); } else { // Bits are written out a Byte at a time and since we only come in here every 8th // bit, make sure to assemble a Byte value from the next 8 bits. for (LgIndex_t Offset = 0; Offset < NumValues; Offset += 8) { Byte_t ValueBuffer = 0; for (int ii = 0; ii < 8; ii++) { Byte_t CurBit = (Byte_t)GetFieldValue(FieldData, Offset + ii); ValueBuffer |= (CurBit << ii); } IsOk = WriteBinaryChecksumByteValues(FileStream, &ValueBuffer, 1); } } ENSURE(VALID_BOOLEAN(IsOk)); return IsOk; } /* */ Boolean_t WriteBinaryFieldDataBlock(FileStream_s *FileStream, FieldData_pa FieldData, LgIndex_t StartOffset, LgIndex_t NumValues) { #if defined TECPLOTKERNEL /* CORE SOURCE CODE REMOVED */ #endif Boolean_t IsOk = FALSE; switch (GetFieldDataType(FieldData)) { case FieldDataType_Float : IsOk = WriteBinaryFieldDataBlockOfType(FileStream, FieldData, StartOffset, NumValues); break; case FieldDataType_Double : IsOk = WriteBinaryFieldDataBlockOfType(FileStream, FieldData, StartOffset, NumValues); break; case FieldDataType_Int32 : IsOk = WriteBinaryFieldDataBlockOfType(FileStream, FieldData, StartOffset, NumValues); break; case FieldDataType_Int16 : IsOk = WriteBinaryFieldDataBlockOfType(FileStream, FieldData, StartOffset, NumValues); break; case FieldDataType_Byte : IsOk = WriteBinaryFieldDataBlockOfType(FileStream, FieldData, StartOffset, NumValues); break; case FieldDataType_Bit : IsOk = WriteBinaryFieldDataBlockOfTypeBit(FileStream, FieldData, StartOffset, NumValues); break; default: CHECK(FALSE); break; } ENSURE(VALID_BOOLEAN(IsOk)); return IsOk; } static Boolean_t WriteASCIIFieldDataValue(FileStream_s *FileStream, FieldData_pa FieldData, LgIndex_t Offset, SmInteger_t AsciiPrecision) { Boolean_t IsOk = FALSE; /* ...quiet compiler */ #if defined TECPLOTKERNEL /* CORE SOURCE CODE REMOVED */ #endif double V = 0.0; char buffer[100*MAX_SIZEOFUTF8CHAR]; char *AsciiValue = buffer; #ifdef TECPLOTKERNEL /* CORE SOURCE CODE REMOVED */ #endif V = GetFieldValue(FieldData, Offset); switch (GetFieldDataType(FieldData)) { case FieldDataType_Float : case FieldDataType_Double : /*IsOk = FPRINTFOK(fprintf(FileStream->File," %.*E",(int)AsciiPrecision,V)); */ sprintf(buffer, " %.*E", (int)AsciiPrecision, V); break; case FieldDataType_Int32 : /* IsOk = FPRINTFOK(fprintf(FileStream->File," %*d",(int)AsciiPrecision,ROUNDL(V))); */ sprintf(buffer, " %*d", (int)AsciiPrecision, ROUNDL(V)); break; case FieldDataType_Int16 : /* IsOk = FPRINTFOK(fprintf(FileStream->File," %6d",ROUND2(V))); */ sprintf(buffer, " %6d", ROUND2(V)); break; case FieldDataType_Byte : /* IsOk = FPRINTFOK(fprintf(FileStream->File," %3d",ROUNDS(V))); */ sprintf(buffer, " %3d", ROUNDS(V)); break; case FieldDataType_Bit : /* IsOk = FPRINTFOK(fprintf(FileStream->File," %c",((V == 0) ? '0' : '1'))); */ sprintf(buffer, " %c", ((V == 0) ? '0' : '1')); break; default: CHECK(FALSE); break; } IsOk = FPRINTFOK(fprintf(FileStream->File, buffer)); #if defined TECPLOTKERNEL /* CORE SOURCE CODE REMOVED */ #endif ENSURE(VALID_BOOLEAN(IsOk)); return (IsOk); } /** */ Boolean_t 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) { Boolean_t IsOk = TRUE; LgIndex_t NumValues; LgIndex_t I, J, K; LgIndex_t NumIJPts = -1; LgIndex_t IEnd = -1; LgIndex_t JEnd = -1; LgIndex_t KEnd = -1; Boolean_t IsLinear = -1; REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File)); REQUIRE(VALID_REF(FieldData)); REQUIRE(VALID_BOOLEAN(IsOrderedData)); REQUIRE(NumIPts >= 0); REQUIRE(NumJPts >= 0); REQUIRE(NumKPts >= 0); REQUIRE(VALID_BOOLEAN(WriteBinary)); REQUIRE(IMPLICATION(!WriteBinary, AsciiPrecision >= 0)); /* * As of version 103 Tecplot writes binary data files so that ordered cell * centered field data includes the ghost cells. This makes it much easier * for Tecplot to map the data when reading by simply writing out * FieldData->NumValues. As of version 104 the ghost cells of the slowest * moving index are not included but that does effect the output as it is * still FieldData->NumValues. */ if (IsOrderedData && !WriteBinary) { /* * Ordered ASCII output is always layed out using * DataValueStructure_Classic format. */ NumIJPts = NumIPts * NumJPts; IEnd = MAX(NumIPts - 1, 1); JEnd = MAX(NumJPts - 1, 1); KEnd = MAX(NumKPts - 1, 1); NumValues = (IEnd * JEnd * KEnd); IsLinear = ((NumJPts == 1 && NumKPts == 1) || (NumIPts == 1 && NumKPts == 1) || (NumIPts == 1 && NumJPts == 1)); } else { NumValues = GetFieldDataNumValues(FieldData); } if (WriteBinary) { IsOk = WriteBinaryFieldDataBlock(FileStream, FieldData, 0, NumValues); } else { LgIndex_t NumValuesPerLine = 80 / (AsciiPrecision + 5); if (IsOrderedData && !IsLinear) { LgIndex_t ValueIndex = 0; for (K = 0; K < KEnd && IsOk; K++) for (J = 0; J < JEnd && IsOk; J++) for (I = 0; I < IEnd && IsOk; I++) { LgIndex_t CellIndex = I + (J * NumIPts) + (K * NumIJPts); IsOk = WriteASCIIFieldDataValue(FileStream, FieldData, CellIndex, AsciiPrecision); if ((ValueIndex + 1) % NumValuesPerLine == 0 || ValueIndex == NumValues - 1) IsOk = (fputc('\n', FileStream->File) != EOF); ValueIndex++; } } else { for (I = 0; I < NumValues && IsOk; I++) { IsOk = WriteASCIIFieldDataValue(FileStream, FieldData, I, AsciiPrecision); if ((I + 1) % NumValuesPerLine == 0 || I == NumValues - 1) IsOk = (fputc('\n', FileStream->File) != EOF); } } } ENSURE(VALID_BOOLEAN(IsOk)); return IsOk; } Boolean_t DumpDatafileString(FileStream_s *FileStream, const char *S, Boolean_t WriteBinary) { Boolean_t IsOk = TRUE; const char *CPtr = S; if (WriteBinary) { const char *CPtr = S; while (IsOk && CPtr && *CPtr) IsOk = WriteBinaryInt32(FileStream, (LgIndex_t)(unsigned char) * CPtr++); if (IsOk) IsOk = WriteBinaryInt32(FileStream, 0); } else { fputc('"', FileStream->File); while (CPtr && *CPtr) { if (*CPtr == '\n') { CPtr++; fputc('\\', FileStream->File); fputc('\\', FileStream->File); fputc('n', FileStream->File); } else { if ((*CPtr == '"') || (*CPtr == '\\')) fputc('\\', FileStream->File); fputc(*CPtr++, FileStream->File); } } fputc('"', FileStream->File); IsOk = (fputc('\n', FileStream->File) != EOF); } return (IsOk); } static void WriteAsciiColor(FILE *File, ColorIndex_t Color) { if (Color >= FirstCustomColor && Color <= LastCustomColor) fprintf(File, "CUST%1d ", Color - FirstCustomColor + 1); else { switch (Color) { case Black_C : fprintf(File, "BLACK "); break; case Red_C : fprintf(File, "RED "); break; case Green_C : fprintf(File, "GREEN "); break; case Blue_C : fprintf(File, "BLUE "); break; case Cyan_C : fprintf(File, "CYAN "); break; case Yellow_C : fprintf(File, "YELLOW "); break; case Purple_C : fprintf(File, "PURPLE "); break; case White_C : fprintf(File, "WHITE "); break; } } } static void 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) { REQUIRE(VALID_REF(File)); REQUIRE(VALID_TEXT_COORDSYS(CoordSys) || VALID_GEOM_COORDSYS(CoordSys)); REQUIRE(VALID_BOOLEAN(AttachToZone)); REQUIRE(IMPLICATION(AttachToZone, Zone >= 0)); REQUIRE(VALID_ENUM(Scope, Scope_e)); REQUIRE(VALID_BOOLEAN(IncludeZ)); REQUIRE(VALID_BOOLEAN(WriteGridDataAsPolar)); REQUIRE(VALID_REF(AnchorPos)); fprintf(File, "CS="); if (CoordSys == CoordSys_Frame) fprintf(File, "FRAME"); else if (CoordSys == CoordSys_Grid) fprintf(File, "GRID"); /* * Not currently used * else if (CoordSys == CoordSys_FrameOffset) fprintf(File,"FRAMEOFFSET"); */ else if (CoordSys == CoordSys_Grid3D) fprintf(File, "GRID3D"); else CHECK(FALSE); if (CoordSys == CoordSys_Grid && !IncludeZ && WriteGridDataAsPolar) { fprintf(File, "\nTHETA=%.12G,R=%.12G", ScaleFact*AnchorPos->ThetaR.Theta, ScaleFact*AnchorPos->ThetaR.R); CHECK(!IncludeZ); } else { fprintf(File, "\nX=%.12G,Y=%.12G", ScaleFact*AnchorPos->XYZ.X, ScaleFact*AnchorPos->XYZ.Y); if (IncludeZ) fprintf(File, ",Z=%.12G", ScaleFact*AnchorPos->XYZ.Z); } if (AttachToZone) fprintf(File, "\nZN=%d", Zone + 1); fprintf(File, "\nC="); WriteAsciiColor(File, Color); fprintf(File, "\nS="); if (Scope == Scope_Global) fprintf(File, "GLOBAL"); else if (Scope == Scope_Local) fprintf(File, "LOCAL"); else CHECK(FALSE); fputc('\n', File); } bool DumpGeometry(FileStream_s* FileStream, Geom_s const* Geom, Boolean_t WriteBinary, Boolean_t WriteGridDataAsPolar) { LgIndex_t I, Index; LgIndex_t SegIndex; bool IsOk = TRUE; FieldDataType_e FDT; REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File)); REQUIRE(VALID_REF(Geom)); REQUIRE(Geom->GeomType != GeomType_Image); if (WriteBinary) { WriteBinaryReal(FileStream, GeomMarker, FieldDataType_Float); if (Geom->PositionCoordSys == CoordSys_Grid) WriteBinaryInt32(FileStream, 0); else if (Geom->PositionCoordSys == CoordSys_Frame) WriteBinaryInt32(FileStream, 1); #if 0 /* * Not currently used */ else if (Geom->PositionCoordSys == CoordSys_FrameOffset) WriteBinaryInt32(FileStream, 2); #endif /* * PositionCoordSys == 3 is for old window coordinate system */ else if (Geom->PositionCoordSys == CoordSys_Grid3D) WriteBinaryInt32(FileStream, 4); else CHECK(FALSE); WriteBinaryInt32(FileStream, (LgIndex_t)Geom->Scope); WriteBinaryInt32(FileStream, (LgIndex_t)Geom->DrawOrder); WriteBinaryReal(FileStream, Geom->AnchorPos.Generic.V1, FieldDataType_Double); WriteBinaryReal(FileStream, Geom->AnchorPos.Generic.V2, FieldDataType_Double); WriteBinaryReal(FileStream, Geom->AnchorPos.Generic.V3, FieldDataType_Double); if (Geom->AttachToZone) WriteBinaryInt32(FileStream, (LgIndex_t)Geom->Zone); else WriteBinaryInt32(FileStream, (LgIndex_t) - 1); WriteBinaryInt32(FileStream, (LgIndex_t)Geom->BColor); WriteBinaryInt32(FileStream, (LgIndex_t)Geom->FillBColor); WriteBinaryInt32(FileStream, (LgIndex_t)Geom->IsFilled); CHECK(Geom->GeomType != GeomType_LineSegs3D); /* deprecated */ WriteBinaryInt32(FileStream, (LgIndex_t)Geom->GeomType); WriteBinaryInt32(FileStream, (LgIndex_t)Geom->LinePattern); WriteBinaryReal(FileStream, Geom->PatternLength, FieldDataType_Double); WriteBinaryReal(FileStream, Geom->LineThickness, FieldDataType_Double); WriteBinaryInt32(FileStream, (LgIndex_t)Geom->NumEllipsePts); WriteBinaryInt32(FileStream, (LgIndex_t)Geom->ArrowheadStyle); WriteBinaryInt32(FileStream, (LgIndex_t)Geom->ArrowheadAttachment); WriteBinaryReal(FileStream, Geom->ArrowheadSize, FieldDataType_Double); WriteBinaryReal(FileStream, Geom->ArrowheadAngle, FieldDataType_Double); /* MACRO FUNCTION COMMAND */ DumpDatafileString(FileStream, Geom->MacroFunctionCommand, TRUE); /* * Assume geometry has X,Y (and Z) all using same field * data type. */ FDT = GetGeomFieldDataType(Geom); WriteFieldDataType(FileStream, FDT, TRUE); WriteBinaryInt32(FileStream, (LgIndex_t)Geom->Clipping); if (Geom->GeomType == GeomType_LineSegs) { short S; WriteBinaryInt32(FileStream, Geom->NumSegments); I = 0; for (S = 0; IsOk && (S < Geom->NumSegments); S++) { WriteBinaryInt32(FileStream, Geom->NumSegPts[S]); WriteBinaryFieldDataBlock(FileStream, Geom->GeomData.Generic.V1Base, I, Geom->NumSegPts[S]); IsOk = WriteBinaryFieldDataBlock(FileStream, Geom->GeomData.Generic.V2Base, I, Geom->NumSegPts[S]) == TRUE; if (Geom->PositionCoordSys == CoordSys_Grid3D) IsOk = WriteBinaryFieldDataBlock(FileStream, Geom->GeomData.Generic.V3Base, I, Geom->NumSegPts[S]) == TRUE; I += Geom->NumSegPts[S]; } } else if (Geom->GeomType == GeomType_Rectangle || Geom->GeomType == GeomType_Ellipse) { WriteBinaryReal(FileStream, GetFieldValue(Geom->GeomData.XYZ.XBase, 0), FDT); IsOk = WriteBinaryReal(FileStream, GetFieldValue(Geom->GeomData.XYZ.YBase, 0), FDT) == TRUE; } else { CHECK((Geom->GeomType == GeomType_Square) || (Geom->GeomType == GeomType_Circle)); IsOk = WriteBinaryReal(FileStream, GetFieldValue(Geom->GeomData.XYZ.XBase, 0), FDT) == TRUE; } } else { double ScaleFact; if (Geom->PositionCoordSys == CoordSys_Frame) ScaleFact = 100.0; else ScaleFact = 1.0; fprintf(FileStream->File, "GEOMETRY\nF=POINT\n"); WriteAsciiTextGeomBasics(FileStream->File, Geom->PositionCoordSys, Geom->AttachToZone, Geom->Zone, Geom->BColor, Geom->Scope, TRUE, WriteGridDataAsPolar, &Geom->AnchorPos, ScaleFact); switch (Geom->LinePattern) { case LinePattern_Solid : fprintf(FileStream->File, "L=SOLID\n"); break; case LinePattern_Dashed : fprintf(FileStream->File, "L=DASHED\n"); break; case LinePattern_DashDot : fprintf(FileStream->File, "L=DASHDOT\n"); break; case LinePattern_Dotted : fprintf(FileStream->File, "L=DOTTED\n"); break; case LinePattern_LongDash : fprintf(FileStream->File, "L=LONGDASH\n"); break; case LinePattern_DashDotDot : fprintf(FileStream->File, "L=DASHDOTDOT\n"); break; default: CHECK(FALSE); break; } fprintf(FileStream->File, "PL=%.12G\n", Geom->PatternLength*PatternLengthInputSpec.InterfaceAdjust.ScaleFact); fprintf(FileStream->File, "LT=%.12G\n", Geom->LineThickness*LineThicknessInputSpec.InterfaceAdjust.ScaleFact); if (Geom->IsFilled) { fprintf(FileStream->File, "FC="); WriteAsciiColor(FileStream->File, Geom->FillBColor); } if (Geom->Clipping == Clipping_ClipToViewport) fprintf(FileStream->File, "CLIPPING=CLIPTOVIEWPORT\n"); else if (Geom->Clipping == Clipping_ClipToFrame) fprintf(FileStream->File, "CLIPPING=CLIPTOFRAME\n"); else CHECK(FALSE); if (Geom->DrawOrder == DrawOrder_AfterData) fprintf(FileStream->File, "DRAWORDER=AFTERDATA\n"); else if (Geom->DrawOrder == DrawOrder_BeforeData) fprintf(FileStream->File, "DRAWORDER=BEFOREDATA\n"); else CHECK(FALSE); /* Macro function command */ fprintf(FileStream->File, "MFC="); DumpDatafileString(FileStream, Geom->MacroFunctionCommand, FALSE); if ((Geom->GeomType == GeomType_Circle) || (Geom->GeomType == GeomType_Ellipse)) fprintf(FileStream->File, "EP=%ld\n", (long)Geom->NumEllipsePts); if (Geom->GeomType == GeomType_LineSegs && Geom->PositionCoordSys != CoordSys_Grid3D) { switch (Geom->ArrowheadStyle) { case ArrowheadStyle_Plain : fprintf(FileStream->File, "AST=PLAIN\n"); break; case ArrowheadStyle_Filled : fprintf(FileStream->File, "AST=FILLED\n"); break; case ArrowheadStyle_Hollow : fprintf(FileStream->File, "AST=HOLLOW\n"); break; default: CHECK(FALSE); break; } switch (Geom->ArrowheadAttachment) { case ArrowheadAttachment_None : break; case ArrowheadAttachment_AtBeginning : fprintf(FileStream->File, "AAT=BEGINNING\n"); break; case ArrowheadAttachment_AtEnd : fprintf(FileStream->File, "AAT=END\n"); break; case ArrowheadAttachment_AtBothEnds : fprintf(FileStream->File, "AAT=BOTH\n"); break; default: CHECK(FALSE); break; } if (Geom->ArrowheadAttachment != ArrowheadAttachment_None) { fprintf(FileStream->File, "ASZ=%.12G\n", Geom->ArrowheadSize*ArrowheadSizeInputSpec.InterfaceAdjust.ScaleFact); fprintf(FileStream->File, "AAN=%.12G\n", Geom->ArrowheadAngle*ArrowheadAngleInputSpec.InterfaceAdjust.ScaleFact); } } switch (Geom->GeomType) { case GeomType_LineSegs : { fprintf(FileStream->File, "T=LINE\n"); fprintf(FileStream->File, "DT="); WriteFieldDataType(FileStream, GetFieldDataType(Geom->GeomData.Generic.V1Base), FALSE); fputc('\n', FileStream->File); fprintf(FileStream->File, "%d\n", (int)Geom->NumSegments); SegIndex = 0; for (I = 0; IsOk && (I < Geom->NumSegments); I++) { fprintf(FileStream->File, "%ld\n", (long)Geom->NumSegPts[I]); for (Index = 0; Index < Geom->NumSegPts[I]; Index++) { fprintf(FileStream->File, "%.12G ", GetFieldValue(Geom->GeomData.Generic.V1Base, SegIndex + Index)*ScaleFact); fprintf(FileStream->File, "%.12G", GetFieldValue(Geom->GeomData.Generic.V2Base, SegIndex + Index)*ScaleFact); if (Geom->PositionCoordSys == CoordSys_Grid3D) IsOk = FPRINTFOK(fprintf(FileStream->File, " %.12G\n", GetFieldValue(Geom->GeomData.Generic.V3Base, SegIndex + Index))); else IsOk = (Boolean_t)(fputc('\n', FileStream->File) != EOF); } SegIndex += Geom->NumSegPts[I]; } } break; case GeomType_Rectangle : { fprintf(FileStream->File, "T=RECTANGLE %.12G %.12G\n", GetFieldValue(Geom->GeomData.XYZ.XBase, 0)*ScaleFact, GetFieldValue(Geom->GeomData.XYZ.YBase, 0)*ScaleFact); } break; case GeomType_Square : { fprintf(FileStream->File, "T=SQUARE %.12G\n", GetFieldValue(Geom->GeomData.XYZ.XBase, 0)*ScaleFact); } break; case GeomType_Circle : { fprintf(FileStream->File, "T=CIRCLE %.12G\n", GetFieldValue(Geom->GeomData.XYZ.XBase, 0)*ScaleFact); } break; case GeomType_Ellipse : { fprintf(FileStream->File, "T=ELLIPSE %.12G %.12G\n", GetFieldValue(Geom->GeomData.XYZ.XBase, 0)*ScaleFact, GetFieldValue(Geom->GeomData.XYZ.YBase, 0)*ScaleFact); } break; default: CHECK(FALSE); } } return IsOk; } /** */ bool DumpText(FileStream_s* FileStream, Text_s const* Text, Boolean_t WriteBinary, Boolean_t WriteGridDataAsPolar) { REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File)); REQUIRE(VALID_REF(Text)); REQUIRE(VALID_BOOLEAN(WriteBinary)); REQUIRE(VALID_BOOLEAN(WriteGridDataAsPolar)); if (WriteBinary) { WriteBinaryReal(FileStream, TextMarker, FieldDataType_Float); if (Text->PositionCoordSys == CoordSys_Grid) WriteBinaryInt32(FileStream, 0); else if (Text->PositionCoordSys == CoordSys_Frame) WriteBinaryInt32(FileStream, 1); #if 0 /* * Not currently used */ else if (Geom->PositionCoordSys == CoordSys_FrameOffset) WriteBinaryInt32(FileStream, 2); #endif /* * 3 is used for old window coordinate system */ else if (Text->PositionCoordSys == CoordSys_Grid3D) WriteBinaryInt32(FileStream, 4); else CHECK(FALSE); WriteBinaryInt32(FileStream, (LgIndex_t)Text->Scope); WriteBinaryReal(FileStream, Text->AnchorPos.Generic.V1, FieldDataType_Double); WriteBinaryReal(FileStream, Text->AnchorPos.Generic.V2, FieldDataType_Double); WriteBinaryReal(FileStream, Text->AnchorPos.Generic.V3, FieldDataType_Double); WriteBinaryInt32(FileStream, (LgIndex_t)Text->TextShape.Font); WriteBinaryInt32(FileStream, (LgIndex_t)Text->TextShape.SizeUnits); WriteBinaryReal(FileStream, Text->TextShape.Height, FieldDataType_Double); WriteBinaryInt32(FileStream, (LgIndex_t)Text->Box.BoxType); WriteBinaryReal(FileStream, Text->Box.Margin, FieldDataType_Double); WriteBinaryReal(FileStream, Text->Box.LineThickness, FieldDataType_Double); WriteBinaryInt32(FileStream, (LgIndex_t)Text->Box.BColor); WriteBinaryInt32(FileStream, (LgIndex_t)Text->Box.FillBColor); WriteBinaryReal(FileStream, Text->Angle, FieldDataType_Double); WriteBinaryReal(FileStream, Text->LineSpacing, FieldDataType_Double); WriteBinaryInt32(FileStream, (LgIndex_t)Text->Anchor); if (Text->AttachToZone) WriteBinaryInt32(FileStream, (LgIndex_t)Text->Zone); else WriteBinaryInt32(FileStream, (LgIndex_t) - 1); WriteBinaryInt32(FileStream, (LgIndex_t)Text->BColor); } else { double ScaleFact; Boolean_t IncludeZ = Text->PositionCoordSys == CoordSys_Grid3D; if (Text->PositionCoordSys == CoordSys_Frame) ScaleFact = 100.0; else ScaleFact = 1.0; fprintf(FileStream->File, "TEXT\n"); WriteAsciiTextGeomBasics(FileStream->File, Text->PositionCoordSys, Text->AttachToZone, Text->Zone, Text->BColor, Text->Scope, IncludeZ, WriteGridDataAsPolar, &Text->AnchorPos, ScaleFact); fprintf(FileStream->File, "HU="); switch (Text->TextShape.SizeUnits) { case Units_Grid : fprintf(FileStream->File, "GRID\n"); break; case Units_Frame : fprintf(FileStream->File, "FRAME\n"); break; case Units_Point : fprintf(FileStream->File, "POINT\n"); break; case Units_AxisPercentage : /* Not allowed */ default: CHECK(FALSE); break; } fprintf(FileStream->File, "LS=%.4G ", Text->LineSpacing); fprintf(FileStream->File, "AN="); switch (Text->Anchor) { case TextAnchor_Left : fprintf(FileStream->File, "LEFT\n"); break; case TextAnchor_Center : fprintf(FileStream->File, "CENTER\n"); break; case TextAnchor_Right : fprintf(FileStream->File, "RIGHT\n"); break; case TextAnchor_MidLeft : fprintf(FileStream->File, "MIDLEFT\n"); break; case TextAnchor_MidCenter : fprintf(FileStream->File, "MIDCENTER\n"); break; case TextAnchor_MidRight : fprintf(FileStream->File, "MIDRIGHT\n"); break; case TextAnchor_HeadLeft : fprintf(FileStream->File, "HEADLEFT\n"); break; case TextAnchor_HeadCenter : fprintf(FileStream->File, "HEADCENTER\n"); break; case TextAnchor_HeadRight : fprintf(FileStream->File, "HEADRIGHT\n"); break; default: CHECK(FALSE); break; } switch (Text->Box.BoxType) { case TextBox_Hollow : fprintf(FileStream->File, "BX=Hollow "); break; case TextBox_Filled : fprintf(FileStream->File, "BX=Filled "); break; default :; } fprintf(FileStream->File, "BXM=%.4G ", Text->Box.Margin*100); fprintf(FileStream->File, "LT=%.4G ", Text->Box.LineThickness*100.0); fprintf(FileStream->File, "BXO="); WriteAsciiColor(FileStream->File, Text->Box.BColor); fprintf(FileStream->File, "BXF="); WriteAsciiColor(FileStream->File, Text->Box.FillBColor); fprintf(FileStream->File, "\nF="); switch (Text->TextShape.Font) { case Font_Helvetica : fprintf(FileStream->File, "HELV"); break; case Font_HelveticaBold : fprintf(FileStream->File, "HELV-BOLD"); break; case Font_Times : fprintf(FileStream->File, "TIMES"); break; case Font_TimesBold: fprintf(FileStream->File, "TIMES-BOLD"); break; case Font_TimesItalic : fprintf(FileStream->File, "TIMES-ITALIC"); break; case Font_TimesItalicBold : fprintf(FileStream->File, "TIMES-ITALIC-BOLD"); break; case Font_Courier : fprintf(FileStream->File, "COURIER"); break; case Font_CourierBold : fprintf(FileStream->File, "COURIER-BOLD"); break; case Font_Greek : fprintf(FileStream->File, "GREEK"); break; case Font_Math : fprintf(FileStream->File, "MATH"); break; case Font_UserDefined : fprintf(FileStream->File, "USER-DEF"); break; default: CHECK(FALSE); break; } if (Text->TextShape.SizeUnits == Units_Frame) ScaleFact = 100.0; else ScaleFact = 1.0; fprintf(FileStream->File, "\nH=%.12G A=%.12G", Text->TextShape.Height*ScaleFact, Text->Angle*DEGPERRADIANS); } if (!WriteBinary) fprintf(FileStream->File, "\nMFC="); DumpDatafileString(FileStream, Text->MacroFunctionCommand, WriteBinary); if (!WriteBinary) { if (Text->Clipping == Clipping_ClipToViewport) fprintf(FileStream->File, "CLIPPING=CLIPTOVIEWPORT\n"); else if (Text->Clipping == Clipping_ClipToFrame) fprintf(FileStream->File, "CLIPPING=CLIPTOFRAME\n"); else CHECK(FALSE); } else { WriteBinaryInt32(FileStream, (LgIndex_t)Text->Clipping); } if (!WriteBinary) fprintf(FileStream->File, "T="); return DumpDatafileString(FileStream, Text->Text, WriteBinary) == TRUE; } Boolean_t DumpCustomAxisLabels(FileStream_s *FileStream, Boolean_t WriteBinary, StringList_pa LabelBase) { Boolean_t IsOk = TRUE; LgIndex_t Index = 0; LgIndex_t Count = 0; REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File)); REQUIRE(VALID_BOOLEAN(WriteBinary)); REQUIRE(StringListValid(LabelBase)); Count = StringListCount(LabelBase); if (WriteBinary) { WriteBinaryReal(FileStream, CustomLabelMarker, FieldDataType_Float); WriteBinaryInt32(FileStream, Count); } else { fprintf(FileStream->File, " CUSTOMLABELS = \n"); } for (Index = 0, IsOk = TRUE; Index < Count && IsOk; Index++) { const char *CurLabel = StringListGetStringRef(LabelBase, Index); IsOk = DumpDatafileString(FileStream, CurLabel, WriteBinary); } ENSURE(VALID_BOOLEAN(IsOk)); return IsOk; } /** */ Boolean_t WriteBinaryMagic(FileStream_s *FileStream) { /* * Write an integer value of 1 to the file. This is used * by the reader to determine byte order of the file. */ return (WriteBinaryInt32(FileStream, 1)); } /** */ bool writeBinaryVersionNumber(FileStream_s& fileStream, int versionNumber) { char buffer[5]; sprintf(buffer, "V%-3d", versionNumber); CHECK(strlen(buffer) == 4); return fprintf(fileStream.File, "#!TD%s", buffer) > 0; } #if defined TECPLOTKERNEL /* CORE SOURCE CODE REMOVED */ #if !defined SUN #else #endif #if !defined NO_ASSERTS #endif #if defined ALLOW_USERDEF_NO_NEIGHBORING_ELEMENT #else #endif #if 0 /* not used yet */ #endif #if defined TECPLOTKERNEL #endif #if defined TECPLOTKERNEL #endif #endif