//------------------------------------------------------------------------------
// Desc: This file contains routines for viewing blocks in the database.
//
// Tabs:	3
//
//		Copyright (c) 1992-2006 Novell, Inc. All Rights Reserved.
//
//		This program is free software; you can redistribute it and/or
//		modify it under the terms of version 2 of the GNU General Public
//		License as published by the Free Software Foundation.
//
//		This program is distributed in the hope that it will be useful,
//		but WITHOUT ANY WARRANTY; without even the implied warranty of
//		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//		GNU General Public License for more details.
//
//		You should have received a copy of the GNU General Public License
//		along with this program; if not, contact Novell, Inc.
//
//		To contact Novell about this file by physical or electronic mail,
//		you may find current contact information at www.novell.com
//
// $Id: viewblk.cpp 3119 2006-01-19 13:39:12 -0700 (Thu, 19 Jan 2006) dsanders $
//------------------------------------------------------------------------------

#include "view.h"

FSTATIC void InitStatusBits(
	FLMBYTE *	pucStatusBytes);

FSTATIC void OrStatusBits(
	FLMBYTE *	pucDestStatusBytes,
	FLMBYTE *	pucSrcStatusBytes);

FSTATIC FLMBOOL TestStatusBit(
	FLMBYTE *	pucStatusBytes,
	FLMINT		iErrorCode);

FSTATIC FLMBOOL OutBlkHdrExpNum(
	FLMUINT		uiCol,
	FLMUINT *	puiRow,
	eColorType	uiBackColor,
	eColorType	uiForeColor,
	eColorType	uiUnselectBackColor,
	eColorType	uiUnselectForeColor,
	eColorType	uiSelectBackColor,
	eColorType	uiSelectForeColor,
	FLMUINT		uiLabelWidth,
	FLMINT		iLabelIndex,
	FLMUINT		uiFileNumber,
	FLMUINT		uiFileOffset,
	void *		pvcValue,
	FLMUINT		uiValueType,
	FLMUINT		uiModType,
	FLMUINT64	ui64ExpNum,
	FLMUINT64	ui64IgnoreExpNum,
	FLMUINT		uiOption);

FSTATIC void FormatBlkType(
	char *		pszTempBuf,
	FLMUINT		uiBlkType
	);

FSTATIC FLMBOOL OutputStatus(
	FLMUINT		uiCol,
	FLMUINT *	puiRow,
	eColorType	uiBackColor,
	eColorType	uiForeColor,
	FLMUINT		uiLabelWidth,
	FLMINT		iLabelIndex,
	FLMBYTE *	pucStatusFlags
	);

FSTATIC FLMBOOL OutputLeafElements(
	FLMUINT				uiCol,
	FLMUINT  *			puiRow,
	F_BTREE_BLK_HDR *	pBlkHdr,
	BLK_EXP_p			pBlkExp,
	FLMBYTE *			pucBlkStatus,
	FLMBOOL				bStatusOnlyFlag);

FSTATIC FLMBOOL OutputDataOnlyElements(
	FLMUINT				uiCol,
	FLMUINT  *			puiRow,
	F_BLK_HDR *			pBlkHdr,
	BLK_EXP_p			pBlkExp,
	FLMBYTE *			pucBlkStatus,
	FLMBOOL				bStatusOnlyFlag);

FSTATIC FLMBOOL OutputNonLeafElements(
	FLMUINT				uiCol,
	FLMUINT *			puiRow,
	F_BTREE_BLK_HDR *	pBlkHdr,
	BLK_EXP_p			pBlkExp,
	FLMBYTE *			pucBlkStatus,
	FLMBOOL				bStatusOnlyFlag);

FSTATIC FLMBOOL OutputDomNode(
	FLMUINT			uiCol,
	FLMUINT *		puiRow,
	eColorType		uiBackColor,
	eColorType		uiForeColor,
	FLMBYTE *		pucVal,
	STATE_INFO *	pStateInfo);

FSTATIC void SetSearchTopBottom( void);

FSTATIC void GetElmInfo(
	FLMBYTE *			pucEntry,
	F_BTREE_BLK_HDR *	pBlkHdr,
	STATE_INFO *		pStateInfo);

extern FLMUINT	gv_uiTopLine;
extern FLMUINT	gv_uiBottomLine;

/********************************************************************
Desc:	Initialize status bits
*********************************************************************/
FSTATIC void InitStatusBits(
	FLMBYTE *	pucStatusBytes
	)
{
	if (pucStatusBytes)
	{
		f_memset( pucStatusBytes, 0, NUM_STATUS_BYTES);
	}
}

/********************************************************************
Desc:	OR together two sets of status bytes
*********************************************************************/
FSTATIC void OrStatusBits(
	FLMBYTE *	pucDestStatusBytes,
	FLMBYTE *	pucSrcStatusBytes
	)
{
	FLMUINT	uiLoop;

	if (pucDestStatusBytes && pucSrcStatusBytes)
	{
		for (uiLoop = 0; uiLoop < NUM_STATUS_BYTES; uiLoop++)
		{
			pucDestStatusBytes [uiLoop] |= pucSrcStatusBytes [uiLoop];
		}
	}
}

/********************************************************************
Desc:	TestStatusBit
*********************************************************************/
FSTATIC FLMBOOL TestStatusBit(
	FLMBYTE *	pucStatusBytes,
	FLMINT		iErrorCode
	)
{

	if (!pucStatusBytes)
	{
		return( FALSE);
	}
	else
	{
		return( (FLMBOOL)(pucStatusBytes [(iErrorCode - 1) / 8] & 
			(FLMBYTE)((FLMBYTE)0x80 >> (FLMBYTE)((iErrorCode - 1) % 8))
			? TRUE
			: FALSE));
	}
}

/***************************************************************************
Desc: This routine outputs all of the status bits which were set for
		a block.  Each error discovered in a block will be displayed on
		a separate line.
*****************************************************************************/
FSTATIC FLMBOOL OutputStatus(
	FLMUINT		uiCol,
	FLMUINT  *	puiRow,
	eColorType	uiBackColor,
	eColorType	uiForeColor,
	FLMUINT		uiLabelWidth,
	FLMINT		iLabelIndex,
	FLMBYTE *	pucStatusFlags
	)
{
	FLMBOOL	bOk = FALSE;
	FLMUINT	uiRow = *puiRow;
	FLMINT	iError;
	FLMBOOL	bHadError = FALSE;

	// Output each error on a separate line

	if (pucStatusFlags)
	{
		for (iError = 0; iError < FLM_NUM_CORRUPT_ERRORS; iError++)
		{
			if (TestStatusBit( pucStatusFlags, iError))
			{
				bHadError = TRUE;
				if (!ViewAddMenuItem( iLabelIndex, uiLabelWidth,
							VAL_IS_ERR_INDEX, (FLMUINT64)iError, 0,
							0, VIEW_INVALID_FILE_OFFSET, 0, MOD_DISABLED,
							uiCol, uiRow++, 0,
							FLM_RED, FLM_LIGHTGRAY,
							FLM_RED, FLM_LIGHTGRAY))
				{
					goto Exit;
				}

				// Set iLabelIndex to -1 so that it will not be displayed after
				// the first one.

				iLabelIndex = -1;
			}
		}
	}

	// If there were no errors in the block, just output an OK status

	if (!bHadError)
	{
		if (!ViewAddMenuItem( iLabelIndex, uiLabelWidth,
					VAL_IS_LABEL_INDEX, (FLMUINT64)LBL_OK, 0,
					0, VIEW_INVALID_FILE_OFFSET, 0, MOD_DISABLED,
					uiCol, uiRow++, 0, uiBackColor, uiForeColor,
					uiBackColor, uiForeColor))
		{
			goto Exit;
		}
	}
	*puiRow = uiRow;
	bOk = TRUE;

Exit:

	return( bOk);
}


/***************************************************************************
Desc: This routine reads into memory a database block.  It will also
		allocate memory to hold the block if necessary.  The block will
		also be decrypted if necessary.
*****************************************************************************/
FLMBOOL ViewBlkRead(
	FLMUINT			uiBlkAddress,
	F_BLK_HDR **	ppBlkHdr,
	FLMBOOL			bOkToConvert,
	FLMUINT			uiReadLen,
	FLMUINT32 *		pui32CalcCRC,
	FLMUINT32 *		pui32BlkCRC,
	FLMUINT *		puiBytesRead,
	FLMBOOL			bShowPartialReadError
	)
{
	FLMBOOL		bOk = FALSE;
	RCODE       rc;
	F_BLK_HDR *	pBlkHdr;
	char			szErrMsg [80];
	FLMUINT		uiBlkEnd;
	FLMUINT16	ui16BlkBytesAvail;

	// First allocate memory to read the block into
	// if not already allocated

	if (!(*ppBlkHdr))
	{
		if (RC_BAD( rc = f_alloc( uiReadLen, ppBlkHdr)))
		{
			ViewShowRCError( "allocating memory to read block", rc);
			goto Exit;
		}
	}
	pBlkHdr = *ppBlkHdr;

	// Read the block into memory
	
	if (RC_BAD( rc = gv_pSFileHdl->readBlock( uiBlkAddress, uiReadLen,
												pBlkHdr, puiBytesRead)))
	{
		if (rc == NE_XFLM_IO_END_OF_FILE)
		{
			rc = NE_XFLM_OK;
			f_memset( (FLMBYTE *)pBlkHdr + *puiBytesRead, 0xEE,
								uiReadLen - *puiBytesRead);
			if (bShowPartialReadError)
			{
				if (!(*puiBytesRead))
				{
					ViewShowRCError( "reading block", NE_XFLM_IO_END_OF_FILE);
					goto Exit;
				}
				else if (*puiBytesRead < uiReadLen)
				{
					f_sprintf( szErrMsg,
						"Only %u bytes of data were read (requested %u)",
							(unsigned)*puiBytesRead, (unsigned)uiReadLen);
					ViewShowError( szErrMsg);
				}
			}
		}
		else
		{
			ViewShowRCError( "reading block", rc);
			goto Exit;
		}
	}

	// Calculate the CRC on the block.

	if (bOkToConvert)
	{
		if (pui32CalcCRC)
		{
			ui16BlkBytesAvail = pBlkHdr->ui16BlkBytesAvail;
			if (blkIsNonNativeFormat( pBlkHdr))
			{
				convert16( &ui16BlkBytesAvail);
			}

			if( ui16BlkBytesAvail > gv_ViewDbHdr.ui16BlockSize)
			{
				*pui32CalcCRC = 0;
			}
			else
			{
				uiBlkEnd = (blkIsNewBTree( pBlkHdr)
								? gv_ViewDbHdr.ui16BlockSize
								: gv_ViewDbHdr.ui16BlockSize - (FLMUINT)ui16BlkBytesAvail);
				*pui32CalcCRC = calcBlkCRC( pBlkHdr, uiBlkEnd);
			}
		}

		if (blkIsNonNativeFormat( pBlkHdr))
		{
			convertBlk( (FLMUINT)gv_ViewDbHdr.ui16BlockSize, pBlkHdr);
		}

		if (pui32BlkCRC)
		{
			*pui32BlkCRC = pBlkHdr->ui32BlkCRC;
		}
	}

	bOk = TRUE;

Exit:

	return( bOk);
}

/***************************************************************************
Desc: This routine searches through the LFH blocks searching for the
		LFH of a particular logical file.
*****************************************************************************/
FLMBOOL ViewGetLFH(
	FLMUINT		uiLfNum,
	eLFileType	eLfType,
	F_LF_HDR *	pLfHdr,
	FLMUINT *	puiFileOffset)
{
	FLMUINT		uiBlkAddress;
	FLMUINT		uiBlkCount = 0;
	F_BLK_HDR *	pBlkHdr = NULL;
	F_LF_HDR *	pTmpLfHdr;
	FLMUINT		uiEndOfBlock;
	FLMUINT		uiPos;
	FLMUINT		uiBytesRead;
	FLMBOOL		bGotLFH = FALSE;

	// Read the LFH blocks and get the information needed
	// If we read too many, the file is probably corrupt.

	*puiFileOffset = 0;
	uiBlkAddress = (FLMUINT)gv_ViewDbHdr.ui32FirstLFBlkAddr;
	while (uiBlkAddress)
	{
		if (!ViewBlkRead( uiBlkAddress, &pBlkHdr, TRUE,
								(FLMUINT)gv_ViewDbHdr.ui16BlockSize,
								NULL, NULL, &uiBytesRead, FALSE) ||
			 !uiBytesRead)
		{
			break;
		}

		// Count the blocks read to prevent too many from being read.
		// We don't want to get into an infinite loop if the database
		// is corrupted.

		uiBlkCount++;

		// Search through the block for the particular LFH which matches
		// the one we are looking for.

		if (uiBytesRead <= SIZEOF_STD_BLK_HDR)
		{
			uiEndOfBlock = SIZEOF_STD_BLK_HDR;
		}
		else
		{
			uiEndOfBlock = blkGetEnd( (FLMUINT)gv_ViewDbHdr.ui16BlockSize,
									SIZEOF_STD_BLK_HDR, pBlkHdr);
			if (uiEndOfBlock > uiBytesRead)
			{
				uiEndOfBlock = uiBytesRead;
			}
		}
		uiPos = SIZEOF_STD_BLK_HDR;
		pTmpLfHdr = (F_LF_HDR *)((FLMBYTE *)pBlkHdr + SIZEOF_STD_BLK_HDR);
		while (uiPos < uiEndOfBlock)
		{

			// See if we got the one we wanted

			if (pTmpLfHdr->ui32LfType != XFLM_LF_INVALID &&
				 (FLMUINT)pTmpLfHdr->ui32LfNumber == uiLfNum &&
				 (FLMUINT)pTmpLfHdr->ui32LfType == (FLMUINT)eLfType)
			{
				f_memcpy( pLfHdr, pTmpLfHdr, sizeof( F_LF_HDR));
				bGotLFH = TRUE;
				*puiFileOffset = uiBlkAddress + uiPos;
				break;
			}

			uiPos += sizeof( F_LF_HDR);
			pTmpLfHdr++;
		}

		// If we didn't end right on end of block, return

		if (uiPos != uiEndOfBlock || bGotLFH)
		{
			break;
		}

		// If we have traversed too many blocks, things are probably corrupt

		if (uiBlkCount > 1000)
		{
			break;
		}
		if (F_BLK_HDR_ui32NextBlkInChain_OFFSET + 4 <= uiBytesRead)
		{
			uiBlkAddress = pBlkHdr->ui32NextBlkInChain;
		}
		else
		{
			uiBlkAddress = 0;
		}
	}

	// Be sure to free the block -- if one was allocated

	f_free( &pBlkHdr);
	return( bGotLFH);
}

/***************************************************************************
Desc: This routine attempts to find an LFH for a particular logical
		file.  It then extracts the name from the LFH.
*****************************************************************************/
FLMBOOL ViewGetLFName(
	char *			pszName,
	FLMUINT			uiLfNum,
	eLFileType		eLfType,
	F_LF_HDR *		pLfHdr,
	FLMUINT *		puiFileOffset)
{
	f_sprintf( pszName, "lfNum=%u", (unsigned)uiLfNum);
	if (!uiLfNum || !ViewGetLFH( uiLfNum, eLfType, pLfHdr, puiFileOffset))
	{
		*puiFileOffset = 0;
		f_memset( pLfHdr, 0, sizeof( F_LF_HDR));
		return( FALSE);
	}
	return( TRUE);
}

/***************************************************************************
Desc: This routine outputs one of the number fields in the block
		header.  It checks the number against an expected value, and if
		the number does not match the expected value also outputs the
		value which was expected.  This routine is used to output values
		in the block header where we expect certain values.
*****************************************************************************/
FSTATIC FLMBOOL OutBlkHdrExpNum(
	FLMUINT			uiCol,
	FLMUINT *		puiRow,
	eColorType		uiBackColor,
	eColorType		uiForeColor,
	eColorType		uiUnselectBackColor,
	eColorType		uiUnselectForeColor,
	eColorType		uiSelectBackColor,
	eColorType		uiSelectForeColor,
	FLMUINT			uiLabelWidth,
	FLMINT			iLabelIndex,
	FLMUINT			uiFileNumber,
	FLMUINT			uiFileOffset,
	void *			pvValue,
	FLMUINT			uiValueType,
	FLMUINT			uiModType,
	FLMUINT64		ui64ExpNum,
	FLMUINT64		ui64IgnoreExpNum,
	FLMUINT			uiOption)
{
	FLMBOOL		bOk = FALSE;
	FLMUINT		uiRow = *puiRow;
	FLMUINT64	ui64Num = 0;

	if (!uiOption)
	{
		uiUnselectBackColor = uiSelectBackColor = uiBackColor;
		uiUnselectForeColor = uiSelectForeColor = uiForeColor;
	}
	switch (uiModType & 0x0F)
	{
		case MOD_FLMUINT64:
			ui64Num = *((FLMUINT64 *)pvValue);
			break;
		case MOD_FLMUINT32:
			ui64Num = (FLMUINT64)(*((FLMUINT32 *)pvValue));
			break;
		case MOD_FLMUINT16:
			ui64Num = (FLMUINT64)(*((FLMUINT16 *)pvValue));
			break;
		case MOD_FLMBYTE:
			ui64Num = (FLMUINT64)(*((FLMUINT8 *)pvValue));
			break;
	}
	if (!ViewAddMenuItem( iLabelIndex, uiLabelWidth,
				uiValueType, ui64Num, 0,
				uiFileNumber, uiFileOffset, 0,
				uiModType | MOD_NATIVE,
				uiCol, uiRow++, uiOption,
				uiUnselectBackColor, uiUnselectForeColor,
				uiSelectBackColor, uiSelectForeColor))
	{
		goto Exit;
	}

	if (ui64ExpNum != ui64IgnoreExpNum && ui64Num != ui64ExpNum)
	{
		if (!ViewAddMenuItem( LBL_EXPECTED, 0,
					uiValueType, ui64ExpNum, 0,
					0, VIEW_INVALID_FILE_OFFSET, 0, MOD_DISABLED,
					uiCol + uiLabelWidth + 1, uiRow++, 0,
					FLM_RED, FLM_LIGHTGRAY,
					FLM_RED, FLM_LIGHTGRAY))
		{
			goto Exit;
		}
	}
	*puiRow = uiRow;
	bOk = TRUE;

Exit:

	return( bOk);
}

/***************************************************************************
Desc:	This routine formats a block's type into ASCII.
*****************************************************************************/
FSTATIC void FormatBlkType(
	char *		pszTempBuf,
	FLMUINT		uiBlkType
	)
{
	switch (uiBlkType)
	{
		case BT_FREE:
			f_strcpy( pszTempBuf, "Free");
			break;
		case BT_LEAF:
			f_strcpy( pszTempBuf, "Leaf");
			break;
		case BT_NON_LEAF:
			f_strcpy( pszTempBuf, "Non-Leaf");
			break;
		case BT_NON_LEAF_COUNTS:
			f_strcpy( pszTempBuf, "Non-Leaf /w Counts");
			break;
		case BT_LEAF_DATA:
			f_strcpy( pszTempBuf, "Leaf /w Data");
			break;
		case BT_DATA_ONLY:
			f_strcpy( pszTempBuf, "Data Only");
			break;
		case BT_LFH_BLK:
			f_strcpy( pszTempBuf, "LFH");
			break;
		default:
			f_sprintf( pszTempBuf,
				"Unknown Type: %u", (unsigned)uiBlkType);
			break;
	}
}

/***************************************************************************
Desc:	This routine outputs a block's header.
*****************************************************************************/
FLMBOOL ViewOutBlkHdr(
	FLMUINT		uiCol,
	FLMUINT *	puiRow,
	F_BLK_HDR *	pBlkHdr,
	BLK_EXP_p	pBlkExp,
	FLMBYTE *	pucBlkStatus,
	FLMUINT32	ui32CalcCRC,
	FLMUINT32	ui32BlkCRC
	)
{
	FLMBOOL			bOk = FALSE;
	FLMUINT			uiLabelWidth = 35;
	FLMUINT			uiRow = *puiRow;
	char				szTempBuf [80];
	FLMUINT			uiBlkAddress;
	FLMUINT			uiEndOfBlock;
	FLMUINT			uiBytesUsed;
	FLMUINT			uiPercentFull;
	FLMUINT			uiOption;
	eColorType		uiBackColor = FLM_BLACK;
	eColorType		uiForeColor = FLM_LIGHTGRAY;
	eColorType		uiUnselectBackColor = FLM_BLACK;
	eColorType		uiUnselectForeColor = FLM_WHITE;
	eColorType		uiSelectBackColor = FLM_BLUE;
	eColorType		uiSelectForeColor = FLM_WHITE;
	F_LF_HDR			lfHdr;
	char				szLfName [80];
	FLMUINT			uiLfNum;
	eLFileType		eLfType;
	FLMUINT			uiTempFileOffset;

	// Output the block Header address

	if (!OutBlkHdrExpNum( uiCol, &uiRow, FLM_RED, FLM_LIGHTGRAY,
			FLM_RED, FLM_WHITE, uiSelectBackColor, uiSelectForeColor,
			uiLabelWidth, LBL_BLOCK_ADDRESS_BLOCK_HEADER,
			FSGetFileNumber( pBlkExp->uiBlkAddr), 
			FSGetFileOffset( pBlkExp->uiBlkAddr),
			&pBlkHdr->ui32BlkAddr,
			VAL_IS_NUMBER | DISP_HEX_DECIMAL,
			MOD_FLMUINT32 | MOD_HEX | MOD_NATIVE,
			(FLMUINT64)pBlkExp->uiBlkAddr, 0, 0))
	{
		goto Exit;
	}

	// Adjust column so rest of header is indented

	uiCol += 2;
	uiLabelWidth -= 2;

	// Output the previous block address

	if (!pBlkHdr->ui32PrevBlkInChain)
	{
		uiOption = 0;
	}
	else
	{
		uiOption = PREV_BLOCK_OPTION;
	}
	if (!OutBlkHdrExpNum( uiCol, &uiRow, uiBackColor, uiForeColor,
				uiUnselectBackColor, uiUnselectForeColor,
				uiSelectBackColor, uiSelectForeColor,
				uiLabelWidth, LBL_PREVIOUS_BLOCK_ADDRESS,
				FSGetFileNumber( pBlkExp->uiBlkAddr), 
				FSGetFileOffset( pBlkExp->uiBlkAddr) +
				F_BLK_HDR_ui32PrevBlkInChain_OFFSET,
				&pBlkHdr->ui32PrevBlkInChain,
				VAL_IS_NUMBER | DISP_HEX_DECIMAL,
				MOD_FLMUINT32 | MOD_HEX | MOD_NATIVE,
				(FLMUINT64)pBlkExp->uiPrevAddr, 0xFFFFFFFF, uiOption))
	{
		goto Exit;
	}

	// Output the next block address

	if (!pBlkHdr->ui32NextBlkInChain)
	{
		uiOption = 0;
	}
	else
	{
		uiOption = NEXT_BLOCK_OPTION;
	}
	if (!OutBlkHdrExpNum( uiCol, &uiRow, uiBackColor, uiForeColor,
				uiUnselectBackColor, uiUnselectForeColor,
				uiSelectBackColor, uiSelectForeColor,
				uiLabelWidth, LBL_NEXT_BLOCK_ADDRESS,
				FSGetFileNumber( pBlkExp->uiBlkAddr), 
				FSGetFileOffset( pBlkExp->uiBlkAddr) +
				F_BLK_HDR_ui32NextBlkInChain_OFFSET,
				&pBlkHdr->ui32NextBlkInChain,
				VAL_IS_NUMBER | DISP_HEX_DECIMAL,
				MOD_FLMUINT32 | MOD_HEX | MOD_NATIVE,
				(FLMUINT64)pBlkExp->uiNextAddr, 0xFFFFFFFF, uiOption))
	{
		goto Exit;
	}

	// Output the prior block image address

	uiBlkAddress = (FLMUINT)pBlkHdr->ui32PriorBlkImgAddr;
	if (uiBlkAddress == 0 ||
			pBlkHdr->ui64TransID <= gv_ViewDbHdr.ui64CurrTransID)
	{
		uiOption = 0;
	}
	else
	{
		uiOption = PREV_BLOCK_IMAGE_OPTION;
	}
	if (!ViewAddMenuItem( LBL_OLD_BLOCK_IMAGE_ADDRESS, uiLabelWidth,
				VAL_IS_NUMBER | DISP_HEX_DECIMAL,
				(FLMUINT64)uiBlkAddress, 0,
				FSGetFileNumber( pBlkExp->uiBlkAddr),
				FSGetFileOffset( pBlkExp->uiBlkAddr) +
				F_BLK_HDR_ui32PriorBlkImgAddr_OFFSET, 0,
				MOD_FLMUINT32 | MOD_HEX | MOD_NATIVE,
				uiCol, uiRow++, uiOption,
				(!uiOption ? uiBackColor : uiUnselectBackColor),
				(!uiOption ? uiForeColor : uiUnselectForeColor),
				(!uiOption ? uiBackColor : uiSelectBackColor),
				(!uiOption ? uiForeColor : uiSelectForeColor)))
	{
		goto Exit;
	}

	// Output the block transaction ID

	if (!ViewAddMenuItem( LBL_BLOCK_TRANS_ID, uiLabelWidth,
				VAL_IS_NUMBER | DISP_DECIMAL,
				pBlkHdr->ui64TransID, 0,
				FSGetFileNumber( pBlkExp->uiBlkAddr),
				FSGetFileOffset( pBlkExp->uiBlkAddr) +
				F_BLK_HDR_ui64TransID_OFFSET, 0,
				MOD_FLMUINT32 | MOD_DECIMAL | MOD_NATIVE,
				uiCol, uiRow++, 0, uiBackColor, uiForeColor,
				uiBackColor, uiForeColor))
	{
		goto Exit;
	}

	// Output the block CRC

	if (!OutBlkHdrExpNum( uiCol, &uiRow, uiBackColor, uiForeColor,
			uiUnselectBackColor, uiUnselectForeColor,
			uiSelectBackColor, uiSelectForeColor,
			uiLabelWidth, LBL_BLOCK_CRC,
			FSGetFileNumber( pBlkExp->uiBlkAddr), 
			FSGetFileOffset( pBlkExp->uiBlkAddr) +
			F_BLK_HDR_ui32BlkCRC_OFFSET,
			&ui32BlkCRC,
			VAL_IS_NUMBER | DISP_DECIMAL,
			MOD_FLMUINT32 | MOD_DECIMAL | MOD_NATIVE,
			(FLMUINT64)ui32CalcCRC, 0, 0))
	{
		return( 0);
	}

	// Output the available bytes in the block

	if (!ViewAddMenuItem( LBL_BLOCK_BYTES_AVAIL, uiLabelWidth,
				VAL_IS_NUMBER | DISP_DECIMAL,
				(FLMUINT64)pBlkHdr->ui16BlkBytesAvail, 0,
				FSGetFileNumber( pBlkExp->uiBlkAddr),
				FSGetFileOffset( pBlkExp->uiBlkAddr) +
				F_BLK_HDR_ui16BlkBytesAvail_OFFSET, 0,
				MOD_FLMUINT16 | MOD_DECIMAL | MOD_NATIVE,
				uiCol, uiRow++, 0, uiBackColor, uiForeColor,
				uiBackColor, uiForeColor))
	{
		goto Exit;
	}

	// Output the heap bytes in the block
	if ((pBlkHdr->ui8BlkType == BT_LEAF) ||
		 (pBlkHdr->ui8BlkType == BT_LEAF_DATA) ||
		 (pBlkHdr->ui8BlkType == BT_NON_LEAF) ||
		 (pBlkHdr->ui8BlkType == BT_NON_LEAF_COUNTS))
	{

		if (!ViewAddMenuItem( LBL_BLOCK_HEAP_SIZE, uiLabelWidth,
					VAL_IS_NUMBER | DISP_DECIMAL,
					(FLMUINT64)((F_BTREE_BLK_HDR *)pBlkHdr)->ui16HeapSize, 0,
					FSGetFileNumber( pBlkExp->uiBlkAddr),
					FSGetFileOffset( pBlkExp->uiBlkAddr) +
					F_BTREE_BLK_HDR_ui16HeapSize_OFFSET, 0,
					MOD_FLMUINT16 | MOD_DECIMAL | MOD_NATIVE,
					uiCol, uiRow++, 0, uiBackColor, uiForeColor,
					uiBackColor, uiForeColor))
		{
			goto Exit;
		}
	}

	uiEndOfBlock = blkGetEnd( (FLMUINT)gv_ViewDbHdr.ui16BlockSize,
							blkHdrSize( pBlkHdr), pBlkHdr);

	// Output the percent full

	if (blkIsNewBTree( pBlkHdr))
	{
		uiBytesUsed = gv_ViewDbHdr.ui16BlockSize -
			pBlkHdr->ui16BlkBytesAvail - blkHdrSize( pBlkHdr);
	}
	else
	{
		uiBytesUsed = uiEndOfBlock - blkHdrSize( pBlkHdr);
	}

	if (!uiBytesUsed || uiEndOfBlock < blkHdrSize( pBlkHdr))
	{
		uiPercentFull = 0;
	}
	else if (uiEndOfBlock > (FLMUINT)gv_ViewDbHdr.ui16BlockSize)
	{
		uiPercentFull = 100;
	}
	else
	{
		uiPercentFull = ((FLMUINT)(uiBytesUsed) * (FLMUINT)(100)) /
				 ((FLMUINT)(gv_ViewDbHdr.ui16BlockSize) -
				  blkHdrSize( pBlkHdr));
	}
	if (!ViewAddMenuItem( LBL_PERCENT_FULL, uiLabelWidth,
			VAL_IS_NUMBER | DISP_DECIMAL,
			(FLMUINT64)uiPercentFull, 0,
			0, VIEW_INVALID_FILE_OFFSET, 0, MOD_DISABLED,
			uiCol, uiRow++, 0, uiBackColor, uiForeColor,
			uiBackColor, uiForeColor))
	{
		goto Exit;
	}

	if (!ViewAddMenuItem( LBL_BLOCK_END, uiLabelWidth,
				VAL_IS_NUMBER | DISP_HEX_DECIMAL,
				(FLMUINT64)(FSGetFileOffset( pBlkExp->uiBlkAddr) + uiEndOfBlock),
				0,
				FSGetFileNumber( pBlkExp->uiBlkAddr),
				FSGetFileOffset( pBlkExp->uiBlkAddr) + uiEndOfBlock,
				0, MOD_DISABLED, uiCol, uiRow++,
				0, uiBackColor, uiForeColor,
				uiBackColor, uiForeColor))
	{
		goto Exit;
	}


	// Output block flags here

	if (pBlkHdr->ui8BlkFlags & BLK_FORMAT_IS_LITTLE_ENDIAN)
	{
		f_strcpy( szTempBuf, "Little-Endian");
	}
	else
	{
		f_strcpy( szTempBuf, "Big-Endian");
	}
	if (pBlkHdr->ui8BlkFlags & BLK_IS_BEFORE_IMAGE)
	{
		f_strcpy( &szTempBuf [f_strlen( szTempBuf)], ", Before-Image");
	}
	if (!ViewAddMenuItem( LBL_BLOCK_FLAGS, uiLabelWidth,
			VAL_IS_TEXT_PTR,
			(FLMUINT)&szTempBuf[0], 0,
			FSGetFileNumber( pBlkExp->uiBlkAddr),
			FSGetFileOffset( pBlkExp->uiBlkAddr) +
			F_BLK_HDR_ui8BlkFlags_OFFSET, 0,
			MOD_FLMBYTE | MOD_HEX | MOD_NATIVE,
			uiCol, uiRow++, 0, uiBackColor, uiForeColor,
			uiBackColor, uiForeColor))
	{
		goto Exit;
	}

	// Output the block type

	FormatBlkType( szTempBuf, (FLMUINT)pBlkHdr->ui8BlkType);
	if (pBlkHdr->ui8BlkType != (FLMUINT8)pBlkExp->uiType)
	{
		f_strcpy( &szTempBuf [f_strlen( szTempBuf)], ", Expecting ");
		FormatBlkType( &szTempBuf [f_strlen( szTempBuf)], pBlkExp->uiType);
	}
	if (!ViewAddMenuItem( LBL_BLOCK_TYPE, uiLabelWidth,
			VAL_IS_TEXT_PTR,
			(FLMUINT)(&szTempBuf [0]), 0,
			FSGetFileNumber( pBlkExp->uiBlkAddr),
			FSGetFileOffset( pBlkExp->uiBlkAddr) +
			F_BLK_HDR_ui8BlkType_OFFSET, 0,
			MOD_FLMBYTE | MOD_HEX | MOD_NATIVE,
			uiCol, uiRow++, 0, uiBackColor, uiForeColor,
			uiBackColor, uiForeColor))
	{
		goto Exit;
	}

	if (blkIsBTree( pBlkHdr) && (pBlkHdr->ui8BlkType != BT_DATA_ONLY))
	{

		// Output the logical file this block belongs to - if any

		uiLfNum = (FLMUINT)(((F_BTREE_BLK_HDR *)pBlkHdr)->ui16LogicalFile);
		eLfType = getBlkLfType( (F_BTREE_BLK_HDR *)pBlkHdr);
		if (!ViewGetLFName( szLfName, uiLfNum, eLfType,
									&lfHdr, &uiTempFileOffset))
		{
			eLfType = XFLM_LF_INVALID;
			uiOption = 0;
		}
		else
		{
			if (eLfType == XFLM_LF_INDEX)
			{
				uiOption = LOGICAL_INDEX_OPTION | uiLfNum;
			}
			else
			{
				uiOption = LOGICAL_CONTAINER_OPTION | uiLfNum;
			}
		}
		if (pBlkExp->uiLfNum && uiLfNum != pBlkExp->uiLfNum)
		{
			f_sprintf( (char *)szTempBuf, "%s (Expected %u)", szLfName,
						(unsigned)pBlkExp->uiLfNum);
		}
		else
		{
			f_strcpy( szTempBuf, szLfName);
		}
		if (!ViewAddMenuItem( LBL_BLOCK_LOGICAL_FILE_NAME, uiLabelWidth,
					VAL_IS_TEXT_PTR,
					(FLMUINT)((FLMBYTE *)(&szTempBuf [0])), 0,
					FSGetFileNumber( pBlkExp->uiBlkAddr),
					FSGetFileOffset( pBlkExp->uiBlkAddr) +
					F_BTREE_BLK_HDR_ui16LogicalFile_OFFSET, 0,
					MOD_FLMUINT16 | MOD_DECIMAL | MOD_NATIVE,
					uiCol, uiRow++, uiOption,
					(!uiOption ? uiBackColor : uiUnselectBackColor),
					(!uiOption ? uiForeColor : uiUnselectForeColor),
					(!uiOption ? uiBackColor : uiSelectBackColor),
					(!uiOption ? uiForeColor : uiSelectForeColor)))
		{
			goto Exit;
		}

		// Output the logical file type

		FormatLFType( szTempBuf, eLfType);
		if (!ViewAddMenuItem( LBL_BLOCK_LOGICAL_FILE_TYPE, uiLabelWidth,
					VAL_IS_TEXT_PTR,
					(FLMUINT)((FLMBYTE *)(&szTempBuf [0])), 0,
					FSGetFileNumber( pBlkExp->uiBlkAddr),
					FSGetFileOffset( pBlkExp->uiBlkAddr) +
					F_BTREE_BLK_HDR_ui8BTreeFlags_OFFSET, 0,
					MOD_FLMBYTE | MOD_HEX | MOD_NATIVE,
					uiCol, uiRow++, 0, uiBackColor, uiForeColor,
					uiBackColor, uiForeColor))
		{
			goto Exit;
		}

		// Output number of keys

		if (!ViewAddMenuItem( LBL_BLOCK_NUM_KEYS, uiLabelWidth,
					VAL_IS_NUMBER | DISP_DECIMAL,
					(FLMUINT64)(((F_BTREE_BLK_HDR *)pBlkHdr)->ui16NumKeys), 0,
					FSGetFileNumber( pBlkExp->uiBlkAddr),
					FSGetFileOffset( pBlkExp->uiBlkAddr) +
					F_BTREE_BLK_HDR_ui16NumKeys_OFFSET, 0,
					MOD_FLMUINT16 | MOD_DECIMAL | MOD_NATIVE,
					uiCol, uiRow++, 0, uiBackColor, uiForeColor,
					uiBackColor, uiForeColor))
		{
			goto Exit;
		}

		// Output block level

		if (!OutBlkHdrExpNum( uiCol, &uiRow,
				uiBackColor, uiForeColor,
				uiUnselectBackColor, uiUnselectForeColor,
				uiSelectBackColor, uiSelectForeColor,
				uiLabelWidth, LBL_B_TREE_LEVEL,
				FSGetFileNumber( pBlkExp->uiBlkAddr), 
				FSGetFileOffset( pBlkExp->uiBlkAddr) +
				F_BTREE_BLK_HDR_ui8BlkLevel_OFFSET,
				&(((F_BTREE_BLK_HDR *)pBlkHdr)->ui8BlkLevel),
				VAL_IS_NUMBER | DISP_DECIMAL,
				MOD_FLMBYTE | MOD_DECIMAL | MOD_NATIVE,
				(FLMUINT64)pBlkExp->uiLevel, (FLMUINT64)0xFF, 0))
		{
			goto Exit;
		}

		// Output if block is a root block

		if (!ViewAddMenuItem( LBL_BLOCK_ROOT, uiLabelWidth,
					VAL_IS_LABEL_INDEX,
					(FLMUINT64)(isRootBlk( (F_BTREE_BLK_HDR *)pBlkHdr)
									? (FLMUINT64)LBL_YES
									: (FLMUINT64)LBL_NO), 0,
					FSGetFileNumber( pBlkExp->uiBlkAddr),
					FSGetFileOffset( pBlkExp->uiBlkAddr) +
					F_BTREE_BLK_HDR_ui8BTreeFlags_OFFSET, 0,
					MOD_FLMBYTE | MOD_HEX | MOD_NATIVE,
					uiCol, uiRow++, 0, uiBackColor, uiForeColor,
					uiBackColor, uiForeColor))
		{
			goto Exit;
		}

		// Output if block is encrypted

		if (!ViewAddMenuItem( LBL_BLOCK_ENCRYPTED, uiLabelWidth,
					VAL_IS_LABEL_INDEX,
					(FLMUINT64)(isEncryptedBlk( pBlkHdr)
									? (FLMUINT64)LBL_YES
									: (FLMUINT64)LBL_NO), 0,
					FSGetFileNumber( pBlkExp->uiBlkAddr),
					FSGetFileOffset( pBlkExp->uiBlkAddr) +
					F_BTREE_BLK_HDR_ui8BTreeFlags_OFFSET, 0,
					MOD_FLMBYTE | MOD_HEX | MOD_NATIVE,
					uiCol, uiRow++, 0, uiBackColor, uiForeColor,
					uiBackColor, uiForeColor))
		{
			goto Exit;
		}

	}

	// Output the flags which indicate the state of the block

	if (!OutputStatus( uiCol, &uiRow, uiBackColor, uiForeColor,
					uiLabelWidth, LBL_BLOCK_STATUS, pucBlkStatus))
	{
		goto Exit;
	}

	*puiRow = uiRow + 1;
	bOk = TRUE;

Exit:

	return( bOk);
}

/***************************************************************************
Desc:	This routine displays a block in the AVAIL list.
*****************************************************************************/
FLMBOOL ViewAvailBlk(
	FLMUINT			uiReadAddress,
	FLMUINT			uiBlkAddress,
	F_BLK_HDR **	ppBlkHdr,
	BLK_EXP_p		pBlkExp
	)
{
	FLMBOOL			bOk = FALSE;
	FLMUINT			uiRow;
	FLMUINT			uiCol;
	F_BLK_HDR *		pBlkHdr;
	FLMBYTE			ucBlkStatus [NUM_STATUS_BYTES];
	STATE_INFO		StateInfo;
//	FLMBOOL			bStateInitialized = FALSE;
//	BLOCK_INFO		BlockInfo;
//	FLMINT			iErrorCode;
	FLMUINT32		ui32CalcCRC;
	FLMUINT32		ui32BlkCRC;
	FLMUINT			uiBytesRead;

	// Read the block into memory

	if (!ViewBlkRead( uiReadAddress, ppBlkHdr, TRUE,
							(FLMUINT)gv_ViewDbHdr.ui16BlockSize,
							&ui32CalcCRC, &ui32BlkCRC, &uiBytesRead, TRUE))
	{
		goto Exit;
	}
	pBlkHdr = *ppBlkHdr;

	ViewMenuInit( "AVAIL Block");

	// Output the block header first

	uiRow = 0;
	uiCol = 5;
	pBlkExp->uiType = BT_FREE;
	pBlkExp->uiLfNum = 0;
	pBlkExp->uiBlkAddr = uiBlkAddress;
	pBlkExp->uiLevel = 0xFF;

	// Setup the STATE variable for processing through the block

	InitStatusBits( ucBlkStatus);
#if 0
	flmInitReadState( &StateInfo, &bStateInitialized,
							(FLMUINT)gv_ViewDbHdr.ui32DbVersion,
							(gv_bViewDbInitialized)
							? gv_hViewDb
							: NULL,
							NULL, 0, BT_FREE, NULL);
#endif
	StateInfo.ui32BlkAddress = (FLMUINT32)uiBlkAddress;
	StateInfo.pBlkHdr = pBlkHdr;
#if 0
	if ((iErrorCode = flmVerifyBlockHeader( &StateInfo, &BlockInfo,
											 (FLMUINT)gv_ViewDbHdr.ui16BlockSize,
											 pBlkExp->uiNextAddr,
											 0xFFFFFFFF,
											 (FLMBOOL)(StateInfo.pDb != NULL
															  ? TRUE
															  : FALSE))) != 0)
	{
		SetStatusBit( ucBlkStatus, iErrorCode);
	}
#endif
	if (!ViewOutBlkHdr( uiCol, &uiRow, pBlkHdr, pBlkExp, ucBlkStatus,
								ui32CalcCRC, ui32BlkCRC))
	{
		goto Exit;
	}
	bOk = TRUE;

Exit:

	return( bOk);
}

/***************************************************************************
Desc: This routine outputs a stream of FLMBYTEs in hex format.  This
		routine is used to output key values and records within an
		element.
*****************************************************************************/
FLMBOOL OutputHexValue(
	FLMUINT			uiCol,
	FLMUINT *		puiRow,
	eColorType		uiBackColor,
	eColorType		uiForeColor,
	FLMINT			iLabelIndex,
	FLMUINT			uiFileNumber,
	FLMUINT			uiFileOffset,
	FLMBYTE *		pucVal,
	FLMUINT			uiValLen,
	FLMBOOL			bCopyVal)
{
	FLMBOOL		bOk = FALSE;
	FLMUINT		uiRow = *puiRow;
	FLMUINT		uiBytesPerLine = MAX_HORIZ_SIZE( uiCol + 3);
	FLMBOOL		bFirstTime = TRUE;
	FLMUINT		uiBytesProcessed = 0;
	FLMUINT		uiNumBytes;

	while (uiBytesProcessed < uiValLen)
	{
		if ((uiNumBytes = uiValLen - uiBytesProcessed) > uiBytesPerLine)
		{
			uiNumBytes = uiBytesPerLine;
		}

		// Output the line

		if (bFirstTime)
		{
			if (!ViewAddMenuItem( iLabelIndex, 0,
										VAL_IS_EMPTY, 0, 0,
										uiFileNumber, uiFileOffset, 0, MOD_DISABLED,
										uiCol, uiRow++, 0, uiBackColor, uiForeColor,
										uiBackColor, uiForeColor))
			{
				goto Exit;
			}
			bFirstTime = FALSE;
			uiCol += 2;
		}
		if (!ViewAddMenuItem( -1, 0,
					(FLMBYTE)((bCopyVal)
								? (FLMBYTE)VAL_IS_BINARY
								: (FLMBYTE)VAL_IS_BINARY_PTR),
					(FLMUINT)pucVal, uiNumBytes,
					uiFileNumber, uiFileOffset, uiNumBytes, MOD_BINARY,
					uiCol, uiRow++, 0, uiBackColor, uiForeColor,
					uiBackColor, uiForeColor))
		{
			goto Exit;
		}
		uiFileOffset += uiNumBytes;
		uiBytesProcessed += uiNumBytes;
		pucVal += uiNumBytes;
	}
	*puiRow = uiRow;
	bOk = TRUE;

Exit:

	return( bOk);
}

/***************************************************************************
Desc: This routine outputs the content of a DOM node in the Element
*****************************************************************************/
FSTATIC FLMBOOL OutputDomNode(
	FLMUINT				uiCol,
	FLMUINT *			puiRow,
	eColorType			uiBackColor,
	eColorType			uiForeColor,
	FLMBYTE *			pucVal,
	STATE_INFO *		pStateInfo)
{
	RCODE					rc = NE_XFLM_OK;
	FLMBOOL				bOk = FALSE;
	FLMUINT				uiLabelWidth = 30;
	FLMUINT				uiRow = *puiRow;
	FLMUINT				uiNumBytes;
	FLMBYTE *			pucData = pucVal;
	FLMUINT				uiDataOffset = pStateInfo->uiElmDataOffset;
	FLMBYTE				ucFlags = 0;
	FLMBYTE				ucExtFlags = 0;
	FLMUINT				uiSENLength = 0;
	const FLMBYTE *	pucTmp;
	FLMUINT64			ui64Value;
	FLMUINT				uiValue;
	
	// VISIT: change to use flmReadNodeInfo

	if ((uiNumBytes = pStateInfo->uiElmDataLen) == 0)
	{
		bOk = TRUE;
		goto Exit;
	}

	// Display the Node Type.  The first byte is encoded as RDDDNNNN
	// where R = Reserved, DDD = Data Type, NNNN = Node Type

	// Display the Data Type
	if (!ViewAddMenuItem( LBL_DOM_DATA_TYPE, uiLabelWidth,
			VAL_IS_NUMBER | DISP_HEX_DECIMAL,
			(*pucData & 0x70) >> 4, 0,
			FSGetFileNumber( pStateInfo->ui32BlkAddress),
			FSGetFileOffset( pStateInfo->ui32BlkAddress) + uiDataOffset,
			0, MOD_DISABLED,
			uiCol, uiRow++, 0,
			uiBackColor, uiForeColor,
			uiBackColor, uiForeColor))
	{
		goto Exit;
	}

	// Display the Node Type
	if (!ViewAddMenuItem( LBL_DOM_NODE_TYPE, uiLabelWidth,
			VAL_IS_NUMBER | DISP_HEX_DECIMAL,
			*pucData & 0x0F, 0,
			FSGetFileNumber( pStateInfo->ui32BlkAddress),
			FSGetFileOffset( pStateInfo->ui32BlkAddress) + uiDataOffset,
			0, MOD_DISABLED,
			uiCol, uiRow++, 0,
			uiBackColor, uiForeColor,
			uiBackColor, uiForeColor))
	{
		goto Exit;
	}

	pucData++;
	uiDataOffset++;
	uiNumBytes--;

	if (!uiNumBytes)
	{
		if (!ViewAddMenuItem( LBL_DOM_FLAGS, uiLabelWidth,
				VAL_IS_LABEL_INDEX,
				LBL_NO_VALUE, 0,
				0, VIEW_INVALID_FILE_OFFSET,
				0, MOD_DISABLED,
				uiCol, uiRow++, 0, uiBackColor, uiForeColor,
				uiBackColor, uiForeColor))
		{
			goto Exit;
		}
	}
	else
	{
		ucFlags = *pucData;
	
		// Display the flags
		if (!ViewAddMenuItem( LBL_DOM_FLAGS, uiLabelWidth,
				VAL_IS_NUMBER | DISP_HEX_DECIMAL,
				*pucData, 0,
				FSGetFileNumber( pStateInfo->ui32BlkAddress),
				FSGetFileOffset( pStateInfo->ui32BlkAddress) + uiDataOffset,
				0, MOD_DISABLED,
				uiCol, uiRow++, 0,
				uiBackColor, uiForeColor,
				uiBackColor, uiForeColor))
		{
			goto Exit;
		}
	
		pucData++;
		uiDataOffset++;
		uiNumBytes--;
	}

	// Name ID
	if (!uiNumBytes)
	{
		if (!ViewAddMenuItem( LBL_DOM_NAME_ID, uiLabelWidth,
				VAL_IS_LABEL_INDEX,
				LBL_NO_VALUE, 0,
				0, VIEW_INVALID_FILE_OFFSET,
				0, MOD_DISABLED,
				uiCol, uiRow++, 0, uiBackColor, uiForeColor,
				uiBackColor, uiForeColor))
		{
			goto Exit;
		}
	}
	else
	{
		pucTmp = pucData;
		uiSENLength = f_getSENLength( *pucTmp);
		if (uiNumBytes >= uiSENLength)
		{
			if( RC_BAD( rc = f_decodeSEN( &pucTmp, 
				&pucTmp[ FLM_MAX_NUM_BUF_SIZE], &uiValue)))
			{
				goto Exit;
			}

			if (!ViewAddMenuItem( LBL_DOM_NAME_ID, uiLabelWidth,
					VAL_IS_NUMBER | DISP_HEX_DECIMAL,
					uiValue, 0,
					FSGetFileNumber( pStateInfo->ui32BlkAddress),
					FSGetFileOffset( pStateInfo->ui32BlkAddress) + uiDataOffset,
					0, MOD_SEN5 | MOD_HEX,
					uiCol, uiRow++, 0,
					uiBackColor, uiForeColor,
					uiBackColor, uiForeColor))
			{
				goto Exit;
			}
		}
		else
		{
			// If we can't display the number, at least display what we have left.
			if (!OutputHexValue( uiCol, &uiRow,
						uiBackColor, uiForeColor, LBL_DOM_NAME_ID,
						FSGetFileNumber( pStateInfo->ui32BlkAddress),
						FSGetFileOffset( pStateInfo->ui32BlkAddress) + uiDataOffset,
						pucData, uiNumBytes, FALSE))
			{
				goto Exit;
			}
			uiSENLength = uiNumBytes;
		}

		pucData += uiSENLength;
		uiNumBytes -= uiSENLength;
		uiDataOffset += uiSENLength;
	}

	// Prefix ID
	if (ucFlags & NSF_EXT_HAVE_PREFIX_BIT)
	{
		if (!uiNumBytes)
		{
			if (!ViewAddMenuItem( LBL_DOM_PREFIX_ID, uiLabelWidth,
					VAL_IS_LABEL_INDEX,
					LBL_NO_VALUE, 0,
					0, VIEW_INVALID_FILE_OFFSET,
					0, MOD_DISABLED,
					uiCol, uiRow++, 0, uiBackColor, uiForeColor,
					uiBackColor, uiForeColor))
			{
				goto Exit;
			}
		}
		else
		{
			pucTmp = pucData;
			uiSENLength = f_getSENLength( *pucTmp);
			if (uiNumBytes >= uiSENLength)
			{
				if( RC_BAD( rc = f_decodeSEN( &pucTmp, 
					&pucTmp[ FLM_MAX_NUM_BUF_SIZE], &uiValue)))
				{
					goto Exit;
				}
	
				if (!ViewAddMenuItem( LBL_DOM_PREFIX_ID, uiLabelWidth,
						VAL_IS_NUMBER | DISP_HEX_DECIMAL,
						uiValue, 0,
						FSGetFileNumber( pStateInfo->ui32BlkAddress),
						FSGetFileOffset( pStateInfo->ui32BlkAddress) + uiDataOffset,
						0, MOD_SEN5 | MOD_HEX,
						uiCol, uiRow++, 0,
						uiBackColor, uiForeColor,
						uiBackColor, uiForeColor))
				{
					goto Exit;
				}
			}
			else
			{
				// If we can't display the number, at least display what we have left.
				if (!OutputHexValue( uiCol, &uiRow,
							uiBackColor, uiForeColor, LBL_DOM_PREFIX_ID,
							FSGetFileNumber( pStateInfo->ui32BlkAddress),
							FSGetFileOffset( pStateInfo->ui32BlkAddress) +
								uiDataOffset,
							pucData, uiNumBytes, FALSE))
				{
					goto Exit;
				}
				uiSENLength = uiNumBytes;
			}
	
			pucData += uiSENLength;
			uiNumBytes -= uiSENLength;
			uiDataOffset += uiSENLength;
		}
	}

	if (!uiNumBytes)
	{
		if (!ViewAddMenuItem( LBL_DOM_BASE_ID, uiLabelWidth,
				VAL_IS_LABEL_INDEX,
				LBL_NO_VALUE, 0,
				0, VIEW_INVALID_FILE_OFFSET,
				0, MOD_DISABLED,
				uiCol, uiRow++, 0, uiBackColor, uiForeColor,
				uiBackColor, uiForeColor))
		{
			goto Exit;
		}
	}
	else
	{
		// Base ID (required)
		pucTmp = pucData;
		uiSENLength = f_getSENLength( *pucTmp);
		if (uiNumBytes >= uiSENLength)
		{
			if( RC_BAD( rc = f_decodeSEN64( &pucTmp, 
				&pucTmp[ FLM_MAX_NUM_BUF_SIZE], &ui64Value)))
			{
				goto Exit;
			}
	
			if (!ViewAddMenuItem( LBL_DOM_BASE_ID, uiLabelWidth,
					VAL_IS_NUMBER | DISP_HEX_DECIMAL,
					ui64Value, 0,
					FSGetFileNumber( pStateInfo->ui32BlkAddress),
					FSGetFileOffset( pStateInfo->ui32BlkAddress) + uiDataOffset,
					0, MOD_SEN9 | MOD_HEX,
					uiCol, uiRow++, 0,
					uiBackColor, uiForeColor,
					uiBackColor, uiForeColor))
			{
				goto Exit;
			}
		}
		else
		{
			// If we can't display the number, at least display what we have left.
			if (!OutputHexValue( uiCol, &uiRow,
						uiBackColor, uiForeColor, LBL_DOM_BASE_ID,
						FSGetFileNumber( pStateInfo->ui32BlkAddress),
						FSGetFileOffset( pStateInfo->ui32BlkAddress) + uiDataOffset,
						pucData, uiNumBytes, FALSE))
			{
				goto Exit;
			}
			uiSENLength = uiNumBytes;			
		}

		pucData += uiSENLength;
		uiDataOffset += uiSENLength;
		uiNumBytes -= uiSENLength;
	}

	if (!uiNumBytes)
	{
		if (!ViewAddMenuItem( LBL_DOM_ROOT_ID, uiLabelWidth,
				VAL_IS_LABEL_INDEX,
				LBL_NO_VALUE, 0,
				0, VIEW_INVALID_FILE_OFFSET,
				0, MOD_DISABLED,
				uiCol, uiRow++, 0, uiBackColor, uiForeColor,
				uiBackColor, uiForeColor))
		{
			goto Exit;
		}
	}
	else
	{
		pucTmp = pucData;
		uiSENLength = f_getSENLength( *pucTmp);
		if (uiNumBytes >= uiSENLength)
		{
			if( RC_BAD( rc = f_decodeSEN64( &pucTmp, 
				&pucTmp[ FLM_MAX_NUM_BUF_SIZE], &ui64Value)))
			{
				goto Exit;
			}

			if (!ViewAddMenuItem( LBL_DOM_ROOT_ID, uiLabelWidth,
					VAL_IS_NUMBER | DISP_HEX_DECIMAL,
					ui64Value, 0,
					FSGetFileNumber( pStateInfo->ui32BlkAddress),
					FSGetFileOffset( pStateInfo->ui32BlkAddress) + uiDataOffset,
					0, MOD_SEN9 | MOD_HEX,
					uiCol, uiRow++, 0,
					uiBackColor, uiForeColor,
					uiBackColor, uiForeColor))
			{
				goto Exit;
			}
		}
		else
		{
			// If we can't display the number, at least display what we have left.
			if (!OutputHexValue( uiCol, &uiRow,
						uiBackColor, uiForeColor, LBL_DOM_ROOT_ID,
						FSGetFileNumber( pStateInfo->ui32BlkAddress),
						FSGetFileOffset( pStateInfo->ui32BlkAddress) + uiDataOffset,
						pucData, uiNumBytes, FALSE))
			{
				goto Exit;
			}			
			uiSENLength = uiNumBytes;
		}
		pucData += uiSENLength;
		uiDataOffset += uiSENLength;
		uiNumBytes -= uiSENLength;
	}

	if (!uiNumBytes)
	{
		if (!ViewAddMenuItem( LBL_DOM_PARENT_ID, uiLabelWidth,
				VAL_IS_LABEL_INDEX,
				LBL_NO_VALUE, 0,
				0, VIEW_INVALID_FILE_OFFSET,
				0, MOD_DISABLED,
				uiCol, uiRow++, 0, uiBackColor, uiForeColor,
				uiBackColor, uiForeColor))
		{
			goto Exit;
		}
	}
	else
	{
		pucTmp = pucData;
		uiSENLength = f_getSENLength( *pucTmp);
		if (uiNumBytes >= uiSENLength)
		{
			if( RC_BAD( rc = f_decodeSEN64( &pucTmp, 
				&pucTmp[ FLM_MAX_NUM_BUF_SIZE], &ui64Value)))
			{
				goto Exit;
			}

			if (!ViewAddMenuItem( LBL_DOM_PARENT_ID, uiLabelWidth,
					VAL_IS_NUMBER | DISP_HEX_DECIMAL,
					ui64Value, 0,
					FSGetFileNumber( pStateInfo->ui32BlkAddress),
					FSGetFileOffset( pStateInfo->ui32BlkAddress) + uiDataOffset,
					0, MOD_SEN9 | MOD_HEX,
					uiCol, uiRow++, 0,
					uiBackColor, uiForeColor,
					uiBackColor, uiForeColor))
			{
				goto Exit;
			}
		}
		else
		{
			// If we can't display the number, at least display what we have left.
			if (!OutputHexValue( uiCol, &uiRow,
						uiBackColor, uiForeColor, LBL_DOM_PARENT_ID,
						FSGetFileNumber( pStateInfo->ui32BlkAddress),
						FSGetFileOffset( pStateInfo->ui32BlkAddress) + uiDataOffset,
						pucData, uiNumBytes, FALSE))
			{
				goto Exit;
			}
			uiSENLength = uiNumBytes;
		}
		pucData += uiSENLength;
		uiDataOffset += uiSENLength;
		uiNumBytes -= uiSENLength;
	}

	// Prev+Next Siblings
	if (ucFlags & NSF_HAVE_SIBLINGS_BIT)
	{
		if (!uiNumBytes)
		{
			if (!ViewAddMenuItem( LBL_DOM_PREV_SIB_ID, uiLabelWidth,
					VAL_IS_LABEL_INDEX,
					LBL_NO_VALUE, 0,
					0, VIEW_INVALID_FILE_OFFSET,
					0, MOD_DISABLED,
					uiCol, uiRow++, 0, uiBackColor, uiForeColor,
					uiBackColor, uiForeColor))
			{
				goto Exit;
			}
		}
		else
		{
			// Previous
			pucTmp = pucData;
			uiSENLength = f_getSENLength( *pucTmp);
			if (uiNumBytes >= uiSENLength)
			{
				if( RC_BAD( rc = f_decodeSEN64( &pucTmp, 
					&pucTmp[ FLM_MAX_NUM_BUF_SIZE], &ui64Value)))
				{
					goto Exit;
				}
	
				if (!ViewAddMenuItem( LBL_DOM_PREV_SIB_ID, uiLabelWidth,
						VAL_IS_NUMBER | DISP_HEX_DECIMAL,
						ui64Value, 0,
						FSGetFileNumber( pStateInfo->ui32BlkAddress),
						FSGetFileOffset( pStateInfo->ui32BlkAddress) + uiDataOffset,
						0, MOD_SEN9 | MOD_HEX,
						uiCol, uiRow++, 0,
						uiBackColor, uiForeColor,
						uiBackColor, uiForeColor))
				{
					goto Exit;
				}
			}
			else
			{
				// If we can't display the number, at least display what we have left.
				if (!OutputHexValue( uiCol, &uiRow,
							uiBackColor, uiForeColor, LBL_DOM_PREV_SIB_ID,
							FSGetFileNumber( pStateInfo->ui32BlkAddress),
							FSGetFileOffset( pStateInfo->ui32BlkAddress) + uiDataOffset,
							pucData, uiNumBytes, FALSE))
				{
					goto Exit;
				}
				uiSENLength = uiNumBytes;
			}
	
			pucData += uiSENLength;
			uiDataOffset += uiSENLength;
			uiNumBytes -= uiSENLength;
		}

		if (!uiNumBytes)
		{
			if (!ViewAddMenuItem( LBL_DOM_NEXT_SIB_ID, uiLabelWidth,
					VAL_IS_LABEL_INDEX,
					LBL_NO_VALUE, 0,
					0, VIEW_INVALID_FILE_OFFSET,
					0, MOD_DISABLED,
					uiCol, uiRow++, 0, uiBackColor, uiForeColor,
					uiBackColor, uiForeColor))
			{
				goto Exit;
			}
		}
		else
		{
			// Next
			pucTmp = pucData;
			uiSENLength = f_getSENLength( *pucTmp);
			if (uiNumBytes >= uiSENLength)
			{
				if( RC_BAD( rc = f_decodeSEN64( &pucTmp, 
					&pucTmp[ FLM_MAX_NUM_BUF_SIZE], &ui64Value)))
				{
					goto Exit;
				}
	
				if (!ViewAddMenuItem( LBL_DOM_NEXT_SIB_ID, uiLabelWidth,
						VAL_IS_NUMBER | DISP_HEX_DECIMAL,
						ui64Value, 0,
						FSGetFileNumber( pStateInfo->ui32BlkAddress),
						FSGetFileOffset( pStateInfo->ui32BlkAddress) + uiDataOffset,
						0, MOD_SEN9 | MOD_HEX,
						uiCol, uiRow++, 0,
						uiBackColor, uiForeColor,
						uiBackColor, uiForeColor))
				{
					goto Exit;
				}
			}
			else
			{
				// If we can't display the number, at least display what we have left.
				if (!OutputHexValue( uiCol, &uiRow,
							uiBackColor, uiForeColor, LBL_DOM_NEXT_SIB_ID,
							FSGetFileNumber( pStateInfo->ui32BlkAddress),
							FSGetFileOffset( pStateInfo->ui32BlkAddress) + uiDataOffset,
							pucData, uiNumBytes, FALSE))
				{
					goto Exit;
				}
				uiSENLength = uiNumBytes;
			}
			pucData += uiSENLength;
			uiDataOffset += uiSENLength;
			uiNumBytes -= uiSENLength;
		}
	}

	// First+Last Child ID
	if (ucFlags & NSF_HAVE_CHILDREN_BIT)
	{
		// First
		if (!uiNumBytes)
		{
			if (!ViewAddMenuItem( LBL_DOM_FIRST_CHILD_ID, uiLabelWidth,
					VAL_IS_LABEL_INDEX,
					LBL_NO_VALUE, 0,
					0, VIEW_INVALID_FILE_OFFSET,
					0, MOD_DISABLED,
					uiCol, uiRow++, 0, uiBackColor, uiForeColor,
					uiBackColor, uiForeColor))
			{
				goto Exit;
			}
		}
		else
		{
			pucTmp = pucData;
			uiSENLength = f_getSENLength( *pucTmp);
			if (uiNumBytes >= uiSENLength)
			{
				if( RC_BAD( rc = f_decodeSEN64( &pucTmp, 
					&pucTmp[ FLM_MAX_NUM_BUF_SIZE], &ui64Value)))
				{
					goto Exit;
				}
	
				if (!ViewAddMenuItem( LBL_DOM_FIRST_CHILD_ID, uiLabelWidth,
						VAL_IS_NUMBER | DISP_HEX_DECIMAL,
						ui64Value, 0,
						FSGetFileNumber( pStateInfo->ui32BlkAddress),
						FSGetFileOffset( pStateInfo->ui32BlkAddress) + uiDataOffset,
						0, MOD_SEN9 | MOD_HEX,
						uiCol, uiRow++, 0,
						uiBackColor, uiForeColor,
						uiBackColor, uiForeColor))
				{
					goto Exit;
				}
			}
			else
			{
				// If we can't display the number, at least display what we have left.
				if (!OutputHexValue( uiCol, &uiRow,
							uiBackColor, uiForeColor, LBL_DOM_FIRST_CHILD_ID,
							FSGetFileNumber( pStateInfo->ui32BlkAddress),
							FSGetFileOffset( pStateInfo->ui32BlkAddress) + uiDataOffset,
							pucData, uiNumBytes, FALSE))
				{
					goto Exit;
				}
				uiSENLength = uiNumBytes;
			}
	
			pucData += uiSENLength;
			uiDataOffset += uiSENLength;
			uiNumBytes -= uiSENLength;
		}

		// Last
		if (!uiNumBytes)
		{
			if (!ViewAddMenuItem( LBL_DOM_LAST_CHILD_ID, uiLabelWidth,
					VAL_IS_LABEL_INDEX,
					LBL_NO_VALUE, 0,
					0, VIEW_INVALID_FILE_OFFSET,
					0, MOD_DISABLED,
					uiCol, uiRow++, 0, uiBackColor, uiForeColor,
					uiBackColor, uiForeColor))
			{
				goto Exit;
			}
		}
		else
		{
			pucTmp = pucData;
			uiSENLength = f_getSENLength( *pucTmp);
			if (uiNumBytes >= uiSENLength)
			{
				if( RC_BAD( rc = f_decodeSEN64( &pucTmp, 
					&pucTmp[ FLM_MAX_NUM_BUF_SIZE], &ui64Value)))
				{
					goto Exit;
				}
	
				if (!ViewAddMenuItem( LBL_DOM_LAST_CHILD_ID, uiLabelWidth,
						VAL_IS_NUMBER | DISP_HEX_DECIMAL,
						ui64Value, 0,
						FSGetFileNumber( pStateInfo->ui32BlkAddress),
						FSGetFileOffset( pStateInfo->ui32BlkAddress) + uiDataOffset,
						0, MOD_SEN9 | MOD_HEX,
						uiCol, uiRow++, 0,
						uiBackColor, uiForeColor,
						uiBackColor, uiForeColor))
				{
					goto Exit;
				}
			}
			else
			{
				// If we can't display the number, at least display what we have left.
				if (!OutputHexValue( uiCol, &uiRow,
							uiBackColor, uiForeColor, LBL_DOM_LAST_CHILD_ID,
							FSGetFileNumber( pStateInfo->ui32BlkAddress),
							FSGetFileOffset( pStateInfo->ui32BlkAddress) + uiDataOffset,
							pucData, uiNumBytes, FALSE))
				{
					goto Exit;
				}
				uiSENLength = uiNumBytes;
			}
			pucData += uiSENLength;
			uiDataOffset += uiSENLength;
			uiNumBytes -= uiSENLength;
		}
	}

	// Annotation
	if (ucExtFlags & NSF_EXT_ANNOTATION_BIT)
	{
		if (!uiNumBytes)
		{
			if (!ViewAddMenuItem( LBL_DOM_ANNOTATION_ID, uiLabelWidth,
					VAL_IS_LABEL_INDEX,
					LBL_NO_VALUE, 0,
					0, VIEW_INVALID_FILE_OFFSET,
					0, MOD_DISABLED,
					uiCol, uiRow++, 0, uiBackColor, uiForeColor,
					uiBackColor, uiForeColor))
			{
				goto Exit;
			}
		}
		else
		{
			pucTmp = pucData;
			uiSENLength = f_getSENLength( *pucTmp);
			if (uiNumBytes >= uiSENLength)
			{
				if( RC_BAD( rc = f_decodeSEN64( &pucTmp, 
					&pucTmp[ FLM_MAX_NUM_BUF_SIZE], &ui64Value)))
				{
					goto Exit;
				}
	
				if (!ViewAddMenuItem( LBL_DOM_ANNOTATION_ID, uiLabelWidth,
						VAL_IS_NUMBER | DISP_HEX_DECIMAL,
						ui64Value, 0,
						FSGetFileNumber( pStateInfo->ui32BlkAddress),
						FSGetFileOffset( pStateInfo->ui32BlkAddress) + uiDataOffset,
						0, MOD_SEN9 | MOD_HEX,
						uiCol, uiRow++, 0,
						uiBackColor, uiForeColor,
						uiBackColor, uiForeColor))
				{
					goto Exit;
				}
			}
			else
			{
				// If we can't display the number, at least display what we have left.
				if (!OutputHexValue( uiCol, &uiRow,
							uiBackColor, uiForeColor, LBL_DOM_ANNOTATION_ID,
							FSGetFileNumber( pStateInfo->ui32BlkAddress),
							FSGetFileOffset( pStateInfo->ui32BlkAddress) + uiDataOffset,
							pucData, uiNumBytes, FALSE))
				{
					goto Exit;
				}
				uiSENLength = uiNumBytes;
			}
			pucData += uiSENLength;
			uiDataOffset += uiSENLength;
			uiNumBytes -= uiSENLength;
		}
	}

	if (uiNumBytes)
	{
		// Output whatever is left as a HEX dump.
		if (!OutputHexValue( uiCol, &uiRow,
					uiBackColor, uiForeColor, LBL_DOM_VALUE,
					FSGetFileNumber( pStateInfo->ui32BlkAddress),
					FSGetFileOffset( pStateInfo->ui32BlkAddress) +
						uiDataOffset,
					pucData, uiNumBytes, FALSE))
		{
			goto Exit;
		}
	}

	bOk = TRUE;

Exit:

	*puiRow = uiRow;

	return( bOk);
}


/***************************************************************************
Desc:	This routine outputs the elements in a LEAF block.
*****************************************************************************/
FSTATIC FLMBOOL OutputLeafElements(
	FLMUINT				uiCol,
	FLMUINT *			puiRow,
	F_BTREE_BLK_HDR *	pBlkHdr,
	BLK_EXP_p			pBlkExp,
	FLMBYTE *			pucBlkStatus,
	FLMBOOL				bStatusOnlyFlag
	)
{
// VISIT:	There are a number of places throughout that have been commentd out
//				that have to do with the block status.  Currently, the pucBlkStatus
//				flag is not being updated in a meaningful way.  Need to investigate
//				what this is used for and find a way to make it meaningful.
	FLMBOOL		bOk = FALSE;
	FLMUINT		uiLabelWidth = 30;
	eColorType	uiBackColor = FLM_BLACK;
	eColorType	uiForeColor = FLM_LIGHTGRAY;
	eColorType	uiUnselectBackColor = FLM_BLACK;
	eColorType	uiUnselectForeColor = FLM_WHITE;
	eColorType	uiSelectBackColor = FLM_BLUE;
	eColorType	uiSelectForeColor = FLM_WHITE;
	FLMUINT		uiRow = *puiRow;
	FLMUINT		uiElementCount = 0;
	FLMINT		iErrorCode;
//	LFileType	eLfType = LF_INVALID;
	FLMBYTE		ucElmStatus [NUM_STATUS_BYTES];
	STATE_INFO	StateInfo;
//	LF_HDR_p		pLogicalFile = NULL;
	FLMUINT		uiCurOffset;
	FLMUINT16 *	pui16OffsetArray;
	FLMUINT		uiOption;
	FLMBOOL		bHasData = (pBlkHdr->stdBlkHdr.ui8BlkType == BT_LEAF_DATA);

	if (pBlkExp->uiLfNum == 0)
	{
		pBlkExp->uiLfNum = (FLMUINT)pBlkHdr->ui16LogicalFile;
	}

	// Setup the STATE variable for processing through the block

	(void)ViewGetDictInfo();

#if 0
	if ((iErrorCode = flmVerifyBlockHeader( &StateInfo,
														 &BlockInfo,
														 (FLMUINT)gv_ViewDbHdr.ui16BlockSize,
														 pBlkExp->uiNextAddr,
														 pBlkExp->uiPrevAddr,
														 (FLMBOOL)(StateInfo.pDb != NULL
															 ? TRUE
															 : FALSE))) != 0)
	{
		SetStatusBit( pucBlkStatus, iErrorCode);
	}
#endif
	uiCurOffset = 0;
	pui16OffsetArray = (FLMUINT16 *)((FLMBYTE *)pBlkHdr + sizeofBTreeBlkHdr( pBlkHdr));

	// Read through the elements in the block

	while( uiCurOffset <= (FLMUINT)(pBlkHdr->ui16NumKeys - 1))
	{
		InitStatusBits( ucElmStatus);
		uiElementCount++;
		GetElmInfo( (FLMBYTE *)pBlkHdr + pui16OffsetArray[ uiCurOffset], pBlkHdr, &StateInfo);
		iErrorCode = 0;  // ??

#if 0
		if ((iErrorCode = flmVerifyElement( &StateInfo,
										FO_DO_EXTENDED_DATA_CHECK)) != 0)
		{
			SetStatusBit( ucElmStatus, iErrorCode);
		}
		else if (eLfType == XFLM_LF_INDEX)
		{
			if (StateInfo.uiCurKeyLen)
			{
				if (RC_BAD( flmVerifyIXRefs( &StateInfo, NULL, 0,
									&iErrorCode)) || iErrorCode != 0)
				{
					SetStatusBit( ucElmStatus, iErrorCode);
				}
			}
		}
#endif

		// Output the element

		if (!bStatusOnlyFlag)
		{
			uiRow++;

			// Output the element number

			if (!ViewAddMenuItem( LBL_ELEMENT_NUMBER, uiLabelWidth,
					VAL_IS_NUMBER | DISP_DECIMAL,
					(FLMUINT64)uiElementCount, 0,
					0,
					VIEW_INVALID_FILE_OFFSET,
					0, MOD_DISABLED,
					uiCol, uiRow++, 0,
					FLM_GREEN, FLM_WHITE,
					FLM_GREEN, FLM_WHITE))
			{
				goto Exit;
			}

			// Remember this item if we are searching
#if 0
			if ((gv_bViewSearching) &&
					(flmCompareKeys( StateInfo.pucCurKey, StateInfo.uiCurKeyLen,
													gv_ucViewSearchKey,
													gv_uiViewSearchKeyLen) >= 0) &&
					(gv_pViewSearchItem == NULL))
			{
				gv_pViewSearchItem = gv_pViewMenuLastItem;
			}
#endif
			// Output the element offset within the block

			if (!ViewAddMenuItem( LBL_ELEMENT_OFFSET, uiLabelWidth,
						VAL_IS_NUMBER | DISP_DECIMAL,
						(FLMUINT64)StateInfo.uiElmOffset, 0,
						FSGetFileNumber( StateInfo.ui32BlkAddress),
						FSGetFileOffset( StateInfo.ui32BlkAddress) + StateInfo.uiElmOffset,
						0, MOD_DISABLED,
						uiCol, uiRow++, 0, uiBackColor, uiForeColor,
						uiBackColor, uiForeColor))
			{
				goto Exit;
			}

			// Output the element length

			if (!ViewAddMenuItem( LBL_ELEMENT_LENGTH, uiLabelWidth,
						VAL_IS_NUMBER | DISP_DECIMAL,
						(FLMUINT64)StateInfo.uiElmLen, 0,
						FSGetFileNumber( StateInfo.ui32BlkAddress),
						FSGetFileOffset( StateInfo.ui32BlkAddress) + StateInfo.uiElmOffset,
						0, MOD_DISABLED,
						uiCol, uiRow++, 0, uiBackColor, uiForeColor,
						uiBackColor, uiForeColor))
			{
				goto Exit;
			}

			// Display the first element flag if present
			if (bHasData)
			{

				if (!ViewAddMenuItem( LBL_FIRST_ELEMENT_FLAG, uiLabelWidth,
						VAL_IS_LABEL_INDEX,
						(bteFirstElementFlag( StateInfo.pucElm)
						? (FLMUINT64)LBL_YES
						: (FLMUINT64)LBL_NO), 0,
						FSGetFileNumber( StateInfo.ui32BlkAddress),
						FSGetFileOffset( StateInfo.ui32BlkAddress) + StateInfo.uiElmOffset,
						0x80, MOD_BITS | MOD_DECIMAL,
						uiCol, uiRow++, 0, uiBackColor, uiForeColor,
						uiBackColor, uiForeColor))
				{
					goto Exit;
				}

				// Display the last element flag

				if (!ViewAddMenuItem( LBL_LAST_ELEMENT_FLAG, uiLabelWidth,
							VAL_IS_LABEL_INDEX,
							(bteLastElementFlag( StateInfo.pucElm)
							? (FLMUINT64)LBL_YES
							: (FLMUINT64)LBL_NO), 0,
							FSGetFileNumber( StateInfo.ui32BlkAddress),
							FSGetFileOffset( StateInfo.ui32BlkAddress) + StateInfo.uiElmOffset,
							0x40, MOD_BITS | MOD_DECIMAL,
							uiCol, uiRow++, 0, uiBackColor, uiForeColor,
							uiBackColor, uiForeColor))
				{
					goto Exit;
				}

				// Display the Data Only flag

				if (!ViewAddMenuItem( LBL_DATA_BLOCK_FLAG, uiLabelWidth,
							VAL_IS_LABEL_INDEX,
							(bteDataBlockFlag( StateInfo.pucElm)
							? (FLMUINT64)LBL_YES
							: (FLMUINT64)LBL_NO), 0,
							FSGetFileNumber( StateInfo.ui32BlkAddress),
							FSGetFileOffset( StateInfo.ui32BlkAddress) + StateInfo.uiElmOffset,
							0x40, MOD_BITS | MOD_DECIMAL,
							uiCol, uiRow++, 0, uiBackColor, uiForeColor,
							uiBackColor, uiForeColor))
				{
					goto Exit;
				}
			}

			// Display the key length

			if (!ViewAddMenuItem( LBL_KEY_LENGTH, uiLabelWidth,
						VAL_IS_NUMBER | DISP_DECIMAL,
						(FLMUINT64)StateInfo.uiElmKeyLen, 0,
						FSGetFileNumber( StateInfo.ui32BlkAddress),
						FSGetFileOffset( StateInfo.ui32BlkAddress) +
													StateInfo.uiElmKeyLenOffset,
						0, MOD_DECIMAL,
						uiCol, uiRow++, 0, uiBackColor, uiForeColor,
						uiBackColor, uiForeColor))
			{
				goto Exit;
			}

			// Output the current key portion, if any

			if (!OutputHexValue( uiCol, &uiRow,
						uiBackColor, uiForeColor, LBL_ELEMENT_KEY,
						FSGetFileNumber( StateInfo.ui32BlkAddress),
						FSGetFileOffset( StateInfo.ui32BlkAddress) +
														StateInfo.uiElmKeyOffset,
						StateInfo.pucElmKey, StateInfo.uiElmKeyLen,
						FALSE))
			{
				goto Exit;
			}



			// Display the data length

			if (bHasData)
			{
				// Output the overall data field (if present)
				if (bteOADataLenFlag( StateInfo.pucElm))
				{
					if (!ViewAddMenuItem( LBL_OA_DATA_LENGTH, uiLabelWidth,
							VAL_IS_NUMBER | DISP_DECIMAL,
							(FLMUINT64)StateInfo.uiElmOADataLen, 0,
							FSGetFileNumber( StateInfo.ui32BlkAddress),
							FSGetFileOffset( StateInfo.ui32BlkAddress) + 
														StateInfo.uiElmOADataLenOffset,
							0, MOD_FLMBYTE | MOD_DECIMAL,
							uiCol, uiRow++, 0, uiBackColor, uiForeColor,
							uiBackColor, uiForeColor))
					{
						goto Exit;
					}
				}

				if (!ViewAddMenuItem( LBL_DATA_LENGTH, uiLabelWidth,
						VAL_IS_NUMBER | DISP_DECIMAL,
						(FLMUINT64)StateInfo.uiElmDataLen, 0,
						FSGetFileNumber( StateInfo.ui32BlkAddress),
						FSGetFileOffset( StateInfo.ui32BlkAddress) + 
													StateInfo.uiElmDataLenOffset,
						0, MOD_FLMBYTE | MOD_DECIMAL,
						uiCol, uiRow++, 0, uiBackColor, uiForeColor,
						uiBackColor, uiForeColor))
				{
					goto Exit;
				}


				// Output the data portion
				// Check for a data only block.
				if ( bteDataBlockFlag( StateInfo.pucElm))
				{
					FLMUINT		uiTempAddress = FB2UD( StateInfo.pucElmData);
					if (uiTempAddress == 0)
					{
						uiOption = 0;
					}
					else
					{
						uiOption = BLK_OPTION_DATA_BLOCK | StateInfo.uiElmOffset;
					}
					if (!ViewAddMenuItem( LBL_DATA_BLOCK_ADDRESS, uiLabelWidth,
								VAL_IS_NUMBER | DISP_HEX_DECIMAL,
								(FLMUINT64)uiTempAddress, 0,
								FSGetFileNumber( StateInfo.ui32BlkAddress),
								FSGetFileOffset( StateInfo.ui32BlkAddress) +
									StateInfo.uiElmDataOffset, 
								0, MOD_DISABLED, uiCol, uiRow++, uiOption,
								(!uiOption ? uiBackColor : uiUnselectBackColor),
								(!uiOption ? uiForeColor : uiUnselectForeColor),
								(!uiOption ? uiBackColor : uiSelectBackColor),
								(!uiOption ? uiForeColor : uiSelectForeColor)))
					{
						goto Exit;
					}

				}
				else
				{
					if ( bteFirstElementFlag( StateInfo.pucElm) &&
						  !isIndexBlk((F_BTREE_BLK_HDR *)StateInfo.pBlkHdr))
					{
						if (!OutputDomNode( uiCol, &uiRow,
								uiBackColor, uiForeColor, 
								StateInfo.pucElmData + 1, &StateInfo))
						{
							goto Exit;
						}

					}
					else
					{

						if (!OutputHexValue( uiCol, &uiRow,
								uiBackColor, uiForeColor, LBL_DATA,
								FSGetFileNumber( StateInfo.ui32BlkAddress),
								FSGetFileOffset( StateInfo.ui32BlkAddress) +
									StateInfo.uiElmDataOffset,
								StateInfo.pucElmData, StateInfo.uiElmDataLen,
								FALSE))
						{
							goto Exit;
						}
					}
				}
			}
		}

		// Go to the next element
		uiCurOffset++;
		OrStatusBits( pucBlkStatus, ucElmStatus);
	}

	if (!bStatusOnlyFlag)
	{
		*puiRow = uiRow;

		// If we were searching and did not find a key, set it on the
		// last key found

		if (gv_bViewSearching && !gv_pViewSearchItem)
		{
			gv_pViewSearchItem = gv_pViewMenuLastItem;
			while (gv_pViewSearchItem &&
					 gv_pViewSearchItem->iLabelIndex != LBL_ELEMENT_NUMBER)
			{
				gv_pViewSearchItem = gv_pViewSearchItem->pPrevItem;
			}
		}
	}
	bOk = TRUE;

Exit:

	*puiRow = uiRow;

#if 0
	if (bStateInitialized && StateInfo.pRecord)
	{
		StateInfo.pRecord->release( &StateInfo.pRecord);
	}
#endif
	return( bOk);
}

/***************************************************************************
Desc:	This routine outputs the elements in a DATA-ONLY block.
*****************************************************************************/
FSTATIC FLMBOOL OutputDataOnlyElements(
	FLMUINT				uiCol,
	FLMUINT *			puiRow,
	F_BLK_HDR *			pBlkHdr,
	BLK_EXP_p,			//pBlkExp,
	FLMBYTE *,			//pucBlkStatus,
	FLMBOOL				bStatusOnlyFlag
	)
{
	FLMBOOL		bOk = FALSE;
	FLMUINT		uiLabelWidth = 30;
	eColorType	uiBackColor = FLM_BLACK;
	eColorType	uiForeColor = FLM_LIGHTGRAY;
	FLMUINT		uiRow = *puiRow;
	FLMINT		iErrorCode;
//	LFileType	eLfType = LF_INVALID;
	FLMBYTE		ucElmStatus [NUM_STATUS_BYTES];
	STATE_INFO	StateInfo;

	// Setup the STATE variable for processing through the block

	(void)ViewGetDictInfo();

#if 0
	if ((iErrorCode = flmVerifyBlockHeader( &StateInfo, &BlockInfo,
						(FLMUINT)gv_ViewDbHdr.ui16BlockSize,
												pBlkExp->uiNextAddr,
												pBlkExp->uiPrevAddr,
												(FLMBOOL)(StateInfo.pDb != NULL
															 ? TRUE
															 : FALSE))) != 0)
	{
		SetStatusBit( pucBlkStatus, iErrorCode);
	}
#endif

	// Read through the block

	InitStatusBits( ucElmStatus);
	
	GetElmInfo( (FLMBYTE *)pBlkHdr + SIZEOF_STD_BLK_HDR,
					(F_BTREE_BLK_HDR *)pBlkHdr, &StateInfo);
	
	iErrorCode = 0;  // ??

#if 0
	if ((iErrorCode = flmVerifyElement( &StateInfo,
									FO_DO_EXTENDED_DATA_CHECK)) != 0)
	{
		SetStatusBit( ucElmStatus, iErrorCode);
	}
	else if (eLfType == XFLM_LF_INDEX)
	{
		if (StateInfo.uiCurKeyLen)
		{
			if (RC_BAD( flmVerifyIXRefs( &StateInfo, NULL, 0,
								&iErrorCode)) || iErrorCode != 0)
			{
				SetStatusBit( ucElmStatus, iErrorCode);
			}
		}
	}
#endif

	// Output the element

	if (!bStatusOnlyFlag)
	{
		uiRow++;


		// Remember this item if we are searching
#if 0
		if ((gv_bViewSearching) &&
				(flmCompareKeys( StateInfo.pucCurKey, StateInfo.uiCurKeyLen,
												gv_ucViewSearchKey,
												gv_uiViewSearchKeyLen) >= 0) &&
				(gv_pViewSearchItem == NULL))
		{
			gv_pViewSearchItem = gv_pViewMenuLastItem;
		}
#endif

		// Output the element length

		if (!ViewAddMenuItem( LBL_ELEMENT_LENGTH, uiLabelWidth,
								VAL_IS_NUMBER | DISP_DECIMAL,
								(FLMUINT64)StateInfo.uiElmLen, 0,
								FSGetFileNumber( StateInfo.ui32BlkAddress),
								FSGetFileOffset( StateInfo.ui32BlkAddress) + 
									StateInfo.uiElmOffset,
								0, MOD_DISABLED,
								uiCol, uiRow++, 0, uiBackColor, uiForeColor,
								uiBackColor, uiForeColor))
		{
			goto Exit;
		}


		// Display the key length if there is a key...
		if ( StateInfo.uiElmKeyLen)
		{
			if (!ViewAddMenuItem( LBL_KEY_LENGTH, uiLabelWidth,
						VAL_IS_NUMBER | DISP_DECIMAL,
						(FLMUINT64)StateInfo.uiElmKeyLen, 0,
						FSGetFileNumber( StateInfo.ui32BlkAddress),
						FSGetFileOffset( StateInfo.ui32BlkAddress) + 
							StateInfo.uiElmKeyOffset, 0,
						MOD_DECIMAL,
						uiCol, uiRow++, 0, uiBackColor, uiForeColor,
						uiBackColor, uiForeColor))
			{
				goto Exit;
			}

			// Output the key portion

			if (!OutputHexValue( uiCol, &uiRow,
						uiBackColor, uiForeColor, LBL_ELEMENT_KEY,
						FSGetFileNumber( StateInfo.ui32BlkAddress),
						FSGetFileOffset( StateInfo.ui32BlkAddress) +
							StateInfo.uiElmKeyOffset,
						StateInfo.pucElmKey, StateInfo.uiElmKeyLen,
						FALSE))
			{
				goto Exit;
			}
		}

		// Display the data length

		if (!ViewAddMenuItem( LBL_DATA_LENGTH, uiLabelWidth,
				VAL_IS_NUMBER | DISP_DECIMAL,
				(FLMUINT64)StateInfo.uiElmDataLen, 0,
				FSGetFileNumber( StateInfo.ui32BlkAddress),
				FSGetFileOffset( StateInfo.ui32BlkAddress) + 
					StateInfo.uiElmDataLenOffset,
				0,
				MOD_FLMBYTE | MOD_DECIMAL,
				uiCol, uiRow++, 0, uiBackColor, uiForeColor,
				uiBackColor, uiForeColor))
		{
			goto Exit;
		}

		// Output the data portion.
		if (!OutputHexValue( uiCol, &uiRow,
				uiBackColor, uiForeColor, LBL_DATA,
				FSGetFileNumber( StateInfo.ui32BlkAddress),
				FSGetFileOffset( StateInfo.ui32BlkAddress) +
					StateInfo.uiElmDataOffset,
				StateInfo.pucElmData, StateInfo.uiElmDataLen,
				FALSE))
		{
			goto Exit;
		}
	}


	if (!bStatusOnlyFlag)
	{
		*puiRow = uiRow;

		// If we were searching and did not find a key, set it on the
		// last key found

		if (gv_bViewSearching && !gv_pViewSearchItem)
		{
			gv_pViewSearchItem = gv_pViewMenuLastItem;
			while (gv_pViewSearchItem &&
					 gv_pViewSearchItem->iLabelIndex != LBL_ELEMENT_NUMBER)
			{
				gv_pViewSearchItem = gv_pViewSearchItem->pPrevItem;
			}
		}
	}
	bOk = TRUE;

Exit:

	return( bOk);
}


/***************************************************************************
Desc:	This routine outputs a LEAF block, including the block header.
*****************************************************************************/
FLMBOOL ViewLeafBlk(
	FLMUINT			uiReadAddress,
	FLMUINT			uiBlkAddress,
	F_BLK_HDR **	ppBlkHdr,
	BLK_EXP_p		pBlkExp
	)
{
	FLMBOOL			bOk = FALSE;
	FLMUINT			uiRow;
	FLMUINT			uiCol;
	F_BLK_HDR *		pBlkHdr;
	FLMBYTE			ucBlkStatus [NUM_STATUS_BYTES];
	FLMUINT32		ui32CalcCRC;
	FLMUINT32		ui32BlkCRC;
	FLMUINT			uiBytesRead;

	InitStatusBits( ucBlkStatus);

	// Read the block into memory

	if (!ViewBlkRead( uiReadAddress, ppBlkHdr, TRUE,
							(FLMUINT)gv_ViewDbHdr.ui16BlockSize,
							&ui32CalcCRC, &ui32BlkCRC,
							&uiBytesRead, TRUE))
	{
		goto Exit;
	}
	pBlkHdr = *ppBlkHdr;

	ViewMenuInit( "LEAF Block");

	// Output the block header first

	uiRow = 0;
	uiCol = 5;
	pBlkExp->uiType = pBlkHdr->ui8BlkType;
	pBlkExp->uiBlkAddr = uiBlkAddress;
	pBlkExp->uiLevel = 0;

	OutputLeafElements( uiCol, &uiRow, (F_BTREE_BLK_HDR *)pBlkHdr,
								pBlkExp, ucBlkStatus, TRUE);
	if (!ViewOutBlkHdr( uiCol, &uiRow, pBlkHdr, pBlkExp, ucBlkStatus,
								ui32CalcCRC, ui32BlkCRC))
	{
		goto Exit;
	}

	// Now output the leaf data

	if (!OutputLeafElements( uiCol, &uiRow, (F_BTREE_BLK_HDR *)pBlkHdr,
							pBlkExp, ucBlkStatus, FALSE))
	{
		goto Exit;
	}
	bOk = TRUE;

Exit:

	return( bOk);
}

/***************************************************************************
Desc:	This routine outputs a Data Only block, including the block header.
*****************************************************************************/
FLMBOOL ViewDataBlk(
	FLMUINT			uiReadAddress,
	FLMUINT			uiBlkAddress,
	F_BLK_HDR **	ppBlkHdr,
	BLK_EXP_p		pBlkExp
	)
{
	FLMBOOL			bOk = FALSE;
	FLMUINT			uiRow;
	FLMUINT			uiCol;
	F_BLK_HDR *		pBlkHdr;
	FLMBYTE			ucBlkStatus [NUM_STATUS_BYTES];
	FLMUINT32		ui32CalcCRC;
	FLMUINT32		ui32BlkCRC;
	FLMUINT			uiBytesRead;

	InitStatusBits( ucBlkStatus);

	// Read the block into memory

	if (!ViewBlkRead( uiReadAddress, ppBlkHdr, TRUE,
							(FLMUINT)gv_ViewDbHdr.ui16BlockSize,
							&ui32CalcCRC, &ui32BlkCRC,
							&uiBytesRead, TRUE))
	{
		goto Exit;
	}
	pBlkHdr = *ppBlkHdr;

	ViewMenuInit( "DATA Block");

	// Output the block header first

	uiRow = 0;
	uiCol = 5;
	pBlkExp->uiType = pBlkHdr->ui8BlkType;
	pBlkExp->uiBlkAddr = uiBlkAddress;
	pBlkExp->uiLevel = 0;

	OutputDataOnlyElements( uiCol, &uiRow, pBlkHdr,
								pBlkExp, ucBlkStatus, TRUE);
	if (!ViewOutBlkHdr( uiCol, &uiRow, pBlkHdr, pBlkExp, ucBlkStatus,
								ui32CalcCRC, ui32BlkCRC))
	{
		goto Exit;
	}

	// Now output the leaf data

	if (!OutputDataOnlyElements( uiCol, &uiRow, pBlkHdr,
							pBlkExp, ucBlkStatus, FALSE))
	{
		goto Exit;
	}
	bOk = TRUE;

Exit:

	return( bOk);
}


/***************************************************************************
Desc:	This routine outputs the elements of a NON-LEAF block.
*****************************************************************************/
FSTATIC FLMBOOL OutputNonLeafElements(
	FLMUINT					uiCol,
	FLMUINT *				puiRow,
	F_BTREE_BLK_HDR *		pBlkHdr,
	BLK_EXP_p				pBlkExp,
	FLMBYTE *				pucBlkStatus,
	FLMBOOL					bStatusOnlyFlag
	)
{
	FLMBOOL		bOk = FALSE;
	FLMUINT		uiLabelWidth = 30;
	eColorType	uiBackColor = FLM_BLACK;
	eColorType	uiForeColor = FLM_LIGHTGRAY;
	eColorType	uiUnselectBackColor = FLM_BLACK;
	eColorType	uiUnselectForeColor = FLM_WHITE;
	eColorType	uiSelectBackColor = FLM_BLUE;
	eColorType	uiSelectForeColor = FLM_WHITE;
	FLMUINT		uiRow = *puiRow;
	FLMUINT		uiElementCount = 0;
//	FLMBYTE *	pucTmpAddr;
	FLMUINT		uiTempAddress;
	FLMUINT		iErrorCode=0;
	FLMUINT		uiOption;
	eLFileType	eLfType;
	FLMUINT		uiBlkType = (FLMUINT)pBlkHdr->stdBlkHdr.ui8BlkType;
	FLMBYTE		ucElmStatus [NUM_STATUS_BYTES];
	STATE_INFO	StateInfo;
//	FLMBOOL		bStateInitialized = FALSE;
//	BLOCK_INFO	BlockInfo;
//	FLMBYTE		ucKeyBuffer [MAX_KEY_SIZ];
//	LF_HDR		LogicalFile;
	LF_HDR *		pLogicalFile = NULL;
//	LFILE_p		pLFile = NULL;
//	FLMUINT		uiFixedDrn;
	FLMUINT16 *	pui16OffsetArray;
	FLMUINT		uiCurOffset;

	if (pBlkExp->uiLfNum == 0)
	{
		pBlkExp->uiLfNum = (FLMUINT)pBlkHdr->ui16LogicalFile;
	}

	pui16OffsetArray = (FLMUINT16 *)((FLMBYTE *)pBlkHdr + sizeofBTreeBlkHdr( pBlkHdr));
	uiCurOffset = 0;

	// Setup the STATE variable for processing through the block

	(void)ViewGetDictInfo();

#if 0
	if (gv_bViewHaveDictInfo)
	{
		F_Dict *	pDict = gv_hViewDb->pDict;

		if (isContainerBlk( pBlkHdr))
		{
			if (RC_OK( pDict->getContainer( pBlkExp->uiLfNum, &pLFile)))
			{
				f_memset( &LogicalFile, 0, sizeof( LF_HDR));
				pLogicalFile = &LogicalFile;
				LogicalFile.pLFile = pLFile;
			}
		}
		else
		{
			IXD *	pIxd;

			if (RC_OK( pDict->getIndex( pBlkExp->uiLfNum, &pLFile, &pIxd)))
			{
				f_memset( &LogicalFile, 0, sizeof( LF_HDR));
				pLogicalFile = &LogicalFile;
				LogicalFile.pLFile = pLFile;
				LogicalFile.pIxd = pIxd;
				LogicalFile.pIfd = pIxd->pFirstIfd;
			}
		}
	}
#endif

	eLfType = (pLogicalFile) ? pLogicalFile->eLfType : XFLM_LF_INVALID;

#if 0
	flmInitReadState( &StateInfo, &bStateInitialized,
							(FLMUINT)gv_ViewDbHdr.ui32DbVersion,
							(gv_bViewDbInitialized)
							? gv_hViewDb
							: NULL,
							pLogicalFile, pBlkExp->uiLevel,
							uiBlkType, ucKeyBuffer);

	if ((iErrorCode = flmVerifyBlockHeader( &StateInfo, &BlockInfo,
						(FLMUINT)gv_ViewDbHdr.ui16BlockSize,
												pBlkExp->uiNextAddr,
												pBlkExp->uiPrevAddr,
												(FLMBOOL)(StateInfo.pDb != NULL
															 ? TRUE
															 : FALSE))) != 0)
	{
		SetStatusBit( pucBlkStatus, iErrorCode);
	}
#endif

	// Output each element in the block

	while (uiCurOffset <= (FLMUINT)(pBlkHdr->ui16NumKeys - 1))
	{
		InitStatusBits( ucElmStatus);
		uiElementCount++;
		GetElmInfo( (FLMBYTE *)pBlkHdr +
										pui16OffsetArray[ uiCurOffset],
						pBlkHdr, &StateInfo);
/*
		if ((iErrorCode = flmVerifyElement( &StateInfo,
									FO_DO_EXTENDED_DATA_CHECK)) != 0)
		{
			SetStatusBit( ucElmStatus, iErrorCode);
		}
*/
		if (!bStatusOnlyFlag)
		{
			uiRow++;

			// Output the element number

			if (!ViewAddMenuItem( LBL_ELEMENT_NUMBER, uiLabelWidth,
						VAL_IS_NUMBER | DISP_DECIMAL,
						(FLMUINT64)uiElementCount, 0,
						0,
						VIEW_INVALID_FILE_OFFSET,
						0, MOD_DISABLED,
						uiCol, uiRow++, 0,
						FLM_GREEN, FLM_WHITE,
						FLM_GREEN, FLM_WHITE))
			{
				goto Exit;
			}

			// Output the element offset within the block

			if (!ViewAddMenuItem( LBL_ELEMENT_OFFSET, uiLabelWidth,
						VAL_IS_NUMBER | DISP_DECIMAL,
						(FLMUINT64)StateInfo.uiElmOffset, 0,
						FSGetFileNumber( StateInfo.ui32BlkAddress),
						FSGetFileOffset( StateInfo.ui32BlkAddress) + 
								StateInfo.uiElmOffset,
						0, MOD_DISABLED,
						uiCol, uiRow++, 0, uiBackColor, uiForeColor,
						uiBackColor, uiForeColor))
			{
				goto Exit;
			}

			// Output the element length

			if (!ViewAddMenuItem( LBL_ELEMENT_LENGTH, uiLabelWidth,
						VAL_IS_NUMBER | DISP_DECIMAL,
						(FLMUINT64)StateInfo.uiElmLen, 0,
						FSGetFileNumber( StateInfo.ui32BlkAddress),
						FSGetFileOffset( StateInfo.ui32BlkAddress) + 
							StateInfo.uiElmOffset,
						0, MOD_DISABLED,
						uiCol, uiRow++, 0, uiBackColor, uiForeColor,
						uiBackColor, uiForeColor))
			{
				goto Exit;
			}

			// Display the child block address

			uiTempAddress = FB2UD( StateInfo.pucElm);
			if (uiTempAddress == 0)
			{
				uiOption = 0;
			}
			else
			{
				uiOption = BLK_OPTION_CHILD_BLOCK | StateInfo.uiElmOffset;
			}
			if (!ViewAddMenuItem( LBL_CHILD_BLOCK_ADDRESS, uiLabelWidth,
						VAL_IS_NUMBER | DISP_HEX_DECIMAL,
						(FLMUINT64)uiTempAddress, 0,
						FSGetFileNumber( StateInfo.ui32BlkAddress),
						FSGetFileOffset( StateInfo.ui32BlkAddress) +
																StateInfo.uiElmOffset,
						0, MOD_CHILD_BLK, uiCol, uiRow++, uiOption,
						(!uiOption ? uiBackColor : uiUnselectBackColor),
						(!uiOption ? uiForeColor : uiUnselectForeColor),
						(!uiOption ? uiBackColor : uiSelectBackColor),
						(!uiOption ? uiForeColor : uiSelectForeColor)))
			{
				goto Exit;
			}

			// Display the counts info if any.
			if (uiBlkType == BT_NON_LEAF_COUNTS)
			{
				if (!ViewAddMenuItem( LBL_CHILD_REFERENCE_COUNT, uiLabelWidth,
							VAL_IS_NUMBER,
							(FLMUINT64) StateInfo.uiElmCounts, 0,
							FSGetFileNumber( StateInfo.ui32BlkAddress),
							FSGetFileOffset( StateInfo.ui32BlkAddress) +
								StateInfo.uiElmCountsOffset,
							0, MOD_FLMUINT32 | MOD_DECIMAL,
							uiCol, uiRow++, uiOption, uiBackColor, uiForeColor,
							uiBackColor, uiForeColor))
				{
					goto Exit;
				}
			}

			// Remember this item if we are searching
#if 0
			if (gv_bViewSearching &&
				 flmCompareKeys( StateInfo.pucCurKey, StateInfo.uiCurKeyLen,
											gv_ucViewSearchKey, gv_uiViewSearchKeyLen) >= 0 &&
				 !gv_pViewSearchItem)
			{
				gv_pViewSearchItem = gv_pViewMenuLastItem;
			}
#endif
			if (iErrorCode != 0)
			{
				if (!OutputStatus( uiCol, &uiRow, uiBackColor, uiForeColor,
							uiLabelWidth, LBL_ELEMENT_STATUS, ucElmStatus))
				{
					goto Exit;
				}
			}

			// Display the key length

			if (!ViewAddMenuItem( LBL_KEY_LENGTH, uiLabelWidth,
					VAL_IS_NUMBER | DISP_DECIMAL,
					(FLMUINT64)StateInfo.uiElmKeyLen, 0,
					FSGetFileNumber( StateInfo.ui32BlkAddress),
					FSGetFileOffset( StateInfo.ui32BlkAddress) + 
						StateInfo.uiElmKeyLenOffset, 0,
					MOD_DECIMAL,
					uiCol, uiRow++, 0, uiBackColor, uiForeColor,
					uiBackColor, uiForeColor))
			{
				goto Exit;
			}

			// Output the key

			if (!OutputHexValue( uiCol, &uiRow,
					uiBackColor, uiForeColor, LBL_ELEMENT_KEY,
					FSGetFileNumber( StateInfo.ui32BlkAddress),
					FSGetFileOffset( StateInfo.ui32BlkAddress) + 
													StateInfo.uiElmKeyOffset,
					StateInfo.pucElmKey, StateInfo.uiElmKeyLen,
					FALSE))
			{
				goto Exit;
			}
		}

		// Go to the next element

		uiCurOffset++;
		OrStatusBits( pucBlkStatus, ucElmStatus);
	}

	if (!bStatusOnlyFlag)
	{
		*puiRow = uiRow;

		// If we were searching and did not find a key, set it on the
		// last key found

		if (gv_bViewSearching && !gv_pViewSearchItem)
		{
			gv_pViewSearchItem = gv_pViewMenuLastItem;
			while (gv_pViewSearchItem &&
					 gv_pViewSearchItem->iLabelIndex != LBL_CHILD_BLOCK_ADDRESS)
			{
				gv_pViewSearchItem = gv_pViewSearchItem->pPrevItem;
			}
		}
	}
	bOk = TRUE;

Exit:

#if 0
	if (bStateInitialized && StateInfo.pRecord)
	{
		StateInfo.pRecord->release( &StateInfo.pRecord);
	}
#endif
	return( bOk);
}

/***************************************************************************
Desc:	This routine outputs a NON-LEAF block, including the block header.
*****************************************************************************/
FLMBOOL ViewNonLeafBlk(
	FLMUINT			uiReadAddress,
	FLMUINT			uiBlkAddress,
	F_BLK_HDR **	ppBlkHdr,
	BLK_EXP_p		pBlkExp
	)
{
	FLMBOOL		bOk = FALSE;
	FLMUINT		uiRow;
	FLMUINT		uiCol;
	F_BLK_HDR *	pBlkHdr;
	FLMBYTE		ucBlkStatus [NUM_STATUS_BYTES];
	FLMUINT32	ui32CalcCRC;
	FLMUINT32	ui32BlkCRC;
	FLMUINT		uiBytesRead;

	InitStatusBits( ucBlkStatus);

	// Read the block into memory

	if (!ViewBlkRead( uiReadAddress, ppBlkHdr, TRUE,
							(FLMUINT)gv_ViewDbHdr.ui16BlockSize,
							&ui32CalcCRC, &ui32BlkCRC,
							&uiBytesRead, TRUE))
	{
		goto Exit;
	}
	pBlkHdr = *ppBlkHdr;

	ViewMenuInit( "NON-LEAF Block");

	// Output the block header first

	uiRow = 0;
	uiCol = 5;
	pBlkExp->uiType = (FLMUINT)pBlkHdr->ui8BlkType;
	pBlkExp->uiBlkAddr = uiBlkAddress;
	OutputNonLeafElements( uiCol, &uiRow, (F_BTREE_BLK_HDR *)pBlkHdr,
									pBlkExp, ucBlkStatus, TRUE);
	if (!ViewOutBlkHdr( uiCol, &uiRow, pBlkHdr, pBlkExp, ucBlkStatus,
							ui32CalcCRC, ui32BlkCRC))
	{
		goto Exit;
	}

	// Now output the non-leaf data

	if (!OutputNonLeafElements( uiCol, &uiRow, (F_BTREE_BLK_HDR *)pBlkHdr,
						pBlkExp, ucBlkStatus, FALSE))
	{
		goto Exit;
	}
	bOk = TRUE;

Exit:

	return( bOk);
}

/********************************************************************
Desc:	View a block in HEX
*********************************************************************/
void ViewHexBlock(
	FLMUINT			uiReadAddress,
	F_BLK_HDR **	ppBlkHdr,
	FLMUINT			uiViewLen
	)
{
	FLMBYTE *	pucBlk;
	FLMUINT		uiRow = 0;
	FLMUINT		uiCol = 13;
	FLMUINT		uiBytesPerLine = MAX_HORIZ_SIZE( uiCol);
	FLMUINT		uiBytesProcessed = 0;
	FLMUINT		uiNumBytes;
	FLMUINT		uiFileOffset;
	FLMUINT		uiFileNumber;
	char			szTitle [80];
	FLMUINT		uiBytesRead;

	uiFileOffset = FSGetFileOffset( uiReadAddress);
	uiFileNumber = FSGetFileNumber( uiReadAddress);

	if (!ViewBlkRead( uiReadAddress, ppBlkHdr, uiViewLen, FALSE,
						NULL, NULL, &uiBytesRead, TRUE))
	{
		return;
	}
	pucBlk = (FLMBYTE *)(*ppBlkHdr);

	f_sprintf( szTitle, "HEX DISPLAY OF BLOCK %08X", (unsigned)uiReadAddress);
	ViewMenuInit( szTitle);

	while (uiBytesProcessed < uiViewLen)
	{
		if ((uiNumBytes = uiViewLen - uiBytesProcessed) > uiBytesPerLine)
		{
			uiNumBytes = uiBytesPerLine;
		}

		// Output the line

		if (!ViewAddMenuItem( -1, 0,
				VAL_IS_BINARY_HEX,
				(FLMUINT)pucBlk, uiNumBytes,
				uiFileNumber, uiFileOffset, uiNumBytes, MOD_BINARY,
				uiCol, uiRow++, 0,
				FLM_BLACK, FLM_LIGHTGRAY,
				FLM_BLACK, FLM_LIGHTGRAY))
		{
			return;
		}
		uiFileOffset += uiNumBytes;
		uiBytesProcessed += uiNumBytes;
		pucBlk += uiNumBytes;
	}
}

/***************************************************************************
Desc: This routine outputs a block in the database.  Depending on the
		type of block, it will call a different routine to display
		the block.  The routine then allows the user to press keys to
		navigate to other blocks in the database if desired.
*****************************************************************************/
void ViewBlocks(
	FLMUINT		uiReadAddress,
	FLMUINT		uiBlkAddress,
	BLK_EXP_p	pBlkExp
	)
{
	FLMUINT		uiOption;
	VIEW_INFO   SaveView;
	VIEW_INFO   DummySave;
	FLMBOOL		bRepaint = TRUE;
	F_BLK_HDR *	pBlkHdr = NULL;
	FLMUINT		uiBlkAddress2;
	BLK_EXP     BlkExp2;
	FLMBOOL		bSetExp = FALSE;
	FLMBOOL		bViewHexFlag = FALSE;
	FLMUINT		uiBytesRead;

	// Loop getting commands until hit the exit key

	if (!gv_bViewHdrRead)
	{
		ViewReadHdr();
	}
	gv_pViewSearchItem = NULL;
	ViewReset( &SaveView);
	while (!gv_bViewPoppingStack)
	{

		// Display the type of block expected

		if (bRepaint)
		{
			if (bViewHexFlag)
			{
				ViewHexBlock( uiReadAddress, &pBlkHdr,
											(FLMUINT)gv_ViewDbHdr.ui16BlockSize);
			}
			else
			{
Switch_Statement:
				switch (pBlkExp->uiType)
				{
					case BT_NON_LEAF_COUNTS:
					case BT_NON_LEAF:
						if (!ViewNonLeafBlk( uiReadAddress, uiBlkAddress,
																 &pBlkHdr, pBlkExp))
						{
							goto Exit;
						}
						break;
					case BT_LEAF:
					case BT_LEAF_DATA:
						if (!ViewLeafBlk( uiReadAddress, uiBlkAddress,
															&pBlkHdr, pBlkExp))
						{
							goto Exit;
						}
						break;
					case BT_DATA_ONLY:
						if (!ViewDataBlk( uiReadAddress, uiBlkAddress,
															&pBlkHdr, pBlkExp))
						{
							goto Exit;
						}
						break;
					case BT_FREE:
						if (!ViewAvailBlk( uiReadAddress, uiBlkAddress,
															 &pBlkHdr, pBlkExp))
						{
							goto Exit;
						}
						break;
					case BT_LFH_BLK:
						if (!ViewLFHBlk( uiReadAddress, uiBlkAddress,
														 &pBlkHdr, pBlkExp))
						{
							goto Exit;
						}
						break;
					case 0xFF:
						if (!ViewBlkRead( uiReadAddress, &pBlkHdr, TRUE,
										(FLMUINT)gv_ViewDbHdr.ui16BlockSize,
												NULL, NULL, &uiBytesRead, FALSE))
						{
							goto Exit;
						}
						else
						{
							pBlkExp->uiType = (FLMUINT)pBlkHdr->ui8BlkType;
							goto Switch_Statement;
						}
				}
			}
		}

		// See what the user wants to do next.

		if (bSetExp &&
			 (pBlkExp->uiType == BT_LEAF || 
			  pBlkExp->uiType == BT_NON_LEAF_COUNTS ||
			  pBlkExp->uiType == BT_NON_LEAF ||
			  pBlkExp->uiType == BT_LEAF_DATA))
		{
			pBlkExp->uiLfNum =
				(FLMUINT)(((F_BTREE_BLK_HDR *)pBlkHdr)->ui16LogicalFile);
			pBlkExp->uiLevel =
				(FLMUINT)(((F_BTREE_BLK_HDR *)pBlkHdr)->ui8BlkLevel);
		}
		bSetExp = FALSE;
		bRepaint = TRUE;
		if (gv_bViewSearching)
		{
			SetSearchTopBottom();
			if (pBlkExp->uiType == BT_LEAF ||
				 pBlkExp->uiType == BT_LEAF_DATA ||
				 !gv_pViewSearchItem)
			{
				gv_bViewSearching = FALSE;
				ViewEnable();
				uiOption = ViewGetMenuOption();
			}
			else
			{
				uiOption = gv_pViewSearchItem->uiOption;
			}
		}
		else
		{
			ViewEnable();
			uiOption = ViewGetMenuOption();
		}
		switch (uiOption)
		{
			case ESCAPE_OPTION:
				goto Exit;
			case PREV_BLOCK_OPTION:
				ViewReset( &DummySave);
				pBlkExp->uiNextAddr = uiBlkAddress;
				pBlkExp->uiPrevAddr = 0xFFFFFFFF;
				uiReadAddress = uiBlkAddress =
						(FLMUINT)pBlkHdr->ui32PrevBlkInChain;
				break;
			case NEXT_BLOCK_OPTION:
				ViewReset( &DummySave);
				pBlkExp->uiNextAddr = 0xFFFFFFFF;
				pBlkExp->uiPrevAddr = uiBlkAddress;
				uiReadAddress = uiBlkAddress =
						(FLMUINT)pBlkHdr->ui32NextBlkInChain;
				break;
			case PREV_BLOCK_IMAGE_OPTION:
				f_memcpy( &BlkExp2, pBlkExp, sizeof( BLK_EXP));
				BlkExp2.uiNextAddr = 0xFFFFFFFF;
				BlkExp2.uiPrevAddr = 0xFFFFFFFF;
				ViewBlocks( (FLMUINT)pBlkHdr->ui32PriorBlkImgAddr,
										uiBlkAddress, &BlkExp2);
				break;
			case GOTO_BLOCK_OPTION:
				if (GetBlockAddrType( &uiBlkAddress2))
				{
					ViewReset( &DummySave);
					uiReadAddress = uiBlkAddress = uiBlkAddress2;
					pBlkExp->uiType = 0xFF;
					pBlkExp->uiLevel = 0xFF;
					pBlkExp->uiNextAddr = 0xFFFFFFFF;
					pBlkExp->uiPrevAddr = 0xFFFFFFFF;
					pBlkExp->uiLfNum = 0;
					bSetExp = TRUE;
					if (uiBlkAddress < 2048)
					{
						bViewHexFlag = TRUE;
					}
				}
				else
				{
					bRepaint = FALSE;
				}
				break;
			case EDIT_OPTION:
			case EDIT_RAW_OPTION:
				if (!ViewEdit( (uiOption == EDIT_OPTION) ? TRUE : FALSE))
				{
					bRepaint = FALSE;
				}
				break;
			case HEX_OPTION:
				ViewDisable();
				bViewHexFlag = !bViewHexFlag;
				break;
			case SEARCH_OPTION:
				switch (pBlkHdr->ui8BlkType)
				{
					case BT_NON_LEAF_COUNTS:
					case BT_NON_LEAF:
					case BT_LEAF_DATA:
					case BT_LEAF:
						gv_uiViewSearchLfNum =
							(FLMUINT)(((F_BTREE_BLK_HDR *)pBlkHdr)->ui16LogicalFile);
						gv_uiViewSearchLfType =
							getBlkLfType( (F_BTREE_BLK_HDR *)pBlkHdr);
						if (ViewGetKey())
						{
							gv_bViewPoppingStack = TRUE;
						}
						break;
					case BT_LFH_BLK:
						{
							VIEW_MENU_ITEM_p  pMenuItem = gv_pViewMenuCurrItem;

							// Determine which logical file, if any we are pointing at

							while (pMenuItem &&
									 pMenuItem->iLabelIndex != LBL_LOGICAL_FILE_NAME)
							{
								pMenuItem = pMenuItem->pPrevItem;
							}
							if (pMenuItem)
							{
								while (pMenuItem &&
										 pMenuItem->iLabelIndex != LBL_LOGICAL_FILE_NUMBER)
								{
									pMenuItem = pMenuItem->pNextItem;
								}
							}
							if (pMenuItem)
							{
								FLMBYTE *	pszTmp;

								gv_uiViewSearchLfNum = (FLMUINT)pMenuItem->ui64Value;
								while (pMenuItem &&
										 pMenuItem->iLabelIndex != LBL_LOGICAL_FILE_TYPE)
								{
									pMenuItem = pMenuItem->pNextItem;
								}
								pszTmp = (FLMBYTE *)((FLMUINT)pMenuItem->ui64Value);
								if (f_stricmp( (const char *)pszTmp, COLLECTION_STRING) == 0)
								{
									gv_uiViewSearchLfType = XFLM_LF_COLLECTION;
								}
								else
								{
									gv_uiViewSearchLfType = XFLM_LF_INDEX;
								}
								if (ViewGetKey())
								{
									gv_bViewPoppingStack = TRUE;
								}
							}
							else
							{
								ViewShowError(
									"Position cursor to a logical file before searching");
							}
						}
						break;
					default:
						ViewShowError(
							"This block does not belong to a logical file - cannot search");
						break;
				}
				break;
			default:
				if (uiOption & LOGICAL_INDEX_OPTION)
				{
					ViewLogicalFile( (FLMUINT)(uiOption &
											(~(LOGICAL_INDEX_OPTION))), XFLM_LF_INDEX);
				}
				else if (uiOption & LOGICAL_CONTAINER_OPTION)
				{
					ViewLogicalFile( (FLMUINT)(uiOption &
											(~(LOGICAL_CONTAINER_OPTION))), XFLM_LF_COLLECTION);
				}
				else if (uiOption & LFH_OPTION_ROOT_BLOCK)
				{
					F_LF_HDR *	pLfHdr = (F_LF_HDR *)((FLMBYTE *)pBlkHdr +
																	SIZEOF_STD_BLK_HDR);
						
					pLfHdr += (uiOption & 0xFFFF);

					BlkExp2.uiLevel = 0xFF;
					BlkExp2.uiType = 0xFF;
					uiBlkAddress2 = (FLMUINT)pLfHdr->ui32RootBlkAddr;
					BlkExp2.uiLfNum = (FLMUINT)pLfHdr->ui32LfNumber;
					BlkExp2.uiNextAddr = BlkExp2.uiPrevAddr = 0;
					ViewBlocks( uiBlkAddress2, uiBlkAddress2, &BlkExp2);
				}
				else if (uiOption & BLK_OPTION_CHILD_BLOCK)
				{
					uiBlkAddress2 = (FLMUINT)gv_pViewMenuCurrItem->ui64Value;
					f_memcpy( &BlkExp2, pBlkExp, sizeof( BLK_EXP));
					BlkExp2.uiNextAddr = 0xFFFFFFFF;
					BlkExp2.uiPrevAddr = 0xFFFFFFFF;
					BlkExp2.uiLevel = 0xFF;
					BlkExp2.uiType = 0xFF;
					ViewBlocks( uiBlkAddress2, uiBlkAddress2, &BlkExp2);
				}
				else if (uiOption & BLK_OPTION_DATA_BLOCK)
				{
					uiBlkAddress2 = (FLMUINT)gv_pViewMenuCurrItem->ui64Value;
					f_memcpy( &BlkExp2, pBlkExp, sizeof( BLK_EXP));
					BlkExp2.uiNextAddr = 0xFFFFFFFF;
					BlkExp2.uiPrevAddr = 0xFFFFFFFF;
					BlkExp2.uiLevel = 0xFF;
					BlkExp2.uiType = 0xFF;
					ViewBlocks( uiBlkAddress2, uiBlkAddress2, &BlkExp2);
				}
				else
				{
					bRepaint = FALSE;
				}
				break;
		}
	}

Exit:

	f_free( &pBlkHdr);
	ViewRestore( &SaveView);
}

/********************************************************************
Desc:	Have user enter a block address.
*********************************************************************/
FLMBOOL GetBlockAddrType(
	FLMUINT *	puiBlkAddress
	)
{
	FLMBOOL	bGotAddress = FALSE;
	FLMBOOL	bBadDigit;
	char		szTempBuf [20];
	FLMUINT	uiLoop;
	FLMUINT	uiChar;
	FLMUINT	uiNumCols;
	FLMUINT	uiNumRows;

	f_conGetScreenSize( &uiNumCols, &uiNumRows);

	// Get the block address

	for (;;)
	{
		bBadDigit = FALSE;
		f_conSetBackFore( FLM_BLACK, FLM_WHITE);
		f_conClearScreen( 0, uiNumRows - 2);
		ViewAskInput( 
			"Enter Block Address (in hex): ", 
			szTempBuf, sizeof( szTempBuf));
		if (f_stricmp( szTempBuf, "\\") == 0 || !szTempBuf [0])
		{
			break;
		}
		uiLoop = 0;
		*puiBlkAddress = 0;
		while (szTempBuf [uiLoop] && uiLoop < 8)
		{
			(*puiBlkAddress) <<= 4;
			uiChar = (FLMUINT)szTempBuf [uiLoop];
			if (uiChar >= '0' && uiChar <= '9')
			{
				(*puiBlkAddress) += (FLMUINT)(uiChar - '0');
			}
			else if (uiChar >= 'a' && uiChar <= 'f')
			{
				(*puiBlkAddress) += (FLMUINT)(uiChar - 'a' + 10);
			}
			else if (uiChar >= 'A' && uiChar<= 'F')
			{
				(*puiBlkAddress) += (FLMUINT)(uiChar - 'A' + 10);
			}
			else
			{
				bBadDigit = TRUE;
				break;
			}
			uiLoop++;
		}
		if (bBadDigit)
		{
			ViewShowError( 
				"Illegal digit in number - must be hex digits");
		}
		else if (szTempBuf [uiLoop])
		{
			ViewShowError( "Too many characters in number");
		}
		else
		{
			bGotAddress = TRUE;
			break;
		}
	}

	f_conClearScreen( 0, uiNumRows - 2);
	ViewEscPrompt();
	return( bGotAddress);
}

/********************************************************************
Desc: ?
*********************************************************************/
FSTATIC void SetSearchTopBottom( void)
{
	if (!gv_pViewSearchItem)
	{
		gv_pViewMenuCurrItem = NULL;
		gv_uiViewMenuCurrItemNum = 0;
		gv_uiViewCurrFileOffset = 0;
		gv_uiViewCurrFileNumber = 0;
		gv_uiViewTopRow = 0;
	}
	else
	{
		gv_pViewMenuCurrItem = gv_pViewSearchItem;
		gv_uiViewMenuCurrItemNum = gv_pViewSearchItem->uiItemNum;
		gv_uiViewCurrFileOffset = gv_pViewSearchItem->uiModFileOffset;
		gv_uiViewCurrFileNumber = gv_pViewSearchItem->uiModFileNumber;
		gv_uiViewTopRow = gv_pViewSearchItem->uiRow;
		if (gv_uiViewTopRow < LINES_PER_PAGE / 2)
		{
			gv_uiViewTopRow = 0;
		}
		else
		{
			gv_uiViewTopRow -= (LINES_PER_PAGE / 2);
		}
	}
	gv_uiViewBottomRow = gv_uiViewTopRow + LINES_PER_PAGE - 1;
	if (gv_uiViewBottomRow > gv_pViewMenuLastItem->uiRow)
	{
		gv_uiViewBottomRow = gv_pViewMenuLastItem->uiRow;
		if (gv_uiViewBottomRow < LINES_PER_PAGE)
		{
			gv_uiViewTopRow = 0;
		}
		else
		{
			gv_uiViewTopRow = gv_uiViewBottomRow - LINES_PER_PAGE + 1;
		}
	}
}

/*=============================================================================
Desc:
=============================================================================*/
FSTATIC void GetElmInfo(
	FLMBYTE *			pucEntry,
	F_BTREE_BLK_HDR *	pBlkHdr,
	STATE_INFO *		pStateInfo
	)
{
	F_NodeVerifier *		pNodeVerifier = pStateInfo->pNodeVerifier;
	
	f_memset( pStateInfo, 0, sizeof(STATE_INFO));

	pStateInfo->pNodeVerifier = pNodeVerifier;
	pStateInfo->pBlkHdr = (F_BLK_HDR *)pBlkHdr;
	pStateInfo->ui32BlkAddress = pBlkHdr->stdBlkHdr.ui32BlkAddr;
	pStateInfo->pucElm = pucEntry;
	pStateInfo->uiElmOffset = (FLMUINT)pucEntry - (FLMUINT)pBlkHdr;

	switch ( pBlkHdr->stdBlkHdr.ui8BlkType)
	{

		// Leaf node - no data.  Only element and key.
		case BT_LEAF:
		{
			pStateInfo->uiElmKeyLenOffset = pStateInfo->uiElmOffset; // No flags.
			pStateInfo->uiElmKeyLen = FB2UW( pucEntry);
			pStateInfo->uiElmLen = pStateInfo->uiElmKeyLen + 2;  // 2 byte key len
			pStateInfo->uiElmKeyOffset = pStateInfo->uiElmOffset + 2;	// ditto
			pStateInfo->pucElmKey = &pucEntry[ 2];  // Key
			break;
		}
		
		// Leaf node with data
		case BT_LEAF_DATA:
		{
			FLMBYTE		ucFlag;
			FLMBYTE *	pucTmp;
			FLMUINT		uiElmLen;

			pucTmp = &pucEntry[ 1];
			ucFlag = pucEntry[ 0];
			uiElmLen = 1;  // Flag

			pStateInfo->uiElmKeyLenOffset = (FLMUINT)pucTmp - (FLMUINT)pBlkHdr;
			
			if (bteKeyLenFlag( pucEntry))
			{
				uiElmLen += 2;
				pStateInfo->uiElmKeyLen = FB2UW( pucTmp);
				uiElmLen += pStateInfo->uiElmKeyLen;
				pucTmp += 2;
			}
			else
			{
				uiElmLen++;
				pStateInfo->uiElmKeyLen = *pucTmp;
				uiElmLen += pStateInfo->uiElmKeyLen;
				pucTmp++;
			}

			pStateInfo->uiElmDataLenOffset = (FLMUINT)pucTmp - (FLMUINT)pBlkHdr;

			if (bteDataLenFlag( pucEntry))
			{
				uiElmLen += 2;
				pStateInfo->uiElmDataLen = FB2UW( pucTmp);
				uiElmLen += pStateInfo->uiElmDataLen;
				pucTmp += 2;
			}
			else
			{
				uiElmLen++;
				pStateInfo->uiElmDataLen = *pucTmp;
				uiElmLen += pStateInfo->uiElmDataLen;
				pucTmp++;
			}
			
			if (bteOADataLenFlag( pucEntry))
			{
				pStateInfo->uiElmOADataLen = FB2UD( pucTmp);
				pStateInfo->uiElmOADataLenOffset = (FLMUINT)pucTmp - (FLMUINT)pBlkHdr;
				uiElmLen += 4; // Add the OA Data Length
				pucTmp += 4;  // Skip over the OA Data Length
			}
			// Save the key pointer...
			pStateInfo->pucElmKey = pucTmp;
			pStateInfo->uiElmKeyOffset = (FLMUINT)pucTmp - (FLMUINT)pBlkHdr;

			// Now the data
			pucTmp += pStateInfo->uiElmKeyLen;
			pStateInfo->pucElmData = pucTmp;
			pStateInfo->uiElmDataOffset = (FLMUINT)pucTmp - (FLMUINT)pBlkHdr;

			// The element length
			pStateInfo->uiElmLen = uiElmLen;
			break;
		}

		case BT_NON_LEAF:
		{
			FLMBYTE *	pucTmp = pucEntry;

			// Skip over the child block address for now.
			pucTmp += 4;
			
			// Get the key length & offset
			pStateInfo->uiElmKeyLen = FB2UW( pucTmp);
			pStateInfo->uiElmKeyLenOffset = (FLMUINT)pucTmp - (FLMUINT)pBlkHdr;
			
			// Get the key and offset
			pucTmp += 2;
			pStateInfo->pucElmKey = pucTmp;
			pStateInfo->uiElmKeyOffset = (FLMUINT)pucTmp - (FLMUINT)pBlkHdr;

			// The element length
			pStateInfo->uiElmLen = pStateInfo->uiElmKeyLen + 6;
			break;
		}

		case BT_NON_LEAF_COUNTS:
		{
			FLMBYTE *	pucTmp = pucEntry;
			
			// Skip over the child block address for now.
			pucTmp += 4;

			// Get the counts and offset
			pStateInfo->uiElmCounts = FB2UD( pucTmp);
			pStateInfo->uiElmCountsOffset = (FLMUINT)pucTmp - (FLMUINT)pBlkHdr;
			
			// Get the key length & offset
			pucTmp += 4;
			pStateInfo->uiElmKeyLen = FB2UW( pucTmp);
			pStateInfo->uiElmKeyLenOffset = (FLMUINT)pucTmp - (FLMUINT)pBlkHdr;
			
			// Get the key and offset
			pucTmp += 2;
			pStateInfo->pucElmKey = pucTmp;
			pStateInfo->uiElmKeyOffset = (FLMUINT)pucTmp - (FLMUINT)pBlkHdr;

			// The element length
			pStateInfo->uiElmLen = pStateInfo->uiElmKeyLen + 10;
			break;
		}

		case BT_DATA_ONLY:
		{
			FLMBYTE *		pucTmp = pucEntry;
			if (!pBlkHdr->stdBlkHdr.ui32PrevBlkInChain)
			{
				pStateInfo->uiElmKeyLen = (FLMUINT)FB2UW( pucTmp);
				pStateInfo->uiElmKeyLenOffset = (FLMUINT)pucTmp - (FLMUINT)pBlkHdr;
				pucTmp += 2;
				pStateInfo->pucElmKey = pucTmp;
				pStateInfo->uiElmKeyOffset = (FLMUINT)pucTmp - (FLMUINT)pBlkHdr;
				pucTmp += pStateInfo->uiElmKeyLen;
			}
			else
			{
				pStateInfo->uiElmKeyLen = 0;
			}
			pStateInfo->uiElmLen = gv_ViewDbHdr.ui16BlockSize - 
						  pBlkHdr->stdBlkHdr.ui16BlkBytesAvail;
			pStateInfo->uiElmDataLen = pStateInfo->uiElmLen -
												pStateInfo->uiElmKeyLen;
			pStateInfo->pucElmData = pucTmp +
				(pStateInfo->uiElmKeyLen ? pStateInfo->uiElmKeyLen + 2 : 0);

		}
	}
}

