2101 lines
46 KiB
C
2101 lines
46 KiB
C
/*++
|
|
|
|
|
|
|
|
Copyright 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
vib.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the VIB (Variable Information Block) support
|
|
routines used by the watch and local windows.
|
|
|
|
Author:
|
|
|
|
William J. Heaton (v-willhe) 20-Jul-1992
|
|
Griffith Wm. Kadnier (v-griffk) 10-Mar-1993
|
|
|
|
Environment:
|
|
|
|
Win32, User Mode
|
|
|
|
--*/
|
|
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
typedef struct {
|
|
USHORT cb;
|
|
LPVOID lpv;
|
|
} MEMLINK, * PTRMEMLINK;
|
|
|
|
#define NAMES_BUFFER 2048
|
|
#define BUFFERMAX 1024
|
|
|
|
|
|
// Global Storage (PROGRAM)
|
|
|
|
|
|
extern CXF CxfIp;
|
|
|
|
|
|
// Global Storage (FILE)
|
|
|
|
|
|
|
|
static char szBuffer[BUFFERMAX+1];
|
|
|
|
|
|
// Prototypes (LOCAL)
|
|
|
|
|
|
PTRCIF PASCAL FTGetCif( VOID );
|
|
VOID PASCAL FTFreeVib( PTRVIB );
|
|
VOID PASCAL FTFreeVibChildren( PTRVIB );
|
|
VOID PASCAL FTFreeAllCif( PTRCIF );
|
|
LTS PASCAL FTExpandVib( PTRVIB pvib );
|
|
VOID PASCAL FTInvalidateVib( PTRVIB pvib);
|
|
VOID PASCAL FTResetVib( PTRVIB pvib);
|
|
BOOL PASCAL FTSetupWoj( PTRVIB pvib, PSTR pName, UINT cbSize);
|
|
|
|
|
|
/*** FTMakeWatchEntry
|
|
|
|
* Purpose: To make a watchentry
|
|
|
|
* Input:
|
|
* ppvib - A pointer to a vib pointer of where to place the new vib
|
|
* pvit - The vit tree that the watchentry is to be added to.
|
|
* szExpStr- A string containing the expression
|
|
|
|
* Output:
|
|
* Returns FALSE is ok, TRUE if errors
|
|
|
|
* Exceptions:
|
|
|
|
* Notes:
|
|
|
|
*/
|
|
int
|
|
FTMakeWatchEntry (
|
|
void *ppvibVoid,
|
|
void *pvit,
|
|
char *szExpStr
|
|
)
|
|
{
|
|
EESTATUS Err;
|
|
UINT cbszExpStr;
|
|
char * pch;
|
|
ULONG iLast;
|
|
|
|
PTRVIB * ppvib = (PTRVIB *) ppvibVoid;
|
|
|
|
// get a new vib
|
|
|
|
if( !(*ppvib = PvibAlloc ( NULL, (PTRVIB) pvit )) ) {
|
|
FTError ( OUTOFMEMORY );
|
|
return TRUE;
|
|
}
|
|
|
|
// take out leading and trailing spaces
|
|
|
|
while( *szExpStr == ' ' ) {
|
|
szExpStr++;
|
|
}
|
|
if ( !*szExpStr ) {
|
|
return TRUE;
|
|
}
|
|
pch = szExpStr + strlen(szExpStr);
|
|
while (pch > szExpStr) {
|
|
if (*(pch = CharPrev(szExpStr, pch)) != ' ') {
|
|
break;
|
|
}
|
|
}
|
|
pch += (IsDBCSLeadByte(*pch) ? 2 : 1);
|
|
strcpy(szBuffer,szExpStr);
|
|
|
|
// do a parse
|
|
if( (Err = EEParse(szBuffer, radix, fCaseSensitive, &(*ppvib)->hTMBd, &iLast)) ) {
|
|
// (*ppvib) = (PTRVIB)NULL;
|
|
// return(TRUE);
|
|
}
|
|
|
|
|
|
// Setup the Woj
|
|
|
|
cbszExpStr = (UINT) (pch - szExpStr);
|
|
if ( !FTSetupWoj( *ppvib, szExpStr, cbszExpStr) ) {
|
|
*ppvib = NULL;
|
|
FTError ( OUTOFMEMORY );
|
|
return TRUE;
|
|
}
|
|
|
|
(*ppvib)->vibPtr = vibWatch;
|
|
|
|
return FALSE;
|
|
} /* WTMakeWatchEntry() */
|
|
|
|
/*** FTSetupWoj
|
|
|
|
* Purpose: Add a Woj (Watch Object?) to a vib
|
|
|
|
* Input:
|
|
* pvib - Pointer to the vib
|
|
* pName - Pointer to the Name
|
|
* cbSize - Size of Name
|
|
|
|
* Output:
|
|
* TRUE/FALSE if memory alloc failed
|
|
|
|
* Exceptions:
|
|
|
|
* Notes:
|
|
|
|
*/
|
|
|
|
BOOL
|
|
FTSetupWoj(
|
|
PTRVIB pvib,
|
|
PSTR pName,
|
|
UINT cbSize
|
|
)
|
|
{
|
|
// If we already have one, lose it
|
|
|
|
if ( pvib->pwoj ) {
|
|
free( pvib->pwoj );
|
|
}
|
|
|
|
// Allocate the Woj
|
|
|
|
pvib->pwoj = (PTRWOJ) malloc( sizeof(WOJ) + cbSize + 1 );
|
|
if ( pvib->pwoj == NULL ) {
|
|
return(FALSE);
|
|
}
|
|
|
|
// copy over the string
|
|
|
|
strncpy ( pvib->pwoj->szExpStr, pName, cbSize);
|
|
pvib->pwoj->szExpStr[cbSize] = '\0';
|
|
|
|
// Fill out the other info
|
|
|
|
pvib->pwoj->iFormSpec = (WORD)cbSize;
|
|
pvib->pwoj->ErrNbr = 0;
|
|
pvib->pwoj->cbLen = (unsigned char)cbSize;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/*** FTVerify
|
|
|
|
* Purpose: To verify the watch tree
|
|
|
|
* Input:
|
|
* pcxf - A pointer to the current CXF
|
|
* pvib - A pointer to the vib to verify
|
|
|
|
* Output:
|
|
* Returns:
|
|
|
|
* Exceptions:
|
|
|
|
* Notes:
|
|
|
|
*/
|
|
|
|
|
|
BOOL
|
|
FTVerify (
|
|
PCXF pcxf,
|
|
PTRVIB pvib
|
|
)
|
|
{
|
|
EEPDTYP ExpTyp;
|
|
BOOL fBind = FALSE;
|
|
EEHSTR hTypeOld = NULL;
|
|
EEHSTR hTypeNew = NULL;
|
|
LPSTR lszTypeOld;
|
|
LPSTR lszTypeNew;
|
|
HTI hti;
|
|
RTMI rti = {0};
|
|
PTI pti;
|
|
BOOL fStatus = FALSE;
|
|
|
|
/*
|
|
* If we're in a function evaluation get out fast
|
|
*/
|
|
|
|
if ( (LptdCur != NULL) && (LptdCur->fInFuncEval)) {
|
|
return(fStatus);
|
|
}
|
|
|
|
/*
|
|
* only while the Variable Info Block is valid
|
|
*/
|
|
|
|
for (; pvib; pvib = pvib->pvibSib ) {
|
|
/*
|
|
* Don't rebind this items
|
|
*/
|
|
|
|
if (pvib->vibPtr == vibGeneric) {
|
|
continue;
|
|
}
|
|
|
|
/*
|
|
* rebind, the error will be displayed during evaluation
|
|
*/
|
|
|
|
if (EEGetTypeFromTM(&pvib->hTMBd, NULL, &hTypeOld, TRUE ) != EENOERROR) {
|
|
hTypeOld = NULL;
|
|
}
|
|
|
|
fBind = ((pvib->hprocCache != ( SHpCXTFrompCXF ( pcxf ) )->hProc) ||
|
|
(pvib->hblkCache != ( SHpCXTFrompCXF ( pcxf ) )->hBlk));
|
|
|
|
if ( fBind ) {
|
|
pvib->hprocCache = ( SHpCXTFrompCXF ( pcxf ) )->hProc;
|
|
pvib->hblkCache = ( SHpCXTFrompCXF ( pcxf ) )->hBlk;
|
|
fStatus = TRUE;
|
|
}
|
|
|
|
/*
|
|
* Make sure we can still Bind
|
|
*/
|
|
|
|
if ( pvib->hTMBd &&
|
|
EEBindTM(&pvib->hTMBd, SHpCXTFrompCXF(pcxf),fBind,FALSE) == EENOERROR ) {
|
|
|
|
/*
|
|
* Reset the NoBind Flag because it back in context
|
|
*/
|
|
|
|
FTResetVib(pvib);
|
|
|
|
/*
|
|
* Make sure the Function Evaluation gets updated
|
|
*/
|
|
|
|
if (EEInfoFromTM ( &pvib->hTMBd, &rti, &hti ) == EENOERROR) {
|
|
DAssert(hti != (HTI)NULL);
|
|
pti = (PTI) MMLpvLockMb (hti);
|
|
if (pti->fFunction) {
|
|
pvib->flags.FuncEval = 1;
|
|
}
|
|
if ( pti != NULL ) {
|
|
MMbUnlockMb ( hti );
|
|
}
|
|
}
|
|
|
|
if (hti != (HTI) NULL) {
|
|
EEFreeTI(&hti);
|
|
}
|
|
|
|
/*
|
|
* Has the Type changed for a Watch or a Type
|
|
*/
|
|
|
|
if ((pvib->vibPtr == vibWatch) || (pvib->vibPtr == vibType)) {
|
|
lszTypeOld = NULL;
|
|
lszTypeNew = NULL;
|
|
if (hTypeOld) {
|
|
if (EEGetTypeFromTM(&pvib->hTMBd, NULL, &hTypeNew, TRUE ) != EENOERROR) {
|
|
hTypeNew = NULL;
|
|
} else {
|
|
lszTypeOld = (PSTR) MMLpvLockMb( hTypeOld );
|
|
lszTypeNew = (PSTR) MMLpvLockMb( hTypeNew );
|
|
}
|
|
}
|
|
if (!lszTypeNew || strcmp(lszTypeOld, lszTypeNew)) {
|
|
/*
|
|
* remove the rest of the tree
|
|
*/
|
|
|
|
FTFreeAllCif(pvib->pcif);
|
|
pvib->pcif = NULL;
|
|
FTclnUpdateParent ( pvib, (1-pvib->cln) );
|
|
fStatus = TRUE;
|
|
|
|
/*
|
|
* Make sure VibPtr is reset
|
|
*/
|
|
|
|
if ( pvib->vibPtr == vibWatch || pvib->vibPtr == vibType ) {
|
|
ExpTyp = EEIsExpandable(&pvib->hTMBd);
|
|
if ( ExpTyp == EETYPE || ExpTyp == EETYPENOTEXP ) {
|
|
pvib->vibPtr = vibType;
|
|
} else {
|
|
pvib->vibPtr = vibWatch;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (lszTypeNew) {
|
|
MMbUnlockMb( hTypeOld );
|
|
MMbUnlockMb( hTypeNew );
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* Update any children
|
|
*/
|
|
|
|
if (pvib->pcif) {
|
|
if ( pvib->pcif->hTMBd ) {
|
|
EEBindTM( &pvib->pcif->hTMBd, SHpCXTFrompCXF(pcxf),
|
|
fBind, FALSE);
|
|
}
|
|
|
|
/*
|
|
* If a child had a signicant change, so did we
|
|
*/
|
|
|
|
if ( FTVerify ( pcxf, pvib->pcif->pvibChild ) ) {
|
|
fStatus = TRUE;
|
|
}
|
|
}
|
|
} else {
|
|
|
|
/*
|
|
* Couldn't Bind, Invalidate any children
|
|
*/
|
|
|
|
if ( pvib->pcif ) {
|
|
FTInvalidateVib(pvib->pcif->pvibChild);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hTypeOld) {
|
|
EEFreeStr(hTypeOld);
|
|
}
|
|
if (hTypeNew) {
|
|
EEFreeStr(hTypeNew);
|
|
}
|
|
|
|
return(fStatus);
|
|
} /* FTVerify() */
|
|
|
|
/*** FTVerifyNew
|
|
|
|
* Purpose: Determine if a vib's result have changed since
|
|
* the last time a user saw it
|
|
|
|
* Input:
|
|
* pvit - A pointer to the vit
|
|
* oln - Item number of interest
|
|
|
|
* Output:
|
|
* Returns:
|
|
* TRUE/FALSE the item has changed
|
|
|
|
* Exceptions:
|
|
|
|
* Notes:
|
|
|
|
*/
|
|
|
|
|
|
BOOL
|
|
FTVerifyNew(
|
|
PTRVIT pVit,
|
|
ULONG oln
|
|
)
|
|
{
|
|
PTRVIB pVib = FTvibGetAtLine( pVit, oln);
|
|
VPI i;
|
|
|
|
// No Vib, No change
|
|
if ( pVib == 0) {
|
|
return(FALSE);
|
|
}
|
|
i = pVib->vibIndex;
|
|
|
|
// Give EE a chance to fill out the result
|
|
FTEnsureTextExists( pVib );
|
|
FTGetPanelString( pVit, pVib, ID_PANE_RIGHT);
|
|
|
|
// Do we have a string at all?
|
|
if ( pVib->pvtext[i].pszValueP || pVib->pvtext[i].pszValueC) {
|
|
|
|
// Do we have both strings?
|
|
if ( pVib->pvtext[i].pszValueP && pVib->pvtext[i].pszValueC ) {
|
|
if ((!_strcmpi(pVib->pvtext[i].pszValueC,pVib->pvtext[i].pszValueP)) &&
|
|
(pVib->pvtext[i].fChanged == FALSE))
|
|
{
|
|
return(FALSE);
|
|
} else
|
|
if ((!_strcmpi(pVib->pvtext[i].pszValueC,pVib->pvtext[i].pszValueP)) &&
|
|
(pVib->pvtext[i].fChanged == TRUE))
|
|
{
|
|
pVib->pvtext[i].fChanged = FALSE;
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
// Nope, It changed
|
|
pVib->pvtext[i].fChanged = TRUE;
|
|
return(TRUE);
|
|
}
|
|
|
|
// Nope, No change
|
|
return(FALSE);
|
|
|
|
} /* FTVerifyNew() */
|
|
|
|
|
|
/*** FTvibGetAtLine Get the vib starting at the line specified.
|
|
|
|
* Purpose: Given a vit, and a line, return the vib packet discribing that line.
|
|
|
|
* Input:
|
|
* pvit - A valid Variable Info block Top describing a Variable Info
|
|
* Block list
|
|
* oln - The line of interest
|
|
|
|
* Output:
|
|
* Returns
|
|
* pvib - A pointer to a vib that describes the requested line
|
|
|
|
* Exceptions:
|
|
|
|
* Notes: Make sure the Variable Info block Top list is valid!
|
|
|
|
*/
|
|
|
|
|
|
PTRVIB
|
|
FTvibGetAtLine(
|
|
PTRVIT pvit,
|
|
ULONG oln
|
|
)
|
|
{
|
|
ULONG olnCur = 0;
|
|
VPI vpiT = 0;
|
|
PTRVIB pvib;
|
|
ULONG strIndex;
|
|
HTI hti;
|
|
RTMI rti = {0};
|
|
PTI pti;
|
|
|
|
if ( pvit ) {
|
|
pvib = pvit->pvibChild;
|
|
} else {
|
|
return(NULL);
|
|
}
|
|
|
|
/*
|
|
* Loop through the vib tree looking for the correct vib. Do this
|
|
* by adding the count of lines in a pvib structure until we get
|
|
* to the correct vib.
|
|
*/
|
|
|
|
while( pvib && olnCur != oln ) {
|
|
|
|
/*
|
|
* Is the line number we are looking for in the current vib?
|
|
|
|
* YES -- move to the child of this vib (expanded item)
|
|
* NO -- skip to the next vib in this list
|
|
*/
|
|
|
|
if( oln < olnCur + (WORD)pvib->cln ) {
|
|
olnCur++;
|
|
vpiT = 0;
|
|
pvib = pvib->pcif->pvibChild; // go into the expanded item.
|
|
}
|
|
|
|
else { // skip this vib, go on to the next
|
|
olnCur += pvib->cln;
|
|
pvib = pvib->pvibSib;
|
|
}
|
|
|
|
if ( pvib == NULL ) {
|
|
break;
|
|
}
|
|
|
|
|
|
/*
|
|
* Move to the i-th element of the current vib, where i is the
|
|
* distance between the first line in the vib and the
|
|
* actual line desired.
|
|
|
|
* If the current vib is a vibGeneric then we need to get the
|
|
* i-th element in this vib.
|
|
* If the current vib is a vibChild -????
|
|
* ELSE -- no action needs to be taken -- use the current vib
|
|
* since it is a one line item.
|
|
*/
|
|
|
|
if ( pvib->vibPtr == vibGeneric || pvib->vibPtr == vibChild ) {
|
|
HTM hTM;
|
|
|
|
if ((!pvib->pvibSib) ||
|
|
(oln < olnCur + pvib->vibIndex - vpiT) ) {
|
|
|
|
EESTATUS Err;
|
|
|
|
/*
|
|
* search for the generic vib
|
|
*/
|
|
|
|
while( pvib->pvibSib ) {
|
|
pvib = pvib->pvibSib;
|
|
}
|
|
|
|
/*
|
|
* OK -- now if we have some data for this item then we
|
|
* can get information about it.
|
|
*/
|
|
|
|
DAssert(pvib->hTMBd == 0);
|
|
|
|
if ( !pvib->flags.NoData ) {
|
|
|
|
// get the index and TM
|
|
pvib->vibIndex = (unsigned short) (vpiT + oln - olnCur);
|
|
|
|
/*
|
|
* Make sure the structure we are about to index into
|
|
* already exitsts.
|
|
*/
|
|
|
|
FTEnsureTextExists( pvib );
|
|
|
|
/*
|
|
* Now see if we have already created a TM for this, if
|
|
* so then we can just use it.
|
|
*/
|
|
|
|
if (pvib->pvtext[pvib->vibIndex].htm) {
|
|
;
|
|
} else {
|
|
/*
|
|
* get the TM to expand.
|
|
*/
|
|
|
|
if( pvib->pvibParent->pcif->hTMBd ) {
|
|
hTM = pvib->pvibParent->pcif->hTMBd;
|
|
} else {
|
|
hTM = pvib->pvibParent->hTMBd;
|
|
}
|
|
|
|
Err = EEGetChildTM ( &hTM, pvib->vibIndex,
|
|
&pvib->pvtext[pvib->vibIndex].htm,
|
|
&strIndex, fCaseSensitive, radix );
|
|
|
|
if (Err) {
|
|
CVExprErr ( Err, MSGGERRSTR, &hTM, NULL);
|
|
pvib->flags.NoBind;
|
|
} else {
|
|
if (!EEInfoFromTM(&pvib->pvtext[pvib->vibIndex].htm,
|
|
&rti, &hti)) {
|
|
DAssert(hti != (HTI) NULL);
|
|
pti = (PTI) MMLpvLockMb( hti );
|
|
if (pti != NULL) {
|
|
if (pti->fFunction) {
|
|
pvib->flags.FuncEval = 1;
|
|
}
|
|
MMbUnlockMb( hti );
|
|
}
|
|
}
|
|
if (hti != (HTI) NULL) {
|
|
EEFreeTI(&hti);
|
|
}
|
|
}
|
|
|
|
}
|
|
olnCur = oln;
|
|
}
|
|
}
|
|
else {
|
|
// check out this Variable Info Block, it cannot be
|
|
// the generic Variable Info Block!
|
|
// we must advance by the preceeding blank space
|
|
|
|
olnCur += pvib->vibIndex - vpiT;
|
|
vpiT = pvib->vibIndex + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return( pvib );
|
|
} /* FTvibGetAtLine() */
|
|
|
|
|
|
/*** PvibAlloc
|
|
|
|
* Purpose: To get a new Variable Info Block. If the list has a Variable
|
|
* Info Block after it, choose that as the next Variable Info Block,
|
|
* but don't alter the current Variable Info Block. If a new Variable
|
|
* Info Block must be allocated, all fields are initialized. This
|
|
* does not update anything in the parent!
|
|
|
|
* Input:
|
|
* pvib - A pointer to the potential next vib. This may be NULL;
|
|
* pvibParent - A pointer to the parent vib, This may not be NULL;
|
|
|
|
* Output:
|
|
|
|
* Returns
|
|
* A pointer to the next vib. The new vib will be unchanged if it
|
|
* already existed, otherwise it will be initialized.
|
|
|
|
* Exceptions:
|
|
|
|
* Notes:
|
|
|
|
*/
|
|
|
|
|
|
PTRVIB
|
|
PvibAlloc (
|
|
PTRVIB pvib,
|
|
PTRVIB pvibParent
|
|
)
|
|
{
|
|
if ( !pvib ) {
|
|
pvib = (PTRVIB) malloc( sizeof(VIB) );
|
|
|
|
if ( !( pvib ) ) {
|
|
return ( NULL );
|
|
}
|
|
|
|
memset ( pvib, 0, sizeof( VIB ) );
|
|
pvib->cln = 1;
|
|
pvib->pvibParent = pvibParent;
|
|
pvib->vibPtr = vibUndefined;
|
|
|
|
// if the parent has a parent, then it must not be a Variable
|
|
// Info block Top, get one more than the parents level
|
|
|
|
if ( pvibParent->pvibParent ) {
|
|
pvib->level = (unsigned char) (pvibParent->level + 1);
|
|
}
|
|
else {
|
|
pvib->level = 0;
|
|
}
|
|
}
|
|
|
|
return ( pvib );
|
|
} /* PvibAlloc() */
|
|
|
|
|
|
/*** FTvibGet
|
|
|
|
* Purpose: To get a new Variable Info Block. If the list has a Variable
|
|
* Info Block after it, choose that as the next Variable Info Block,
|
|
* but don't alter the current Variable Info Block. If a new Variable
|
|
* Info Block must be allocated, all fields are initialized. This
|
|
* does not update anything in the parent!
|
|
|
|
* Input:
|
|
* pvib - A pointer to the potential next vib. This may be NULL;
|
|
* pvibParent - A pointer to the parent vib, This may not be NULL;
|
|
|
|
* Output:
|
|
|
|
* Returns
|
|
* A pointer to the next vib. The new vib will be unchanged if it
|
|
* already existed, otherwise it will be initialized.
|
|
|
|
* Exceptions:
|
|
|
|
* Notes:
|
|
|
|
*/
|
|
|
|
|
|
PTRVIB
|
|
FTvibGet (
|
|
PTRVIB pvib,
|
|
PTRVIB pvibParent
|
|
)
|
|
{
|
|
if ( !pvib ) {
|
|
pvib = (PTRVIB) malloc( sizeof(VIB) );
|
|
if ( !( pvib ) ) {
|
|
return ( NULL );
|
|
}
|
|
|
|
memset ( pvib, 0, sizeof( VIB ) );
|
|
pvib->cln = 1;
|
|
pvib->pvibParent = pvibParent;
|
|
pvib->vibPtr = vibUndefined;
|
|
|
|
// if the parent has a parent, then it must not be a Variable
|
|
// Info block Top, get one more than the parents level
|
|
|
|
if ( pvibParent->pvibParent ) {
|
|
pvib->level = (unsigned char) (pvibParent->level + 1);
|
|
}
|
|
else {
|
|
pvib->level = 0;
|
|
}
|
|
}
|
|
|
|
return ( pvib );
|
|
}
|
|
|
|
|
|
|
|
|
|
/*** FTvibInit
|
|
|
|
* Purpose: To clear out an existing Variable Info Block, freeing all of
|
|
* its children and sibilings.
|
|
|
|
* Input:
|
|
* pvib - A pointer to the vib to be initialized
|
|
* pvibParent - A pointer to the parent, this may not be NULL
|
|
|
|
* Output:
|
|
* Returns pvib
|
|
|
|
* Exceptions:
|
|
|
|
* Notes:
|
|
|
|
*/
|
|
|
|
|
|
PTRVIB
|
|
FTvibInit(
|
|
PTRVIB pvib,
|
|
PTRVIB pvibParent
|
|
)
|
|
{
|
|
|
|
// Free all of the children. Don't use FTFreeVibChildren() because it may
|
|
// merge this vibif it is an array
|
|
|
|
FTFreeAllCif ( pvib->pcif );
|
|
|
|
// free all remaining sibiling
|
|
FTFreeAllSib ( pvib->pvibSib );
|
|
pvib->pvibSib = (PTRVIB) NULL;
|
|
|
|
// reinitialize the packet
|
|
if ( pvib->vibPtr != vibGeneric && pvib->vibPtr != vibUndefined && pvib->hTMBd ) {
|
|
EEFreeTM (&pvib->hTMBd);
|
|
}
|
|
|
|
if ( pvib->pwoj ) {
|
|
free( pvib->pwoj );
|
|
pvib->pwoj = (PTRWOJ)NULL;
|
|
}
|
|
|
|
memset ( pvib, 0, sizeof( VIB ) );
|
|
pvib->cln = 1;
|
|
pvib->pvibParent = pvibParent;
|
|
pvib->vibPtr = vibUndefined;
|
|
|
|
// if the parent has a parent, then it must not be a Variable Info
|
|
// block Top, get one more than the parent's level
|
|
|
|
if( pvibParent->pvibParent ) {
|
|
pvib->level = (unsigned char) (pvibParent->level + 1);
|
|
} else {
|
|
pvib->level = 0;
|
|
}
|
|
|
|
return(pvib);
|
|
|
|
} /* FTvibInit() */
|
|
|
|
|
|
|
|
/*** FTGetCif
|
|
|
|
* Purpose: To allocate a full Child InFo packet.
|
|
|
|
* Input: NONE
|
|
|
|
* Output:
|
|
* Returns A pointer to a new Child InFo packet.
|
|
|
|
* Exceptions:
|
|
|
|
* Notes:
|
|
|
|
*/
|
|
|
|
PTRCIF
|
|
FTGetCif(
|
|
void
|
|
)
|
|
{
|
|
PTRCIF pcif;
|
|
|
|
if ( (pcif = (PTRCIF) malloc( sizeof(CIF) )) ) {
|
|
memset(pcif, 0, sizeof(CIF));
|
|
}
|
|
|
|
return ( pcif );
|
|
|
|
} /* FTGetCif() */
|
|
|
|
|
|
/*** FTFreeVib
|
|
|
|
* Purpose: To free a Variable Info Block and all of its associated memory
|
|
|
|
* Input:
|
|
* pvib - A pointer to the Variable Info Block that is to be freed
|
|
|
|
* Output:
|
|
* Returns .....
|
|
|
|
* Exceptions:
|
|
|
|
* Notes:
|
|
|
|
*/
|
|
|
|
VOID
|
|
FTFreeVib (
|
|
PTRVIB pvib
|
|
)
|
|
{
|
|
ULONG i;
|
|
if ( pvib ) {
|
|
|
|
// free the TM if it is appropriate
|
|
|
|
// For child TMS -- this is a copy of the item in the vibGeneric
|
|
|
|
|
|
if ( pvib->vibPtr == vibChild) {
|
|
pvib->hTMBd = 0;
|
|
}
|
|
if ( pvib->vibPtr != vibUndefined && pvib->hTMBd ) {
|
|
EEFreeTM ( &pvib->hTMBd );
|
|
}
|
|
|
|
// Free the watch information
|
|
if ( pvib->pwoj )
|
|
free(pvib->pwoj );
|
|
|
|
// free any text strings
|
|
if ( pvib->cText ) {
|
|
for (i=0; i<pvib->cText ; i++ ) {
|
|
|
|
if ( pvib->pvtext[i].pszValueC)
|
|
free(pvib->pvtext[i].pszValueC);
|
|
|
|
if ( pvib->pvtext[i].pszValueP)
|
|
free(pvib->pvtext[i].pszValueP);
|
|
|
|
if ( pvib->pvtext[i].pszFormat)
|
|
free(pvib->pvtext[i].pszFormat);
|
|
|
|
if ( pvib->pvtext[i].htm) {
|
|
EEFreeTM(&pvib->pvtext[i].htm);
|
|
}
|
|
}
|
|
free(pvib->pvtext);
|
|
}
|
|
|
|
|
|
// now free the Variable Info Block itself
|
|
|
|
free(pvib);
|
|
}
|
|
return;
|
|
} /* FTFreeVib() */
|
|
|
|
|
|
/*** FTFreeVibChildren
|
|
|
|
* Purpose: Given a Variable Info Block, clear out all child structures.
|
|
* The pcif (Pointer to Child Info) field will be NULL on return.
|
|
|
|
* Input:
|
|
* pvib - A pointer to the Variable Info Block that is to be cleared
|
|
|
|
* Output:
|
|
* Returns .....
|
|
|
|
* Exceptions:
|
|
|
|
* Notes: If the vib is of type vibArray, the vib itself may be merged in
|
|
* with the genaric array vib.
|
|
|
|
*/
|
|
|
|
|
|
VOID
|
|
FTFreeVibChildren (
|
|
PTRVIB pvib
|
|
)
|
|
{
|
|
PTRVIB pvibCur;
|
|
VIB vibT;
|
|
|
|
// free all of its Child InFo packets
|
|
|
|
FTFreeAllCif ( pvib->pcif );
|
|
pvib->pcif = NULL;
|
|
|
|
// if the Variable Info Block is expanded, merge it back into the
|
|
// the generic element by eliminating it from the child list
|
|
if( pvib->vibPtr != vibChild ) return;
|
|
|
|
// search the list
|
|
pvibCur = &vibT;
|
|
|
|
// This should never be at level 0 of the chain,
|
|
// the parent should never be a Variable Info block Top
|
|
|
|
pvibCur->pvibSib = pvib->pvibParent->pcif->pvibChild;
|
|
while( pvibCur->pvibSib != pvib ) pvibCur = pvibCur->pvibSib;
|
|
|
|
pvibCur->pvibSib = pvib->pvibSib;
|
|
pvib->pvibParent->pcif->pvibChild = vibT.pvibSib;
|
|
|
|
// Don't free the hTM since it is a copy of the one being saved in
|
|
// the generic structure rather than a duplicate handle.
|
|
|
|
pvib->hTMBd = 0;
|
|
// if ( pvib->hTMBd ) {
|
|
// EEFreeTM ( &pvib->hTMBd );
|
|
// }
|
|
|
|
FTFreeVib ( pvib );
|
|
return;
|
|
} /* FTFreeVibChildren() */
|
|
|
|
/*** FTFreeAllSib
|
|
|
|
* Purpose: Starting at the point specifed in the tree, all following children
|
|
* and sibilings are freed. The Variable Info Block specified is also freed.
|
|
|
|
* Input:
|
|
* pvib - The first Variable Info Block in the list to be freed.
|
|
|
|
* Output:
|
|
* Returns .....
|
|
|
|
* Exceptions:
|
|
|
|
* Notes:
|
|
|
|
*/
|
|
|
|
|
|
void
|
|
FTFreeAllSib(
|
|
PTRVIB pvib
|
|
)
|
|
{
|
|
while ( pvib ) {
|
|
if( pvib->pcif ) {
|
|
FTFreeAllCif( pvib->pcif );
|
|
}
|
|
|
|
|
|
if( pvib->pvibSib ) {
|
|
pvib->pvibSib->pvibParent = pvib;
|
|
pvib = pvib->pvibSib;
|
|
FTFreeVib ( pvib->pvibParent );
|
|
} else {
|
|
FTFreeVib( pvib ); // free the last vib and get out
|
|
break;
|
|
}
|
|
}
|
|
return;
|
|
} /* FTFreeAllSib() */
|
|
|
|
/*** FTFreeAllCif
|
|
|
|
* Purpose: To free all children blocks and the Child InFo.
|
|
|
|
* Input:
|
|
* pcif A pointer to the Child InFo.
|
|
|
|
* Output:
|
|
* Returns .....
|
|
|
|
* Exceptions:
|
|
|
|
* Notes:
|
|
|
|
*/
|
|
|
|
VOID
|
|
FTFreeAllCif(
|
|
PTRCIF pcif
|
|
)
|
|
{
|
|
if( pcif ) {
|
|
FTFreeAllSib ( pcif->pvibChild );
|
|
pcif->pvibChild = (PTRVIB) NULL;
|
|
|
|
if ( pcif->hTMBd ) {
|
|
EEFreeTM ( &pcif->hTMBd );
|
|
}
|
|
|
|
free ( pcif );
|
|
}
|
|
return;
|
|
} /* FTFreeAllCif() */
|
|
|
|
|
|
/*** FTExpandOne(PTRVIB pvib)
|
|
|
|
* Purpose:
|
|
* Expand all vibs at this level in the tree (All siblings)
|
|
|
|
|
|
* Input:
|
|
* pVib - Pointer to a VIB
|
|
|
|
* Output:
|
|
* None
|
|
|
|
* Exceptions:
|
|
|
|
* Notes:
|
|
|
|
*/
|
|
|
|
|
|
VOID
|
|
FTExpandOne(
|
|
PTRVIB pvib
|
|
)
|
|
{
|
|
while ( pvib) {
|
|
|
|
// Don't Collapse if it's already open!
|
|
if ( !pvib->pcif && pvib->flags.ExpandMe ) {
|
|
FTExpandVib(pvib);
|
|
}
|
|
|
|
// Now take care of the siblings
|
|
pvib = pvib->pvibSib;
|
|
}
|
|
}
|
|
|
|
|
|
/*** FTExpand
|
|
|
|
* Purpose: To expand the structure at the line pointed to by oln. oln is
|
|
* the offset from the start of the locals, not the start of the
|
|
* window.
|
|
|
|
* Input:
|
|
* pvit - A Pointer to the Variable Information Top
|
|
* oln - The offset from the first local
|
|
|
|
* Output:
|
|
* Returns a LTS
|
|
|
|
* Exceptions:
|
|
|
|
|
|
*/
|
|
|
|
|
|
LTS
|
|
FTExpand (
|
|
PTRVIT pvit,
|
|
ULONG oln
|
|
)
|
|
{
|
|
PTRVIB pvib;
|
|
|
|
if ( pvit && (pvib = FTvibGetAtLine( pvit, oln)) ) {
|
|
return( FTExpandVib(pvib) );
|
|
}
|
|
|
|
return(UNABLETOEXPAND);
|
|
}
|
|
|
|
|
|
/*** FTExpand
|
|
|
|
* Purpose: To expand the structure at a particular vib.
|
|
|
|
* Input:
|
|
* PTR pvib - Pointer to a VIB
|
|
|
|
* Output:
|
|
* Returns a LTS
|
|
|
|
* Exceptions:
|
|
|
|
|
|
*/
|
|
|
|
LTS
|
|
FTExpandVib(
|
|
PTRVIB pvib
|
|
)
|
|
{
|
|
EESTATUS Err;
|
|
HTM hTM;
|
|
long cChild;
|
|
EEPDTYP ExpTyp;
|
|
SHFLAG shflag;
|
|
ULONG strIndex;
|
|
HTI hti;
|
|
RTMI rti = {0};
|
|
HTM hTMParent;
|
|
|
|
|
|
// If its already expand, collasse it
|
|
|
|
|
|
if ( pvib->pcif ) {
|
|
FTclnUpdateParent ( pvib, (1-pvib->cln) );
|
|
FTFreeVibChildren ( pvib );
|
|
return OK;
|
|
}
|
|
|
|
|
|
// Can we Expand?
|
|
|
|
|
|
if ( pvib->flags.NoData || pvib->flags.NoBind ) {
|
|
return(UNABLETOEXPAND);
|
|
}
|
|
|
|
if (pvib->vibPtr == vibGeneric) {
|
|
hTMParent = pvib->pvtext[pvib->vibIndex].htm;
|
|
} else {
|
|
hTMParent = pvib->hTMBd;
|
|
}
|
|
|
|
if ( EEInfoFromTM ( &hTMParent, &rti, &hti ) != EENOERROR) {
|
|
return(UNABLETOEXPAND);
|
|
}
|
|
|
|
if (hti != (HTI) 0) {
|
|
EEFreeTI(&hti);
|
|
}
|
|
ExpTyp = EEIsExpandable ( &hTMParent );
|
|
if ( ExpTyp == EENOTEXP || ExpTyp == EETYPENOTEXP ) {
|
|
return ( UNABLETOEXPAND );
|
|
}
|
|
|
|
// here is the nasty, if we are currently an expandable, we don't
|
|
// want to update the generic vib, but rather make a new one
|
|
|
|
if( pvib->vibPtr == vibGeneric ) {
|
|
PTRVIB *ppvib;
|
|
PTRVIB pvibNew;
|
|
|
|
// get a new vib
|
|
if ( !(pvibNew = PvibAlloc ( NULL, pvib->pvibParent )) ) return ( OUTOFMEMORY );
|
|
|
|
// copy the generic vib
|
|
*pvibNew = *pvib;
|
|
pvibNew->cln = 1; // put in the count
|
|
|
|
// Copy over the correct hTM
|
|
|
|
pvibNew->hTMBd = pvib->pvtext[pvib->vibIndex].htm;
|
|
|
|
// put this vib in the list, this should alway be at least two down
|
|
// from the root vit. A sym must be in between
|
|
|
|
ppvib = &pvib->pvibParent->pcif->pvibChild;
|
|
pvib = *ppvib;
|
|
while ( pvib->pvibSib && pvib->vibIndex < pvibNew->vibIndex ) {
|
|
ppvib = &pvib->pvibSib;
|
|
pvib = pvib->pvibSib;
|
|
}
|
|
|
|
// fixup the link list
|
|
*ppvib = pvibNew;
|
|
pvibNew->pvibSib = pvib;
|
|
|
|
// now select this vib
|
|
pvib = pvibNew;
|
|
pvib->vibPtr = vibChild;
|
|
pvib->pvtext = NULL; // Make sure that Text Info isn't dup'd
|
|
pvib->cText = 0; // because of the copy above.
|
|
}
|
|
|
|
// now expand it
|
|
if( !(pvib->pcif = FTGetCif()) || !(pvib->pcif->pvibChild = PvibAlloc ( NULL, pvib )) ) {
|
|
FTFreeVibChildren( pvib );
|
|
return ( UNABLETOEXPAND );
|
|
}
|
|
|
|
// if it is a pointer and I can't dereference, get out
|
|
|
|
hTM = hTMParent;
|
|
if( ExpTyp == EEPOINTER &&
|
|
EEDereferenceTM ( &hTMParent, &hTM, &strIndex, fCaseSensitive ) != EENOERROR ) {
|
|
|
|
FTFreeVibChildren( pvib );
|
|
return ( UNABLETOEXPAND );
|
|
}
|
|
|
|
// get the count
|
|
Err = EEcChildrenTM ( &hTM, &cChild, &shflag );
|
|
|
|
// set up the new Variable Info Block after expansion
|
|
switch(ExpTyp) {
|
|
|
|
case EEAGGREGATE:
|
|
if ( !cChild ) {
|
|
pvib->pcif->pvibChild->flags.NoData;
|
|
cChild = 1;
|
|
}
|
|
// FALL THROUGH
|
|
|
|
case EETYPE:
|
|
pvib->pcif->pvibChild->vibPtr = vibGeneric;
|
|
break;
|
|
|
|
case EEPOINTER:
|
|
if( cChild ) {
|
|
pvib->pcif->pvibChild->vibPtr = vibGeneric;
|
|
pvib->pcif->hTMBd = hTM;
|
|
} else {
|
|
pvib->pcif->pvibChild->vibPtr = vibPointer;
|
|
pvib->pcif->pvibChild->hTMBd = hTM;
|
|
cChild = 1;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// say we are expanded, and put the expand count in the tree.
|
|
FTclnUpdateParent( pvib, (short) cChild );
|
|
pvib->flags.ExpandMe = FALSE;
|
|
return(OK);
|
|
} /* FTExpand() */
|
|
|
|
|
|
/*** FTclnUpdateParent
|
|
|
|
* Purpose: To Go up the tree and update all of the parent's cln fields
|
|
|
|
* Input:
|
|
* pvibParent - The first parent to update
|
|
* dcln - The difference to update them by
|
|
|
|
* Output:
|
|
|
|
* Exceptions:
|
|
|
|
* Notes:
|
|
|
|
*/
|
|
void
|
|
FTclnUpdateParent(
|
|
PTRVIB pvibParent,
|
|
int dcln
|
|
)
|
|
{
|
|
while ( pvibParent ) { // Walk up the tree
|
|
pvibParent->cln += (short) dcln;
|
|
pvibParent = pvibParent->pvibParent;
|
|
}
|
|
} /* FTclnUpdateParent() */
|
|
|
|
|
|
/*** FTGetVibTypeString
|
|
|
|
* Purpose:
|
|
* Get a pointer to a vib return a string that contains the
|
|
* text for its expansion button.
|
|
|
|
* Input:
|
|
* pVib - Pointer to the Vib
|
|
|
|
* Output:
|
|
* Returns a pointer to the String o rNULL
|
|
|
|
* Exceptions:
|
|
|
|
|
|
*/
|
|
|
|
PSTR
|
|
FTGetVibTypeString(
|
|
PTRVIB pVib
|
|
)
|
|
{
|
|
EEPDTYP ExpTyp;
|
|
|
|
// If we don't have any data, return a space
|
|
|
|
if ( pVib->flags.NoData || pVib->flags.NoBind ) {
|
|
return( " " );
|
|
}
|
|
|
|
/*
|
|
* If EE says we can't expand, return a space
|
|
*/
|
|
|
|
if (pVib->vibPtr == vibGeneric) {
|
|
ExpTyp = EEIsExpandable( &pVib->pvtext[pVib->vibIndex].htm );
|
|
} else {
|
|
ExpTyp = EEIsExpandable ( &pVib->hTMBd );
|
|
}
|
|
|
|
if ( (ExpTyp == EENOTEXP) || (ExpTyp == EETYPENOTEXP)) {
|
|
return( " " );
|
|
|
|
// If we have a child info block, we're already expanded
|
|
|
|
} else if ( pVib->pcif ) {
|
|
return( "-" );
|
|
}
|
|
|
|
// Else we are expandable
|
|
return( "+" );
|
|
} /* FTGetVibTypeString() */
|
|
|
|
|
|
|
|
/*** FTGetVibResultString
|
|
|
|
* Purpose:
|
|
* Get a pointer to a vib return a string that contains the
|
|
* text for the evaluated result.
|
|
|
|
* Input:
|
|
* pVit - Pointer to the VIT (Variable Information Top)
|
|
* pVib - Pointer to the VIB (Variable Information Block)
|
|
|
|
* Output:
|
|
* Returns a pointer to the String o rNULL
|
|
|
|
* Exceptions:
|
|
|
|
|
|
*/
|
|
|
|
PSTR
|
|
FTGetVibResultString(
|
|
PTRVIT pVit,
|
|
PTRVIB pVib
|
|
)
|
|
{
|
|
EEHSTR hValue = 0;
|
|
PCXF pCxf;
|
|
PSTR szValue;
|
|
EESTATUS Err;
|
|
PSTR pszFormat = NULL;
|
|
PVTEXT pvtext;
|
|
HTM hTM;
|
|
|
|
|
|
pCxf = (pVib->vibPtr == vibWatch) ? &CxfIp : &pVit->cxf;
|
|
|
|
if ( pVib->flags.NoBind) {
|
|
szBuffer[0] = 0;
|
|
return(szBuffer);
|
|
}
|
|
|
|
if (pVib->vibPtr == vibGeneric) {
|
|
hTM = pVib->pvtext[pVib->vibIndex].htm;
|
|
} else {
|
|
hTM = pVib->hTMBd;
|
|
}
|
|
|
|
if ( pVib->flags.NoData ) {
|
|
LoadString(g_hInst, ERR_Expclass_No_Members, szBuffer, BUFFERMAX);
|
|
return(szBuffer);
|
|
}
|
|
|
|
if ( pVib->flags.FuncEval) {
|
|
LoadString(g_hInst, ERR_No_Funcs_In_Watch, szBuffer, BUFFERMAX);
|
|
return(szBuffer);
|
|
}
|
|
|
|
// If we have a format override, make sure it passed
|
|
if ( pVib->pvtext) {
|
|
pvtext = &pVib->pvtext[pVib->vibIndex];
|
|
if ( pvtext->pszFormat ) {
|
|
pszFormat = pvtext->pszFormat;
|
|
}
|
|
}
|
|
|
|
if (pszFormat && *pszFormat == ',') {
|
|
pszFormat++;
|
|
}
|
|
if ( (Err = EEvaluateTM ( &hTM, SHhFrameFrompCXF(pCxf),EEVERTICAL )) ||
|
|
(Err = EEGetValueFromTM ( &hTM, radix, (PUCHAR) pszFormat, &hValue)) ) {
|
|
CVExprErr ( Err, MSGSTRING, &hTM, szBuffer );
|
|
return(szBuffer);
|
|
}
|
|
|
|
szValue = (PSTR) MMLpvLockMb( (HDEP)hValue );
|
|
strncpy(szBuffer,szValue,BUFFERMAX);
|
|
MMbUnlockMb ( (HDEP)hValue );
|
|
EEFreeStr(hValue);
|
|
|
|
// If we have a new line in the string then terminate there
|
|
//pszBuffer = strchr(szBuffer,'\n');
|
|
//if (pszBuffer) *pszBuffer = 0;
|
|
|
|
|
|
return(szBuffer);
|
|
}
|
|
|
|
|
|
/*** FTGetVibNameString
|
|
|
|
* Purpose:
|
|
* Get a pointer to a vib return a string that contains the
|
|
* text for the name portion.
|
|
|
|
* Input:
|
|
* pVib - Pointer to the VIB (Variable Information Block)
|
|
|
|
* Output:
|
|
* Returns a pointer to the String o rNULL
|
|
|
|
* Exceptions:
|
|
|
|
|
|
*/
|
|
|
|
PSTR
|
|
FTGetVibNameString(
|
|
PTRVIB pVib
|
|
)
|
|
{
|
|
PSTR pszBuffer = szBuffer;
|
|
PSTR szValue;
|
|
HDEP hType = 0;
|
|
EEHSTR hName = 0;
|
|
int i;
|
|
int len = 0;
|
|
EESTATUS Err;
|
|
|
|
/*
|
|
* put in indent
|
|
*/
|
|
|
|
|
|
if ((int)pVib->level < 128) {
|
|
for(i=0; i<(int)pVib->level; i++) {
|
|
*pszBuffer++ = '|';
|
|
*pszBuffer++ = ' ';
|
|
len += 2;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Get the Name
|
|
*/
|
|
|
|
switch(pVib->vibPtr) {
|
|
/*
|
|
* Case 1:
|
|
|
|
* This implies that the item is a real variable and we can
|
|
* know its name from what was typed in to the system. So
|
|
* get it from the typed in expression.
|
|
*/
|
|
|
|
case vibWatch:
|
|
strncpy(pszBuffer,pVib->pwoj->szExpStr,BUFFERMAX-len);
|
|
break;
|
|
|
|
/*
|
|
* Get the Name from the Type info
|
|
*/
|
|
|
|
case vibType:
|
|
if ((pVib->pwoj != NULL) && (pVib->pwoj->szExpStr != NULL)) {
|
|
strncpy(pszBuffer, pVib->pwoj->szExpStr, BUFFERMAX-len);
|
|
} else if ( pVib->flags.NoBind ) {
|
|
/*
|
|
* Out of Context, no info
|
|
*/
|
|
|
|
*pszBuffer = 0;
|
|
} else {
|
|
/*
|
|
* Get the Type String
|
|
*/
|
|
|
|
if (((Err = EEGetNameFromTM(&pVib->hTMBd, &hName)) != EENOERROR) ||
|
|
((Err = EEGetTypeFromTM(&pVib->hTMBd, hName,
|
|
(PEEHSTR)&hType, TRUE) != EENOERROR))) {
|
|
CVExprErr ( Err, MSGSTRING, &pVib->hTMBd, szBuffer );
|
|
if (hName) {
|
|
EEFreeStr(hName);
|
|
}
|
|
if (hType) {
|
|
EEFreeStr(hType);
|
|
}
|
|
return(szBuffer);
|
|
}
|
|
|
|
/*
|
|
* Lock it down and copy to the woj
|
|
*/
|
|
|
|
szValue = (PSTR) MMLpvLockMb ( hType );
|
|
strncpy(pszBuffer,szValue + sizeof(HDR_TYPE),BUFFERMAX-len);
|
|
MMbUnlockMb ( hType );
|
|
EEFreeStr ( (EEHSTR)hType );
|
|
}
|
|
break;
|
|
|
|
/*
|
|
* Case 3:
|
|
* We are doing deverivations from a base item. In this
|
|
* case we are hopless about getting the string correct
|
|
* on our own so let the EE get the string for use. It
|
|
* will still be wrong sometimes but mostly correct.
|
|
*/
|
|
|
|
case vibGeneric:
|
|
if (pVib->flags.NoBind) {
|
|
/*
|
|
* Expression is out of context so return NULL string
|
|
*/
|
|
*pszBuffer = 0;
|
|
} else {
|
|
/*
|
|
* Get the name from the TM
|
|
*/
|
|
|
|
Err = EEGetNameFromTM( &pVib->pvtext[pVib->vibIndex].htm,
|
|
&hName );
|
|
|
|
if ( Err != EENOERROR ) {
|
|
CVExprErr( Err, MSGSTRING,
|
|
&pVib->pvtext[pVib->vibIndex].htm, szBuffer);
|
|
if (hName) {
|
|
EEFreeStr( hName );
|
|
}
|
|
return szBuffer;
|
|
}
|
|
|
|
szValue = (PSTR) MMLpvLockMb( (HDEP) hName );
|
|
strncpy( pszBuffer, szValue, BUFFERMAX-len );
|
|
pszBuffer[BUFFERMAX-len] = 0;
|
|
MMbUnlockMb( (HDEP) hName );
|
|
EEFreeStr( hName );
|
|
}
|
|
break;
|
|
|
|
/*
|
|
* Case 4:
|
|
|
|
* Get the Name from the Evaluation tree
|
|
*/
|
|
default:
|
|
if ( pVib->flags.NoBind ) {
|
|
/*
|
|
* Out of Context, no info
|
|
*/
|
|
|
|
*pszBuffer = 0;
|
|
} else {
|
|
/*
|
|
* Get the Name from the tm
|
|
*/
|
|
|
|
if ( Err = EEGetNameFromTM ( &pVib->hTMBd, &hName) ) {
|
|
CVExprErr ( Err, MSGSTRING, &pVib->hTMBd, szBuffer );
|
|
if ( hName ) {
|
|
EEFreeStr(hName);
|
|
}
|
|
return(szBuffer);
|
|
}
|
|
|
|
szValue = (PSTR) MMLpvLockMb( (HDEP)hName );
|
|
strncpy(pszBuffer,szValue,BUFFERMAX-len);
|
|
pszBuffer[BUFFERMAX-len] = 0;
|
|
MMbUnlockMb ( (HDEP)hName );
|
|
EEFreeStr(hName);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return(szBuffer);
|
|
}
|
|
|
|
/*** FTGetWatchList
|
|
|
|
* Purpose:
|
|
* Return a buffer that has a list of all the Toplevel watchs
|
|
* for the given vit.
|
|
|
|
* Input:
|
|
* pVit - Pointer to the Variable Information Top
|
|
|
|
* Output:
|
|
* Returns a pointer to the formatted buffer or NULL if there
|
|
* was an error.
|
|
|
|
* Exceptions:
|
|
|
|
* Notes:
|
|
* The Buffer was malloced and needs to be free'd by the caller.
|
|
* The first character of each line is the expansion type.
|
|
|
|
*/
|
|
|
|
|
|
PSTR
|
|
FTGetWatchList(
|
|
PTRVIT pVit
|
|
)
|
|
{
|
|
PTRVIB pVib;
|
|
PSTR pBuffer; // Pointer to start of buffer
|
|
PSTR pCh; // Pointer to End of buffer
|
|
PSTR pName; // Pointer to next string
|
|
PSTR pType; // Pointer to the expansion string
|
|
|
|
ULONG Size = NAMES_BUFFER; // Size of Buffer
|
|
ULONG Cnt = 0; // Count of Lines
|
|
ULONG Len = 1; // Lenth of filled buffer
|
|
|
|
|
|
|
|
// If we can't get a buffer, give up
|
|
|
|
|
|
if ( !pVit || (pBuffer = (PSTR) malloc(NAMES_BUFFER)) == NULL) {
|
|
return(NULL);
|
|
}
|
|
pCh = pBuffer;
|
|
*pCh = 0;
|
|
|
|
|
|
// Loop through the VIT
|
|
|
|
|
|
pVib = pVit->pvibChild;
|
|
while ( pVib ) {
|
|
|
|
// Get the values
|
|
|
|
pName = FTGetVibNameString(pVib);
|
|
pType = FTGetVibTypeString(pVib);
|
|
|
|
// Make sure we fit in the buffer
|
|
|
|
if ( Len + strlen(pName) + 3 > Size ) {
|
|
Size += NAMES_BUFFER;
|
|
pBuffer = (PSTR) realloc(pBuffer, Size);
|
|
pCh = pBuffer + Len - 1 ; // Reposition to the same offset
|
|
}
|
|
|
|
// Copy the string and point to the end
|
|
|
|
*pCh++ = *pType;
|
|
strcpy(pCh, pName);
|
|
pCh += strlen(pName);
|
|
|
|
// Copy in the carriage return/linefeed
|
|
|
|
*pCh++ = '\r';
|
|
*pCh++ = '\n';
|
|
|
|
// Increment the length and get next vib
|
|
|
|
Len += strlen(pName) + 3;
|
|
pVib = pVib->pvibSib;
|
|
}
|
|
|
|
*pCh = 0;
|
|
return(pBuffer);
|
|
}
|
|
|
|
/*** FTSetWatchList
|
|
|
|
* Purpose:
|
|
* Restore a watch list that was generated by FTGetWatchList()
|
|
* for a given vit.
|
|
|
|
* Input:
|
|
* pVit - Pointer to the Variable Information Top
|
|
* List - Save area generated by FTGetWatchList()
|
|
|
|
* Output:
|
|
* None
|
|
|
|
* Exceptions:
|
|
|
|
* Notes:
|
|
|
|
*/
|
|
|
|
VOID
|
|
FTSetWatchList(
|
|
PTRVIT pVit,
|
|
PSTR list
|
|
)
|
|
{
|
|
PSTR pWatch;
|
|
PTRVIB pVib;
|
|
char cType;
|
|
|
|
// While we have line with \r\n
|
|
|
|
pWatch = strtok(list, "\r\n");
|
|
while ( pWatch ) {
|
|
|
|
if (IsDBCSLeadByte(*pWatch)) {
|
|
pWatch = strtok( NULL, "\r\n"); // Get the Next Watch
|
|
continue;
|
|
}
|
|
cType = *pWatch++; // Get the Expansion Type
|
|
pVib = AddCVWatch(pVit, pWatch); // Add the Watch
|
|
|
|
|
|
#if V-WILLHE
|
|
|
|
// NOTENOTE - V-Willhe If we do this we get free() areas. The
|
|
// vib is ok....check for corruption in
|
|
// FTExpandVib.
|
|
|
|
|
|
if ( pVib && cType == '-') { // If it was expanded,
|
|
FTExpandVib( pVib); // Make it so...
|
|
}
|
|
#endif
|
|
pWatch = strtok( NULL, "\r\n"); // Get the Next Watch
|
|
}
|
|
return;
|
|
}
|
|
|
|
/*** FTInvalidateVib
|
|
|
|
* Purpose:
|
|
* To invalidate the entire tree starting at a given node.
|
|
|
|
* Input:
|
|
* pVib - Pointer to a VIB
|
|
|
|
* Output:
|
|
* None
|
|
|
|
* Exceptions:
|
|
|
|
* Notes:
|
|
|
|
*/
|
|
|
|
|
|
VOID
|
|
FTInvalidateVib(
|
|
PTRVIB pvib
|
|
)
|
|
{
|
|
while ( pvib) {
|
|
|
|
// Make sure this one is invalidated
|
|
pvib->flags.NoBind = TRUE;
|
|
|
|
// If we have any children, invalidate them
|
|
if ( pvib->pcif ) {
|
|
FTInvalidateVib( pvib->pcif->pvibChild);
|
|
}
|
|
|
|
// Now take care of the siblings
|
|
pvib = pvib->pvibSib;
|
|
}
|
|
}
|
|
|
|
/*** FTResetVib
|
|
|
|
* Purpose:
|
|
* Reset any NoBind flags from this vib down
|
|
|
|
* Input:
|
|
* pVib - Pointer to a VIB
|
|
|
|
* Output:
|
|
* None
|
|
|
|
* Exceptions:
|
|
|
|
* Notes:
|
|
|
|
*/
|
|
|
|
|
|
VOID
|
|
FTResetVib(
|
|
PTRVIB pvib
|
|
)
|
|
{
|
|
while ( pvib) {
|
|
|
|
// Make sure this one is turned off
|
|
pvib->flags.NoBind = FALSE;
|
|
|
|
// If we have any children, reset them
|
|
if ( pvib->pcif ) {
|
|
FTResetVib( pvib->pcif->pvibChild);
|
|
}
|
|
|
|
// Now take care of the siblings
|
|
pvib = pvib->pvibSib;
|
|
}
|
|
}
|
|
|
|
|
|
/*** FTAgeVibValues
|
|
|
|
* Purpose:
|
|
* Age the Vib's value strings by moving it to the previous value.
|
|
* If we have a previous value free it. Null the current value.
|
|
|
|
* Input:
|
|
* pVib - Pointer to a VIB
|
|
|
|
* Output:
|
|
* None
|
|
|
|
* Exceptions:
|
|
|
|
* Notes:
|
|
|
|
*/
|
|
|
|
|
|
VOID
|
|
FTAgeVibValues(
|
|
PTRVIB pvib
|
|
)
|
|
{
|
|
ULONG i;
|
|
|
|
while ( pvib) {
|
|
|
|
FTEnsureTextExists( pvib );
|
|
if ( pvib->cText ) {
|
|
|
|
// For each text segment
|
|
|
|
for ( i=0; i < pvib->cText ; i++) {
|
|
|
|
// Free the Prev. If it exists
|
|
if ( pvib->pvtext[i].pszValueP ) {
|
|
free(pvib->pvtext[i].pszValueP);
|
|
}
|
|
|
|
// Move Current to Prev. and Null current
|
|
pvib->pvtext[i].pszValueP = pvib->pvtext[i].pszValueC;
|
|
pvib->pvtext[i].pszValueC = NULL;
|
|
}
|
|
}
|
|
|
|
// If we have any children, Age them
|
|
|
|
if ( pvib->pcif ) {
|
|
FTAgeVibValues( pvib->pcif->pvibChild);
|
|
}
|
|
|
|
// Now take care of the siblings
|
|
pvib = pvib->pvibSib;
|
|
}
|
|
}
|
|
|
|
|
|
/*** FTGetPanelString
|
|
|
|
* Purpose:
|
|
* Get the String associated with a vib index.
|
|
|
|
* Input:
|
|
* UINT PanelNumber - Panel whos string we need (BUTTON, LEFT, RIGHT)
|
|
* UINT VibINdex - Index of the Vib we need
|
|
|
|
* Output:
|
|
* PSTR Pointer to the buffer containing the string.
|
|
|
|
* Exceptions:
|
|
|
|
* Notes:
|
|
|
|
*/
|
|
|
|
|
|
PSTR
|
|
FTGetPanelString(
|
|
PTRVIT pVit,
|
|
PTRVIB pVib,
|
|
UINT PanelNumber
|
|
)
|
|
{
|
|
PVTEXT pvtext;
|
|
|
|
FTEnsureTextExists( pVib );
|
|
|
|
// Focus in on the one we want
|
|
switch (PanelNumber) {
|
|
|
|
case ID_PANE_BUTTON:
|
|
return(FTGetVibTypeString(pVib));
|
|
|
|
case ID_PANE_LEFT:
|
|
return(FTGetVibNameString(pVib));
|
|
|
|
case ID_PANE_RIGHT:
|
|
pvtext = &pVib->pvtext[pVib->vibIndex];
|
|
if ( pvtext->pszValueC == NULL) {
|
|
pvtext->pszValueC = _strdup(FTGetVibResultString(pVit,pVib));
|
|
}
|
|
return(pvtext->pszValueC);
|
|
|
|
default:
|
|
return(NULL);
|
|
}
|
|
|
|
}
|
|
|
|
/*** FTGetPanelStatus
|
|
|
|
* Purpose:
|
|
* Has the text for a panel id changed?
|
|
|
|
* Input:
|
|
* UINT PanelNumber - Panel whos string we need (BUTTON, LEFT, RIGHT)
|
|
* UINT VibINdex - Index of the Vib we need
|
|
|
|
* Output:
|
|
* TRUE/FALSE
|
|
|
|
* Exceptions:
|
|
|
|
* Notes:
|
|
|
|
*/
|
|
|
|
|
|
BOOL
|
|
FTGetPanelStatus(
|
|
PTRVIB pVib,
|
|
UINT PanelNumber
|
|
)
|
|
{
|
|
PVTEXT pvtext;
|
|
|
|
if ( PanelNumber == ID_PANE_RIGHT) {
|
|
FTEnsureTextExists( pVib );
|
|
pvtext = &pVib->pvtext[pVib->vibIndex];
|
|
if ( pvtext->pszValueC && pvtext->pszValueP) {
|
|
return ( strcmp( pvtext->pszValueC, pvtext->pszValueP) );
|
|
} else {
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
else {
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
/*** FTEnsureTextExists
|
|
|
|
* Purpose:
|
|
* Ensure that the Text segment for a vib exists
|
|
|
|
* Input:
|
|
* PRTVIB pVib - Pointer to the vib to check
|
|
|
|
* Output:
|
|
|
|
* Exceptions:
|
|
|
|
* Notes:
|
|
|
|
*/
|
|
|
|
VOID
|
|
FTEnsureTextExists(
|
|
PTRVIB pVib
|
|
)
|
|
{
|
|
int count;
|
|
int slack;
|
|
|
|
// Make sure we have a text segment
|
|
if ( pVib->pvtext == NULL) {
|
|
pVib->pvtext = (PVTEXT) malloc( sizeof(VTEXT) );
|
|
RAssert(pVib->pvtext);
|
|
memset(pVib->pvtext,0, sizeof(VTEXT));
|
|
pVib->cText = 1;
|
|
}
|
|
|
|
// Make sure the Indicated index has text associated
|
|
// with it, if not expand in 10 entry increments
|
|
|
|
if ( pVib->vibIndex + 1 > pVib->cText) {
|
|
count = pVib->vibIndex + 11;
|
|
slack = count - pVib->cText;
|
|
pVib->pvtext = (PVTEXT) realloc(pVib->pvtext, count * sizeof(VTEXT) );
|
|
RAssert(pVib->pvtext);
|
|
memset(&pVib->pvtext[pVib->cText], 0, slack * sizeof(VTEXT) );
|
|
pVib->cText = count;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
FTAddWatchVariable(
|
|
PTRVIT * ppVit,
|
|
PTRVIB * ppVib,
|
|
LPSTR lpszWatchVar
|
|
)
|
|
/*++
|
|
Routine Desciption:
|
|
Adds an expression to the pvitWatch tree
|
|
|
|
Arguments:
|
|
ppVit - * If NULL, then this argument is ignored.
|
|
* If not NULL, then the current VIT will be returned.
|
|
ppVib - * If NULL, then this argument is ignored.
|
|
* If not NULL, then the new VIB will be returned.
|
|
lpszWatchVar - Can be NULL, or point to a zero length string, However
|
|
nothing will be added.
|
|
|
|
Return Value:
|
|
FALSE - Failure. If the expression could not be added.
|
|
TRUE - Success. The expression was added.
|
|
--*/
|
|
{
|
|
PTRVIT pVit = NULL;
|
|
PTRVIB pVib = NULL;
|
|
|
|
if (!lpszWatchVar) {
|
|
return FALSE;
|
|
}
|
|
|
|
while (whitespace(*lpszWatchVar)) {
|
|
lpszWatchVar++;
|
|
}
|
|
|
|
if (strlen(lpszWatchVar) == 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
pVit = InitWatchVit();
|
|
pVib = AddCVWatch( pVit, lpszWatchVar);
|
|
|
|
if (ppVit) {
|
|
*ppVit = pVit;
|
|
}
|
|
if (ppVib) {
|
|
*ppVib = pVib;
|
|
}
|
|
|
|
return TRUE;
|
|
} |