Files
mars-flaim/xflaim/util/fdomedt.cpp

13464 lines
265 KiB
C++

//------------------------------------------------------------------------------
// Desc: DOM editor class
// Tabs: 3
//
// Copyright (c) 2003-2007 Novell, Inc. All Rights Reserved.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version 2.1
// of the License.
//
// This library 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
// Library Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; 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$
//------------------------------------------------------------------------------
#include "flaimsys.h"
#include "flm_lutl.h"
#include "domedit.h"
#include "fxpath.h"
static char * pszDomeditMonths [12] =
{
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
};
static char * pszDomeditFullMonthNames [12] =
{
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
};
FSTATIC FLMBOOL domeditIsNum(
const char * pszToken,
FLMUINT * puiNum);
FSTATIC char * domeditSkipChars(
const char * pszStr,
const char * pszCharsToSkip);
FSTATIC FLMBOOL domeditStrToDate(
const char * s,
FLMUINT * puiYear,
FLMUINT * puiMonth,
FLMUINT * puiDay);
FSTATIC void domGetOutputFileName(
FTX_WINDOW * pWindow,
char * pszOutputFileName,
FLMUINT uiOutputFileNameBufSize);
FSTATIC RCODE makeNewRow(
DME_ROW_INFO ** ppTmpRow,
FLMUNICODE * puzValue,
FLMUINT64 ui64Id,
FLMBOOL bUseValue = FALSE);
FSTATIC FLMUINT unicodeStrLen(
FLMUNICODE * puzStr);
FSTATIC void asciiToUnicode(
const char * pszAsciiString,
FLMUNICODE * puzString);
FSTATIC RCODE unicodeToAscii(
FLMUNICODE * puzString,
char * pszString,
FLMUINT uiLength);
FSTATIC RCODE formatText(
FLMUNICODE * puzBuf,
FLMBOOL bQuoted,
const char * pszPreText,
const char * pszPostText,
char ** ppszString);
FSTATIC RCODE formatDocumentNode(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pRow,
FLMUINT * puiNumVals,
FLMUINT uiFlags);
FSTATIC RCODE formatElementNode(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pRow,
FLMUINT * puiNumVals,
FLMUINT uiFlags);
FSTATIC RCODE formatAttributeNode(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pRow,
FLMUINT * puiNumVals,
FLMUINT uiFlags);
FSTATIC RCODE formatDataNode(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pRow,
FLMUINT * puiNumVals,
FLMUINT uiFlags,
const char * pszPreText,
const char * pszPostText);
FSTATIC RCODE formatProcessingInstruction(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pRow,
FLMUINT * puiNumVals,
FLMUINT uiFlags);
FSTATIC RCODE formatRow(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pRow,
FLMUINT * puiNumVals,
FLMUINT uiFlags);
FSTATIC RCODE formatIndexKeyNode(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pRow,
FLMUINT * puiNumVals);
FSTATIC void printNodeType(
DME_ROW_INFO * pRow,
FTX_WINDOW * pStatusWin);
FSTATIC void releaseRow(
DME_ROW_INFO ** ppRow);
FSTATIC RCODE getDOMNode(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pRow);
FSTATIC RCODE f_KeyEditorKeyHook(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pCurRow,
FLMUINT uiKeyIn,
FLMUINT * puiKeyOut,
void * pvKeyData);
FSTATIC RCODE f_QueryEditorKeyHook(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pCurRow,
FLMUINT uiKeyIn,
FLMUINT * puiKeyOut,
void * pvKeyData);
FSTATIC RCODE f_ViewOnlyKeyHook(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pCurRow,
FLMUINT uiKeyIn,
FLMUINT * puiKeyOut,
void * pvKeyData);
FSTATIC RCODE f_IndexRangeDispHook(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pRow,
FLMUINT * puiNumVals);
FSTATIC RCODE setupIndexRow(
F_DataVector * pKey,
FLMUINT uiElementNumber,
FLMUINT uiIndex,
FLMUINT uiFlag,
DME_ROW_INFO ** ppTmpRow);
RCODE _domEditBackgroundThread(
IF_Thread * pThread);
RCODE domEditVerifyRun( void);
extern FLMBOOL gv_bShutdown;
#define FLM_START_STATS
#define FLM_STOP_STATS
#define FLM_RESET_STATS
/****************************************************************************
Desc: Default constructor
*****************************************************************************/
F_DomEditor::F_DomEditor( void)
{
m_pEditWindow = NULL;
m_pEditStatusWin = NULL;
m_uiEditCanvasRows = 0;
m_bSetupCalled = FALSE;
m_pDisplayHook = (F_DOMEDIT_DISP_HOOK)F_DomEditorDefaultDispHook;
m_pNameTable = NULL;
m_DisplayData = 0;
m_pKeyHook = NULL;
m_KeyData = 0;
m_bMonochrome = FALSE;
m_pDb = NULL;
m_bOpenedDb = FALSE;
m_pRowAnchor = NULL;
m_pDocList = NULL;
m_pCurDoc = NULL;
m_pScrFirstRow = NULL;
m_pScrLastRow = NULL;
m_pCurRow = NULL;
reset();
}
/****************************************************************************
Desc: Destructor
*****************************************************************************/
F_DomEditor::~F_DomEditor( void)
{
DME_ROW_INFO * pTmpRow = m_pScrFirstRow;
DME_ROW_INFO * pDocList = m_pDocList;
if (m_bOpenedDb && m_pDb != NULL)
{
m_pDb->Release();
m_pDb = NULL;
}
if (m_pScrFirstRow)
{
releaseAllRows();
}
while (pDocList)
{
pTmpRow = pDocList->pNext;
if (pDocList->puzValue)
{
f_free( &pDocList->puzValue);
}
if (pDocList->pDomNode)
{
if (!(pDocList->uiFlags & F_DOMEDIT_FLAG_ENDTAG))
{
pDocList->pDomNode->Release();
}
else
{
pDocList->pDomNode = NULL;
}
}
f_free( &pDocList);
pDocList = pTmpRow;
}
reset();
}
/****************************************************************************
Desc: Prepares the editor for use
*****************************************************************************/
RCODE F_DomEditor::Setup(
FTX_SCREEN * pScreen)
{
RCODE rc = NE_XFLM_OK;
flmAssert( pScreen != NULL);
m_pScreen = pScreen;
m_bSetupCalled = TRUE;
return( rc);
}
/****************************************************************************
Desc: Reset the DOMEditor object
*****************************************************************************/
void F_DomEditor::reset( void)
{
m_pScrFirstRow = NULL;
m_pScrLastRow = NULL;
m_pCurRow = NULL;
if (m_bOpenedDb && m_pDb != NULL)
{
m_pDb->Release();
}
m_bOpenedDb = FALSE;
m_pDb = NULL;
m_uiCollection = XFLM_DATA_COLLECTION;
m_szTitle[ 0] = '\0';
m_bReadOnly = FALSE;
m_pbShutdown = NULL;
m_pParent = NULL;
m_uiCurRow = 0;
m_uiEditCanvasRows = 0;
m_pHelpHook = NULL;
m_pEventHook = NULL;
m_bDocList = FALSE;
m_uiLastKey = 0;
m_uiULX = 0;
m_uiULY = 0;
m_uiLRX = 0;
m_uiLRY = 0;
m_uiNumRows = 0;
if( m_pRowAnchor)
{
f_free( &m_pRowAnchor);
}
m_pDocList = NULL;
m_pCurDoc = NULL;
if (m_pNameTable)
{
m_pNameTable->Release();
m_pNameTable = NULL;
}
}
/****************************************************************************
Name: insertRecord
Desc:
*****************************************************************************/
RCODE F_DomEditor::insertRow(
DME_ROW_INFO * pRow,
DME_ROW_INFO * pStartRow)
{
RCODE rc = NE_XFLM_OK;
flmAssert( m_bSetupCalled == TRUE);
if( RC_BAD( rc = _insertRow( pRow, pStartRow)))
{
goto Exit;
}
Exit:
return( rc);
}
/****************************************************************************
Desc: _insertRow
*****************************************************************************/
RCODE F_DomEditor::_insertRow(
DME_ROW_INFO * pRow,
DME_ROW_INFO * pStartRow)
{
DME_ROW_INFO * pTmpRow = NULL;
RCODE rc = NE_XFLM_OK;
flmAssert( m_bSetupCalled == TRUE);
if( m_pEventHook)
{
if( RC_BAD( rc = m_pEventHook( this, F_DOMEDIT_EVENT_RECINSERT,
(void *)(pRow), m_EventData)))
{
goto Exit;
}
}
if( !m_pScrFirstRow)
{
m_pScrFirstRow = pRow;
m_pCurRow = m_pScrFirstRow;
m_uiNumRows = 1;
}
else
{
if (pStartRow)
{
pTmpRow = pStartRow->pNext;
pStartRow->pNext = pRow;
}
else
{
pTmpRow = m_pScrFirstRow;
}
pRow->pNext = pTmpRow;
pRow->pPrev = pStartRow;
if (pTmpRow)
{
pTmpRow->pPrev = pRow;
}
if (!pStartRow)
{
m_pScrFirstRow = pRow;
}
m_uiNumRows++;
}
// Adjust the last display row if needed.
if ( m_uiNumRows == 1)
{
m_pScrLastRow = m_pScrFirstRow;
}
else
{
while (m_pScrLastRow->pNext)
{
m_pScrLastRow = m_pScrLastRow->pNext;
}
}
Exit:
return( rc);
}
/****************************************************************************
Name: setTitle
Desc:
*****************************************************************************/
RCODE F_DomEditor::setTitle(
const char * pszTitle)
{
RCODE rc = NE_XFLM_OK;
eColorType uiBack;
eColorType uiFore;
flmAssert( m_bSetupCalled == TRUE);
m_szTitle[ 0] = ' ';
f_strncpy( &m_szTitle[ 1], pszTitle, F_DOMEDIT_MAX_TITLE_SIZE - 2);
f_strcat( m_szTitle, " ");
m_szTitle[ F_DOMEDIT_MAX_TITLE_SIZE] = '\0';
if (m_pEditWindow)
{
uiBack = m_bMonochrome ? FLM_BLACK : FLM_BLUE;
uiFore = FLM_WHITE;
FTXWinSetTitle( m_pEditWindow, m_szTitle, uiBack, uiFore);
}
return( rc);
}
/****************************************************************************
Desc: Set the default source Collection...
*****************************************************************************/
RCODE F_DomEditor::setSource(
F_Db * pDb,
FLMUINT uiCollection)
{
RCODE rc = NE_XFLM_OK;
flmAssert( m_bSetupCalled == TRUE);
if (m_bOpenedDb && m_pDb != NULL && pDb != m_pDb)
{
m_pDb->Release();
m_bOpenedDb = FALSE;
}
if (m_pDb != pDb)
{
if (m_pDb)
{
m_pDb->Release();
}
m_pDb = pDb;
}
m_pDb->AddRef();
if (pDb)
{
m_bOpenedDb = TRUE;
}
m_uiCollection = uiCollection;
return( rc);
}
/****************************************************************************
Desc: QueryStatus class.
*****************************************************************************/
class EditQueryStatus : public IF_QueryStatus
{
public:
#define LABEL_WIDTH 30
#define LABEL_COLUMN 2
#define DATA_COLUMN (LABEL_COLUMN + LABEL_WIDTH + 1)
#define QUERY_LINE 2
#define SOURCE_LINE (QUERY_LINE + 1)
#define USING_LINE (SOURCE_LINE + 1)
#define COST_LINE (USING_LINE + 1)
#define VERIFY_LINE (COST_LINE + 1)
#define NODE_MATCH_LINE (VERIFY_LINE + 1)
#define CAN_COMPARE_KEY_LINE (NODE_MATCH_LINE + 1)
#define KEYS_READ_LINE (CAN_COMPARE_KEY_LINE + 1)
#define DUP_KEYS_LINE (KEYS_READ_LINE + 1)
#define KEYS_PASSED_LINE (DUP_KEYS_LINE + 1)
#define NODES_READ_LINE (KEYS_PASSED_LINE + 1)
#define NODES_TESTED_LINE (NODES_READ_LINE + 1)
#define NODES_PASSED_LINE (NODES_TESTED_LINE + 1)
#define DOCUMENTS_READ_LINE (NODES_PASSED_LINE + 1)
#define DOCUMENTS_DUP_LINE (DOCUMENTS_READ_LINE + 1)
#define NODES_FAILED_VAL_LINE (DOCUMENTS_DUP_LINE + 1)
#define DOCS_FAILED_VAL_LINE (NODES_FAILED_VAL_LINE + 1)
#define DOCUMENTS_PASSED_LINE (DOCS_FAILED_VAL_LINE + 1)
#define TOT_DOCS_READ_LINE (DOCUMENTS_PASSED_LINE + 2)
#define TOT_DOCS_PASSED_LINE (TOT_DOCS_READ_LINE + 1)
#define CAN_RETRIEVE_DOCS_LINE (TOT_DOCS_PASSED_LINE + 1)
#define MESSAGE_LINE (CAN_RETRIEVE_DOCS_LINE + 2)
EditQueryStatus()
{
m_pWindow = NULL;
m_uiSourceCnt = 0;
m_pszQuery = NULL;
f_memset( &m_optInfo, 0, sizeof( XFLM_OPT_INFO));
m_ui64TotalDocsRead = 0;
m_ui64TotalDocsPassed = 0;
m_bCanRetrieveDocs = FALSE;
m_bKeepResults = TRUE;
}
virtual ~EditQueryStatus()
{
if (m_pWindow)
{
FTXWinFree( &m_pWindow);
}
if (m_pszQuery)
{
f_free( &m_pszQuery);
}
}
RCODE XFLAPI queryStatus(
XFLM_OPT_INFO * pOptInfo);
RCODE XFLAPI newSource(
XFLM_OPT_INFO * pOptInfo);
RCODE XFLAPI resultSetStatus(
FLMUINT64 ui64TotalDocsRead,
FLMUINT64 ui64TotalDocsPassed,
FLMBOOL bCanRetrieveDocs);
RCODE XFLAPI resultSetComplete(
FLMUINT64 ui64TotalDocsRead,
FLMUINT64 ui64TotalDocsPassed);
void createQueryStatusWindow(
FTX_SCREEN * pScreen,
eColorType uiBack,
eColorType uiFore,
char * pszQuery);
RCODE testEscape(
FLMUINT uiSourceCnt,
FLMUINT * puiChar);
FINLINE FLMBOOL keepResults( void)
{
return( m_bKeepResults);
}
void refreshStatus(
FLMBOOL bRefreshAll,
FLMUINT uiSource,
FLMUINT uiSourceCnt,
XFLM_OPT_INFO * pOptInfo);
void refreshResultSetStatus(
FLMBOOL bRefreshAll,
FLMUINT64 ui64TotalDocsRead,
FLMUINT64 ui64TotalDocsPassed,
FLMBOOL bCanRetrieveDocs);
FINLINE FLMINT XFLAPI getRefCount( void)
{
return( IF_QueryStatus::getRefCount());
}
virtual FINLINE FLMINT XFLAPI AddRef( void)
{
return( IF_QueryStatus::AddRef());
}
virtual FINLINE FLMINT XFLAPI Release( void)
{
return( IF_QueryStatus::Release());
}
private:
void outputLabel(
FLMUINT uiRow,
const char * pszLabel);
void outputStr(
FLMUINT uiRow,
const char * pszValue);
FINLINE void outputBool(
FLMUINT uiRow,
FLMBOOL bBool)
{
outputStr( uiRow, (char *)(bBool ? (char *)"YES" : (char *)"NO"));
}
void outputUINT(
FLMUINT uiRow,
FLMUINT uiValue);
void outputUINT64(
FLMUINT uiRow,
FLMUINT64 ui64Value);
FTX_WINDOW * m_pWindow;
FLMUINT m_uiNumCols;
FLMUINT m_uiNumRows;
FLMUINT m_uiSourceCnt;
XFLM_OPT_INFO m_optInfo;
FLMUINT64 m_ui64TotalDocsRead;
FLMUINT64 m_ui64TotalDocsPassed;
FLMBOOL m_bCanRetrieveDocs;
char * m_pszQuery;
FLMBOOL m_bKeepResults;
};
/****************************************************************************
Desc: Displays a message window
*****************************************************************************/
void EditQueryStatus::createQueryStatusWindow(
FTX_SCREEN * pScreen,
eColorType uiBack,
eColorType uiFore,
char * pszQuery)
{
FLMBOOL bOk = FALSE;
FLMUINT uiNumCols;
FLMUINT uiNumRows;
FLMUINT uiQueryStrLen = f_strlen( pszQuery);
FTXScreenGetSize( pScreen, &uiNumCols, &uiNumRows);
m_uiNumCols = uiNumCols - 8;
m_uiNumRows = uiNumRows - 4;
if( RC_BAD( FTXWinInit( pScreen, m_uiNumCols, m_uiNumRows, &m_pWindow)))
{
goto Exit;
}
FTXWinSetScroll( m_pWindow, FALSE);
FTXWinSetCursorType( m_pWindow, FLM_CURSOR_INVISIBLE);
FTXWinSetBackFore( m_pWindow, uiBack, uiFore);
FTXWinClear( m_pWindow);
FTXWinDrawBorder( m_pWindow);
FTXWinMove( m_pWindow, (FLMUINT)((uiNumCols - m_uiNumCols) / 2),
(FLMUINT)((uiNumRows - m_uiNumRows) / 2));
FTXWinOpen( m_pWindow);
if (RC_BAD( f_alloc( uiQueryStrLen + 1, &m_pszQuery)))
{
goto Exit;
}
f_memcpy( m_pszQuery, pszQuery, uiQueryStrLen + 1);
if (uiQueryStrLen > m_uiNumCols - 2 - DATA_COLUMN)
{
m_pszQuery [m_uiNumCols - 2 - DATA_COLUMN] = 0;
}
FTXRefresh();
bOk = TRUE;
Exit:
if (!bOk && m_pWindow)
{
FTXWinFree( &m_pWindow);
}
}
/****************************************************************************
Desc: Output a label on the query status screen.
*****************************************************************************/
void EditQueryStatus::outputLabel(
FLMUINT uiRow,
const char * pszLabel
)
{
char szLabel [50];
FLMUINT uiStrLen = f_strlen( pszLabel);
f_memset( szLabel, '.', LABEL_WIDTH);
szLabel [LABEL_WIDTH] = ' ';
szLabel [LABEL_WIDTH + 1] = 0;
if (uiStrLen > LABEL_WIDTH)
{
uiStrLen = LABEL_WIDTH;
}
f_memcpy( szLabel, pszLabel, uiStrLen);
FTXWinSetCursorPos( m_pWindow, LABEL_COLUMN, uiRow);
FTXWinPrintf( m_pWindow, "%s", szLabel);
}
/****************************************************************************
Desc: Output a string value on the query status screen.
*****************************************************************************/
void EditQueryStatus::outputStr(
FLMUINT uiRow,
const char * pszValue
)
{
FTXWinSetCursorPos( m_pWindow, DATA_COLUMN, uiRow);
FTXWinPrintf( m_pWindow, "%s", pszValue);
FTXWinClearToEOL( m_pWindow);
}
/****************************************************************************
Desc: Output a FLMUINT value on the query status screen.
*****************************************************************************/
void EditQueryStatus::outputUINT(
FLMUINT uiRow,
FLMUINT uiValue
)
{
char szValue [20];
f_sprintf( szValue, "%,u", (unsigned)uiValue);
outputStr( uiRow, szValue);
}
/****************************************************************************
Desc: Output a FLMUINT64 value on the query status screen.
*****************************************************************************/
void EditQueryStatus::outputUINT64(
FLMUINT uiRow,
FLMUINT64 ui64Value
)
{
char szValue [60];
f_sprintf( szValue, "%,I64u", ui64Value);
outputStr( uiRow, szValue);
}
/****************************************************************************
Desc: Refresh query status screen
*****************************************************************************/
void EditQueryStatus::refreshStatus(
FLMBOOL bRefreshAll,
FLMUINT uiSource,
FLMUINT uiSourceCnt,
XFLM_OPT_INFO * pOptInfo)
{
char szTmp [60];
if (bRefreshAll)
{
f_memcpy( &m_optInfo, pOptInfo, sizeof( XFLM_OPT_INFO));
outputLabel( QUERY_LINE, "Query");
outputStr( QUERY_LINE, m_pszQuery);
outputLabel( SOURCE_LINE, "Source");
if (!uiSourceCnt)
{
outputUINT( SOURCE_LINE, uiSource);
}
else
{
f_sprintf( szTmp, "%u of %u", (unsigned)uiSource,
(unsigned)uiSourceCnt);
outputStr( SOURCE_LINE, szTmp);
}
outputLabel( COST_LINE, " Cost");
outputLabel( VERIFY_LINE, " Must Verify Path");
outputLabel( NODE_MATCH_LINE, " Do Node Match");
outputLabel( CAN_COMPARE_KEY_LINE, " Can Compare Key");
switch (m_optInfo.eOptType)
{
case XFLM_QOPT_USING_INDEX:
outputLabel( USING_LINE, "Using Index");
if (m_optInfo.szIxName [0])
{
FLMUINT uiStrLen = f_strlen( (const char *)m_optInfo.szIxName);
if (uiStrLen > m_uiNumCols - 2 - DATA_COLUMN)
{
m_optInfo.szIxName [m_uiNumCols - 2 - DATA_COLUMN] = 0;
}
outputStr( USING_LINE, (char *)m_optInfo.szIxName);
}
else
{
f_sprintf( szTmp, "#%u", (unsigned)m_optInfo.uiIxNum);
outputStr( USING_LINE, szTmp);
}
outputUINT( COST_LINE, m_optInfo.uiCost);
outputBool( VERIFY_LINE, m_optInfo.bMustVerifyPath);
outputBool( NODE_MATCH_LINE, m_optInfo.bDoNodeMatch);
outputBool( CAN_COMPARE_KEY_LINE, m_optInfo.bCanCompareOnKey);
break;
case XFLM_QOPT_FULL_COLLECTION_SCAN:
outputLabel( USING_LINE, "Using");
outputStr( USING_LINE, "Collection Scan");
outputStr( COST_LINE, "N/A");
outputStr( VERIFY_LINE, "N/A");
outputStr( NODE_MATCH_LINE, "N/A");
outputStr( CAN_COMPARE_KEY_LINE, "N/A");
break;
case XFLM_QOPT_SINGLE_NODE_ID:
outputLabel( USING_LINE, "Using Node ID");
f_sprintf( szTmp, "#%I64u", m_optInfo.ui64NodeId);
outputStr( USING_LINE, szTmp);
outputUINT( COST_LINE, m_optInfo.uiCost);
outputBool( VERIFY_LINE, m_optInfo.bMustVerifyPath);
outputStr( NODE_MATCH_LINE, "N/A");
outputStr( CAN_COMPARE_KEY_LINE, "N/A");
break;
case XFLM_QOPT_NODE_ID_RANGE:
outputLabel( USING_LINE, "Using Node ID Range");
f_sprintf( szTmp, "#%I64u to %I64u", m_optInfo.ui64NodeId,
m_optInfo.ui64EndNodeId);
outputStr( USING_LINE, szTmp);
outputUINT( COST_LINE, m_optInfo.uiCost);
outputBool( VERIFY_LINE, m_optInfo.bMustVerifyPath);
outputStr( NODE_MATCH_LINE, "N/A");
outputStr( CAN_COMPARE_KEY_LINE, "N/A");
break;
default:
break;
}
outputLabel( KEYS_READ_LINE, "Keys Read");
outputLabel( DUP_KEYS_LINE, "Keys Elim By Dup Docs");
outputLabel( KEYS_PASSED_LINE, "Keys Passed");
outputLabel( NODES_READ_LINE, "Nodes Read");
outputLabel( NODES_TESTED_LINE, "Nodes Tested");
outputLabel( NODES_PASSED_LINE, "Nodes Passed");
outputLabel( DOCUMENTS_READ_LINE, "Documents Read");
outputLabel( DOCUMENTS_DUP_LINE, "Dup Docs Eliminated");
outputLabel( NODES_FAILED_VAL_LINE, "Nodes Failed Validation");
outputLabel( DOCS_FAILED_VAL_LINE, "Docs Failed Validation");
outputLabel( DOCUMENTS_PASSED_LINE, "Documents Passed");
refreshResultSetStatus( TRUE, m_ui64TotalDocsRead, m_ui64TotalDocsPassed,
m_bCanRetrieveDocs);
}
if (bRefreshAll || pOptInfo->ui64KeysRead != m_optInfo.ui64KeysRead)
{
m_optInfo.ui64KeysRead = pOptInfo->ui64KeysRead;
outputUINT64( KEYS_READ_LINE, m_optInfo.ui64KeysRead);
}
if (bRefreshAll || pOptInfo->ui64KeyHadDupDoc != m_optInfo.ui64KeyHadDupDoc)
{
m_optInfo.ui64KeyHadDupDoc = pOptInfo->ui64KeyHadDupDoc;
outputUINT64( DUP_KEYS_LINE, m_optInfo.ui64KeyHadDupDoc);
}
if (bRefreshAll || pOptInfo->ui64KeysPassed != m_optInfo.ui64KeysPassed)
{
m_optInfo.ui64KeysPassed = pOptInfo->ui64KeysPassed;
outputUINT64( KEYS_PASSED_LINE, m_optInfo.ui64KeysPassed);
}
if (bRefreshAll || pOptInfo->ui64NodesRead != m_optInfo.ui64NodesRead)
{
m_optInfo.ui64NodesRead = pOptInfo->ui64NodesRead;
outputUINT64( NODES_READ_LINE, m_optInfo.ui64NodesRead);
}
if (bRefreshAll || pOptInfo->ui64NodesTested != m_optInfo.ui64NodesTested)
{
m_optInfo.ui64NodesTested = pOptInfo->ui64NodesTested;
outputUINT64( NODES_TESTED_LINE, m_optInfo.ui64NodesTested);
}
if (bRefreshAll || pOptInfo->ui64NodesPassed != m_optInfo.ui64NodesPassed)
{
m_optInfo.ui64NodesPassed = pOptInfo->ui64NodesPassed;
outputUINT64( NODES_PASSED_LINE, m_optInfo.ui64NodesPassed);
}
if (bRefreshAll || pOptInfo->ui64DocsRead != m_optInfo.ui64DocsRead)
{
m_optInfo.ui64DocsRead = pOptInfo->ui64DocsRead;
outputUINT64( DOCUMENTS_READ_LINE, m_optInfo.ui64DocsRead);
}
if (bRefreshAll || pOptInfo->ui64DupDocsEliminated != m_optInfo.ui64DupDocsEliminated)
{
m_optInfo.ui64DupDocsEliminated = pOptInfo->ui64DupDocsEliminated;
outputUINT64( DOCUMENTS_DUP_LINE, m_optInfo.ui64DupDocsEliminated);
}
if (bRefreshAll || pOptInfo->ui64NodesFailedValidation != m_optInfo.ui64NodesFailedValidation)
{
m_optInfo.ui64NodesFailedValidation = pOptInfo->ui64NodesFailedValidation;
outputUINT64( NODES_FAILED_VAL_LINE, m_optInfo.ui64NodesFailedValidation);
}
if (bRefreshAll || pOptInfo->ui64DocsFailedValidation != m_optInfo.ui64DocsFailedValidation)
{
m_optInfo.ui64DocsFailedValidation = pOptInfo->ui64DocsFailedValidation;
outputUINT64( DOCS_FAILED_VAL_LINE, m_optInfo.ui64DocsFailedValidation);
}
if (bRefreshAll || pOptInfo->ui64DocsPassed != m_optInfo.ui64DocsPassed)
{
m_optInfo.ui64DocsPassed = pOptInfo->ui64DocsPassed;
outputUINT64( DOCUMENTS_PASSED_LINE, m_optInfo.ui64DocsPassed);
}
}
/****************************************************************************
Desc: Refresh query status screen
*****************************************************************************/
void EditQueryStatus::refreshResultSetStatus(
FLMBOOL bRefreshAll,
FLMUINT64 ui64TotalDocsRead,
FLMUINT64 ui64TotalDocsPassed,
FLMBOOL bCanRetrieveDocs)
{
if (bRefreshAll)
{
m_ui64TotalDocsRead = ui64TotalDocsRead;
m_ui64TotalDocsPassed = ui64TotalDocsPassed;
m_bCanRetrieveDocs = bCanRetrieveDocs;
outputLabel( TOT_DOCS_READ_LINE, "Total Docs Read");
outputLabel( TOT_DOCS_PASSED_LINE, "Total Docs Passed");
outputLabel( CAN_RETRIEVE_DOCS_LINE, "Can Retrieve Docs");
}
if (bRefreshAll || ui64TotalDocsRead != m_ui64TotalDocsRead)
{
m_ui64TotalDocsRead = ui64TotalDocsRead;
outputUINT64( TOT_DOCS_READ_LINE, m_ui64TotalDocsRead);
}
if (bRefreshAll || ui64TotalDocsPassed != m_ui64TotalDocsPassed)
{
m_ui64TotalDocsPassed = ui64TotalDocsPassed;
outputUINT64( TOT_DOCS_PASSED_LINE, m_ui64TotalDocsPassed);
}
if (bRefreshAll || bCanRetrieveDocs != m_bCanRetrieveDocs)
{
m_bCanRetrieveDocs = bCanRetrieveDocs;
outputUINT64( CAN_RETRIEVE_DOCS_LINE, m_bCanRetrieveDocs);
}
}
/****************************************************************************
Desc: See if user pressed escape
*****************************************************************************/
RCODE EditQueryStatus::testEscape(
FLMUINT uiSourceCnt,
FLMUINT * puiChar)
{
RCODE rc = NE_XFLM_OK;
if (m_pWindow)
{
if (uiSourceCnt)
{
FTXWinSetCursorPos( m_pWindow, LABEL_COLUMN, MESSAGE_LINE);
if (uiSourceCnt == 1)
{
FTXWinPrintf( m_pWindow, "Press any character to show query results: ");
}
else
{
FTXWinPrintf( m_pWindow, "N,P=Show Next/Prev Source, other=Show query results: ");
}
FTXWinInputChar( m_pWindow, puiChar);
}
else if( RC_OK( FTXWinTestKB( m_pWindow)))
{
FLMUINT uiChar;
FTXWinInputChar( m_pWindow, &uiChar);
if (uiChar == FKB_ESCAPE)
{
FTXWinSetCursorPos( m_pWindow, LABEL_COLUMN, MESSAGE_LINE);
FTXWinPrintf( m_pWindow,
"Escape pressed, exit? (Y=Show results, ESC=quit): ");
if( RC_BAD( FTXWinInputChar( m_pWindow, &uiChar)) ||
uiChar == FKB_ESCAPE)
{
rc = RC_SET( NE_XFLM_USER_ABORT);
m_bKeepResults = FALSE;
goto Exit;
}
else if (uiChar == 'Y' || uiChar == 'y')
{
rc = RC_SET( NE_XFLM_USER_ABORT);
goto Exit;
}
else
{
FTXWinSetCursorPos( m_pWindow, LABEL_COLUMN, MESSAGE_LINE);
FTXWinPrintf( m_pWindow,
" ");
}
}
}
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Query status callback
*****************************************************************************/
RCODE EditQueryStatus::queryStatus(
XFLM_OPT_INFO * pOptInfo)
{
RCODE rc = NE_XFLM_OK;
if (m_pWindow)
{
// See if the user pressed escape.
if (RC_BAD( rc = testEscape( 0, NULL)))
{
goto Exit;
}
// Update our statistics display
refreshStatus( FALSE, m_uiSourceCnt, 0, pOptInfo);
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Query status callback
*****************************************************************************/
RCODE EditQueryStatus::newSource(
XFLM_OPT_INFO * pOptInfo)
{
RCODE rc = NE_XFLM_OK;
if (m_pWindow)
{
// See if the user pressed escape.
if (RC_BAD( rc = testEscape( 0, NULL)))
{
goto Exit;
}
// Update our statistics display
m_uiSourceCnt++;
refreshStatus( TRUE, m_uiSourceCnt, 0, pOptInfo);
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Query status callback
*****************************************************************************/
RCODE XFLAPI EditQueryStatus::resultSetStatus(
FLMUINT64 ui64TotalDocsRead,
FLMUINT64 ui64TotalDocsPassed,
FLMBOOL bCanRetrieveDocs)
{
RCODE rc = NE_XFLM_OK;
if (m_pWindow)
{
// See if the user pressed escape.
if (RC_BAD( rc = testEscape( 0, NULL)))
{
goto Exit;
}
refreshResultSetStatus( FALSE, ui64TotalDocsRead, ui64TotalDocsPassed,
bCanRetrieveDocs);
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Query status callback
*****************************************************************************/
RCODE XFLAPI EditQueryStatus::resultSetComplete(
FLMUINT64 ui64TotalDocsRead,
FLMUINT64 ui64TotalDocsPassed)
{
RCODE rc = NE_XFLM_OK;
if (m_pWindow)
{
// See if the user pressed escape.
if (RC_BAD( rc = testEscape( 0, NULL)))
{
goto Exit;
}
refreshResultSetStatus( FALSE, ui64TotalDocsRead, ui64TotalDocsPassed,
TRUE);
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Interact with the user...
*****************************************************************************/
RCODE F_DomEditor::interactiveEdit(
FLMUINT uiULX,
FLMUINT uiULY,
FLMUINT uiLRX,
FLMUINT uiLRY,
FLMBOOL bBorder,
FLMUINT uiStatusLines,
FLMUINT uiStartChar)
{
DME_ROW_INFO * pTmpRow;
FLMBOOL bRefreshEditWindow = FALSE;
FLMBOOL bRefreshStatusWindow = FALSE;
FLMUINT uiNumRows = 0;
FLMUINT uiNumCols = 0;
FLMUINT uiMaxRow = 0;
FLMUINT uiStartCol = 0;
eDbTransType eTransType = XFLM_NO_TRANS;
FLMUINT uiLoop;
FLMUINT uiCurFlags = 0;
char szAction[ 2];
FLMUINT uiTermChar;
FLMUINT uiHelpKey = uiStartChar;
FLMBOOL bDoneEditing = FALSE;
RCODE rc = NE_XFLM_OK;
RCODE tmpRc = NE_XFLM_OK;
eColorType uiFore;
eColorType uiBack;
IF_Thread * pIxManagerThrd = NULL;
IF_Thread * pMemManagerThrd = NULL;
char * pszQuery = NULL;
FLMUINT uiSzQueryBufSize;
IF_ThreadMgr * pThreadMgr = NULL;
IF_DbSystem * pDbSystem = NULL;
flmAssert( m_bSetupCalled == TRUE);
flmAssert( m_pScreen != NULL);
m_uiCurRow = 0;
m_pScrFirstRow = NULL;
m_uiLastKey = 0;
uiSzQueryBufSize = 1024;
if (RC_BAD( rc = f_alloc( uiSzQueryBufSize, &pszQuery)))
{
goto Exit;
}
*pszQuery = 0;
if( RC_BAD( rc = FlmGetThreadMgr( &pThreadMgr)))
{
goto Exit;
}
if( RC_BAD( rc = FlmAllocDbSystem( &pDbSystem)))
{
goto Exit;
}
if( !m_pNameTable)
{
if( RC_BAD( rc = refreshNameTable()))
{
goto Exit;
}
}
if( !uiLRX && !uiLRY)
{
FTXScreenGetSize( m_pScreen, &uiNumCols, &uiNumRows);
uiNumRows -= uiULY;
uiNumCols -= uiULX;
}
else
{
uiNumRows = (uiLRY - uiULY) + 1;
uiNumCols = (uiLRX - uiULX) + 1;
}
uiStartCol = uiULX;
uiNumRows -= uiStatusLines; // Subtract however many lines are for the status area
m_uiULX = uiULX;
m_uiULY = uiULY;
m_uiLRX = uiLRX;
m_uiLRY = uiLRY;
if( RC_BAD( rc = FTXWinInit( m_pScreen, uiNumCols,
uiNumRows, &m_pEditWindow)))
{
goto Exit;
}
FTXWinMove( m_pEditWindow, uiStartCol, uiULY);
FTXWinSetScroll( m_pEditWindow, FALSE);
FTXWinSetLineWrap( m_pEditWindow, FALSE);
FTXWinSetCursorType( m_pEditWindow, FLM_CURSOR_INVISIBLE);
uiBack = m_bMonochrome ? FLM_BLACK : FLM_BLUE;
uiFore = FLM_WHITE;
FTXWinSetBackFore( m_pEditWindow, uiBack, uiFore);
FTXWinClear( m_pEditWindow);
if( bBorder)
{
FTXWinDrawBorder( m_pEditWindow);
}
FTXWinSetTitle( m_pEditWindow, m_szTitle, uiBack, uiFore);
if( uiStatusLines)
{
if( RC_BAD( rc = FTXWinInit( m_pScreen, uiNumCols, uiStatusLines,
&m_pEditStatusWin)))
{
goto Exit;
}
FTXWinMove( m_pEditStatusWin, uiULX, uiULY + uiNumRows);
FTXWinSetScroll( m_pEditStatusWin, FALSE);
FTXWinSetCursorType( m_pEditStatusWin, FLM_CURSOR_INVISIBLE);
FTXWinSetBackFore( m_pEditStatusWin,
m_bMonochrome ? FLM_BLACK : FLM_GREEN, FLM_WHITE);
FTXWinClear( m_pEditStatusWin);
FTXWinOpen( m_pEditStatusWin);
}
FTXWinOpen( m_pEditWindow);
FTXWinGetCanvasSize( m_pEditWindow, &uiNumCols, &uiNumRows);
m_uiEditCanvasRows = uiNumRows;
m_uiEditCanvasCols = uiNumCols;
uiMaxRow = uiNumRows - 1;
bRefreshEditWindow = TRUE;
bRefreshStatusWindow = TRUE;
if( m_pDb != NULL)
{
eTransType = m_pDb->getTransType();
}
/*
Call the callback to indicate that the interactive
editor has been invoked
*/
if( m_pEventHook)
{
m_pEventHook( this, F_DOMEDIT_EVENT_IEDIT,
0, m_EventData);
}
FTXRefresh();
while( !bDoneEditing && !isExiting())
{
if( bRefreshEditWindow)
{
/*
Refresh the edit window
*/
if( m_pParent)
{
m_bMonochrome = m_pParent->isMonochrome();
}
FTXWinPaintBackground( m_pEditWindow,
m_bMonochrome ? FLM_BLACK : FLM_BLUE);
if( m_pEventHook)
{
if( RC_BAD( rc = m_pEventHook( this, F_DOMEDIT_EVENT_REFRESH,
0, m_EventData)))
{
goto Exit;
}
}
refreshEditWindow( &m_pScrFirstRow, m_pCurRow, &m_uiCurRow);
FTXWinSetCursorPos( m_pEditWindow, 0, m_uiCurRow);
bRefreshEditWindow = FALSE;
bRefreshStatusWindow = TRUE;
}
if( m_pEditStatusWin && bRefreshStatusWindow)
{
/*
Update the status window
*/
FTXWinSetBackFore( m_pEditStatusWin,
m_bMonochrome ? FLM_LIGHTGRAY : FLM_GREEN,
m_bMonochrome ? FLM_BLACK : FLM_WHITE);
FTXWinSetCursorPos( m_pEditStatusWin, 0, 0);
getControlFlags( m_pCurRow, &uiCurFlags);
if( !(uiCurFlags & F_DOMEDIT_FLAG_LIST_ITEM))
{
switch( eTransType)
{
case XFLM_UPDATE_TRANS:
{
FTXWinPrintf( m_pEditStatusWin, " | UTRANS");
break;
}
case XFLM_READ_TRANS:
{
FTXWinPrintf( m_pEditStatusWin, " | RTRANS");
break;
}
default:
{
break;
}
}
}
if( m_pCurRow)
{
FLMUINT64 ui64DocId = m_pCurRow->ui64DocId;
FLMUINT64 ui64NodeId = m_pCurRow->ui64NodeId;
FLMUINT uiNameId = m_pCurRow->uiNameId;
if ( ui64NodeId || ui64DocId || uiNameId)
{
FTXWinPrintf( m_pEditStatusWin, "[");
if ( ui64DocId)
{
FTXWinPrintf( m_pEditStatusWin, "Doc:%,10I64u", ui64DocId);
if ( ui64NodeId || uiNameId)
{
FTXWinPrintf( m_pEditStatusWin, " / ");
}
}
if ( ui64NodeId)
{
FTXWinPrintf( m_pEditStatusWin, "Node:%,10I64u", ui64NodeId);
if ( uiNameId)
{
FTXWinPrintf( m_pEditStatusWin, " / ");
}
}
if ( uiNameId)
{
FTXWinPrintf( m_pEditStatusWin, "Name:%,13u", uiNameId);
}
FTXWinPrintf( m_pEditStatusWin, "]");
if ( ui64NodeId)
{
printNodeType( m_pCurRow, m_pEditStatusWin);
}
}
}
FTXWinClearToEOL( m_pEditStatusWin);
FTXRefresh();
bRefreshStatusWindow = FALSE;
}
if( uiHelpKey || RC_OK( FTXWinTestKB( m_pEditWindow)))
{
FLMUINT uiChar;
bRefreshEditWindow = TRUE;
if( uiHelpKey)
{
uiChar = uiHelpKey;
uiHelpKey = 0;
}
else
{
FTXWinInputChar( m_pEditWindow, &uiChar);
}
if( uiChar)
{
if( m_pKeyHook)
{
m_pKeyHook( this, m_pCurRow, uiChar, &uiChar, m_KeyData);
}
if (uiChar != FKB_TAB)
{
m_uiLastKey = uiChar;
}
}
if( uiChar == FKB_TAB)
{
// Grab the last keystroke that was passed to the editor.
// This is needed in environments where the ALT and
// control keys are not available and must be selected from
// the command list. Rather than requiring the user to
// re-select the command from the list each time, he/she can
// simply press the tab key to repeat the last keystroke.
uiChar = m_uiLastKey;
}
getControlFlags( m_pCurRow, &uiCurFlags);
switch( uiChar)
{
case 0:
{
/*
Key handled by the keyboard callback. Refresh the
edit window so that any changes made to the buffer by
the callback will be displayed.
*/
bRefreshEditWindow = TRUE;
break;
}
case FKB_ENTER:
{
if( !m_pCurRow)
{
break;
}
if( uiCurFlags & F_DOMEDIT_FLAG_LIST_ITEM)
{
setControlFlags( m_pCurRow,
uiCurFlags | F_DOMEDIT_FLAG_SELECTED);
bDoneEditing = TRUE;
}
else if( !canEditRow( m_pCurRow))
{
displayMessage( "The row cannot be edited",
RC_SET( NE_XFLM_ILLEGAL_OP), NULL, FLM_RED, FLM_WHITE);
}
else if( RC_BAD( tmpRc = editRow( m_uiCurRow, m_pCurRow)))
{
displayMessage( "The field could not be edited", tmpRc,
NULL, FLM_RED, FLM_WHITE);
}
bRefreshEditWindow = TRUE;
break;
}
case 'S':
case 's':
{
bRefreshEditWindow = TRUE;
break;
}
// Just view (edit without saving changes)
case 'V':
case 'v':
{
if( !m_pCurRow)
{
break;
}
if( RC_BAD( tmpRc = editRow( m_uiCurRow, m_pCurRow, TRUE)))
{
displayMessage( "The field could not be edited", tmpRc,
NULL, FLM_RED, FLM_WHITE);
}
bRefreshEditWindow = TRUE;
break;
}
// Expand the current row.
case FKB_RIGHT:
{
DME_ROW_INFO * pLastRow = NULL;
if (!m_pCurRow->bExpanded)
{
if (RC_BAD( tmpRc = expandRow( m_pCurRow, TRUE, &pLastRow)))
{
displayMessage( "Error expanding current row", tmpRc,
NULL, FLM_RED, FLM_WHITE);
break;
}
if (m_pCurRow->bExpanded)
{
if ((pLastRow == m_pCurRow) ||
(pLastRow->uiLevel != m_pCurRow->uiLevel))
{
// We need to mark the starting row since the expansion is
// incomplete.
if (m_pRowAnchor)
{
f_free( &m_pRowAnchor);
}
if( RC_BAD( rc = f_alloc( sizeof( DME_ROW_ANCHOR), &m_pRowAnchor)))
{
goto Exit;
}
f_memset( m_pRowAnchor, 0, sizeof(DME_ROW_ANCHOR));
m_pRowAnchor->ui64NodeId = m_pCurRow->ui64NodeId;
m_pRowAnchor->uiAnchorLevel = m_pCurRow->uiLevel;
m_pRowAnchor->bSingleLevel = TRUE;
}
}
bRefreshEditWindow = TRUE;
}
break;
}
// Expand the current row.
case FKB_PLUS:
{
DME_ROW_INFO * pLastRow = NULL;
if (!m_pCurRow->bExpanded)
{
if (RC_BAD( rc = expandRow( m_pCurRow, FALSE, &pLastRow)))
{
goto Exit;
}
if (m_pCurRow->bExpanded)
{
if ((pLastRow == NULL) ||
(pLastRow->uiLevel != m_pCurRow->uiLevel))
{
// We need to mark the starting row since the expansion is
// incomplete.
if (m_pRowAnchor)
{
f_free( &m_pRowAnchor);
}
if( RC_BAD( rc = f_alloc( sizeof( DME_ROW_ANCHOR), &m_pRowAnchor)))
{
goto Exit;
}
f_memset( m_pRowAnchor, 0, sizeof(DME_ROW_ANCHOR));
m_pRowAnchor->ui64NodeId = m_pCurRow->ui64NodeId;
m_pRowAnchor->uiAnchorLevel = m_pCurRow->uiLevel;
m_pRowAnchor->bSingleLevel = FALSE;
}
}
bRefreshEditWindow = TRUE;
}
break;
}
// Collapse the current row.
case FKB_LEFT:
case FKB_MINUS:
{
if (m_pCurRow->bExpanded)
{
if (RC_BAD( tmpRc = collapseRow( &m_pCurRow)))
{
displayMessage( "Error collapsing current row", tmpRc,
NULL, FLM_RED, FLM_WHITE);
break;
}
bRefreshEditWindow = TRUE;
}
break;
}
// Move field cursor to the next row
case FKB_DOWN:
{
if (RC_BAD( tmpRc = getNextRow( m_pCurRow,
&pTmpRow,
TRUE,
m_pCurRow ? !m_pCurRow->bExpanded : FALSE)))
{
displayMessage( "Failed to retrieve a new row.", tmpRc,
NULL, FLM_RED, FLM_WHITE);
break;
}
if (pTmpRow != NULL)
{
if( m_uiCurRow < uiMaxRow)
{
refreshRow( m_uiCurRow, m_pCurRow, FALSE);
m_uiCurRow++;
refreshRow( m_uiCurRow, pTmpRow, TRUE);
bRefreshStatusWindow = TRUE;
}
else
{
bRefreshEditWindow = TRUE;
}
m_pCurRow = pTmpRow;
checkDocument( &m_pCurDoc, m_pCurRow);
}
break;
}
// Move field cursor to the prior row
case FKB_UP:
{
if (RC_BAD( tmpRc = getPrevRow( m_pCurRow,
&pTmpRow,
TRUE)))
{
displayMessage( "Failed to retrieve a previous row.", tmpRc,
NULL, FLM_RED, FLM_WHITE);
break;
}
if( pTmpRow != NULL)
{
if( m_uiCurRow > 0)
{
refreshRow( m_uiCurRow, m_pCurRow, FALSE);
m_uiCurRow--;
refreshRow( m_uiCurRow, pTmpRow, TRUE);
bRefreshStatusWindow = TRUE;
}
else
{
bRefreshEditWindow = TRUE;
}
m_pCurRow = pTmpRow;
// Did we change to another document?
checkDocument( &m_pCurDoc, m_pCurRow);
}
break;
}
/*
Page up
*/
case FKB_PGUP:
{
for( uiLoop = 0; uiLoop < uiNumRows; uiLoop++)
{
if (RC_BAD( tmpRc = getPrevRow( m_pCurRow,
&pTmpRow,
TRUE)))
{
displayMessage( "Failed to retrieve a previous row.", tmpRc,
NULL, FLM_RED, FLM_WHITE);
break;;
}
if( pTmpRow != NULL)
{
m_pCurRow = pTmpRow;
// Did we change to another document?
checkDocument( &m_pCurDoc, m_pCurRow);
}
else
{
m_uiCurRow = 0;
break;
}
}
bRefreshEditWindow = TRUE;
break;
}
/*
Page down
*/
case FKB_PGDN:
{
FLMBOOL bIgnoreAnchor = !m_pCurRow->bExpanded;
for( uiLoop = 0; uiLoop < uiNumRows; uiLoop++)
{
if (RC_BAD( rc = getNextRow( m_pCurRow,
&pTmpRow,
TRUE,
bIgnoreAnchor)))
{
displayMessage( "Failed to retrieve a next row.", tmpRc,
NULL, FLM_RED, FLM_WHITE);
break;
}
if (pTmpRow != NULL)
{
m_pCurRow = pTmpRow;
checkDocument( &m_pCurDoc, m_pCurRow);
}
else
{
m_uiCurRow += uiLoop;
if( m_uiCurRow >= uiNumRows)
{
m_uiCurRow = uiNumRows - 1;
}
break;
}
bIgnoreAnchor = FALSE;
}
bRefreshEditWindow = TRUE;
break;
}
/*
Go to the top of the buffer
*/
#if 0 // Removed functionality
case FKB_HOME:
{
m_pCurRow = m_pScrFirstRow;
m_uiCurRow = 0;
bRefreshEditWindow = TRUE;
checkDocument( &m_pCurDoc, m_pCurRow);
break;
}
/*
Jump to the end of the buffer
*/
case FKB_END:
{
m_uiCurRow = uiMaxRow;
for( ;;)
{
if ( RC_BAD( rc = getNextRow( m_pCurRow, &pTmpRow, FALSE)))
{
goto Exit;
}
if (pTmpRow != NULL)
{
m_pCurRow = pTmpRow;
checkDocument( &m_pCurDoc, m_pCurRow);
}
else
{
break;
}
}
setCurrentAtBottom();
bRefreshEditWindow = TRUE;
break;
}
#endif
case FKB_END:
{
if( m_pEditStatusWin)
{
FTXWinSetCursorPos( m_pEditStatusWin, 0, 0);
FTXWinPrintf( m_pEditStatusWin,
"Scanning to the end of the display ...");
FTXWinClearToEOL( m_pEditStatusWin);
}
m_uiCurRow = uiMaxRow;
for( ;;)
{
if ( RC_BAD( tmpRc = getNextRow( m_pCurRow,
&pTmpRow,
TRUE)))
{
displayMessage( "Failed to retrieve a next row.", tmpRc,
NULL, FLM_RED, FLM_WHITE);
break;
}
if (pTmpRow != NULL)
{
m_pCurRow = pTmpRow;
// We need to check to see if we have moved to another document
checkDocument( &m_pCurDoc, m_pCurRow);
}
else
{
break;
}
}
setCurrentAtBottom();
bRefreshEditWindow = TRUE;
break;
}
/*
Jump to the top of the buffer
*/
case FKB_HOME:
{
if( m_pEditStatusWin)
{
FTXWinSetCursorPos( m_pEditStatusWin, 0, 0);
FTXWinPrintf( m_pEditStatusWin,
"Scanning to the beginning of the display ...");
FTXWinClearToEOL( m_pEditStatusWin);
}
m_uiCurRow = uiMaxRow;
for( ;;)
{
if ( RC_BAD( tmpRc = getPrevRow( m_pCurRow,
&pTmpRow,
TRUE)))
{
displayMessage( "Failed to retrieve a previous row.", tmpRc,
NULL, FLM_RED, FLM_WHITE);
break;
}
if (pTmpRow != NULL)
{
m_pCurRow = pTmpRow;
// We need to check to see if we have moved to another document
checkDocument( &m_pCurDoc, m_pCurRow);
}
else
{
m_pScrFirstRow = m_pCurRow;
break;
}
}
setCurrentAtTop();
bRefreshEditWindow = TRUE;
break;
}
// Add something
case 'N':
case 'n':
case FKB_ALT_A:
{
if (RC_BAD( tmpRc = addSomething( &m_pCurRow)))
{
displayMessage( "Add/Insert operation failed",
RC_SET( tmpRc), NULL, FLM_RED, FLM_WHITE);
break;
}
bRefreshEditWindow = TRUE;
break;
}
// Display attributes
case 'A':
case 'a':
{
if (RC_BAD( tmpRc = displayAttributes( m_pCurRow)))
{
displayMessage(
"Attributes could not be displayed",
RC_SET( tmpRc), NULL, FLM_RED, FLM_WHITE);
}
break;
}
// Display node informatoin
case 'D':
case 'd':
{
if (RC_BAD( tmpRc = displayNodeInfo( m_pCurRow)))
{
displayMessage(
"Node information could not be displayed",
RC_SET( tmpRc), NULL, FLM_RED, FLM_WHITE);
}
break;
}
case 'X':
case 'x':
{
if (RC_BAD( tmpRc = exportNode( m_pCurRow)))
{
displayMessage(
"Node could not be exported",
RC_SET( tmpRc), NULL, FLM_RED, FLM_WHITE);
}
break;
}
/*
Index operations
*/
case 'I':
case 'i':
case FKB_ALT_I:
{
if( m_pDb == NULL)
{
break;
}
if( RC_BAD( tmpRc = indexList()))
{
displayMessage( "Index List Operation Failed",
RC_SET(tmpRc),
NULL,
FLM_RED,
FLM_WHITE);
break;
}
bRefreshEditWindow = TRUE;
break;
}
/*
List all documents
*/
case 'L':
case 'l':
case FKB_ALT_L:
{
FLMUINT uiCollection = m_uiCollection;
FLMUINT64 ui64NodeId;
char szResponse[ 32];
DME_ROW_INFO * pDocList = m_pDocList;
szResponse [0] = 0;
if (!m_pDocList)
{
if( RC_BAD( tmpRc = selectCollection( &uiCollection,
&uiTermChar)))
{
displayMessage( "Error getting collection",
RC_SET(tmpRc),
NULL,
FLM_RED,
FLM_WHITE);
break;
}
if( uiTermChar != FKB_ENTER)
{
break;
}
m_uiCollection = uiCollection;
}
if( RC_BAD( tmpRc = retrieveDocumentList( uiCollection,
&ui64NodeId,
&uiTermChar)))
{
if( m_pEditStatusWin)
{
FTXWinClearLine( m_pEditStatusWin, 0, 0);
}
displayMessage( "Unable to retrieve document list",
RC_SET(tmpRc),
NULL,
FLM_RED,
FLM_WHITE);
break;
}
if( uiTermChar != FKB_ENTER)
{
break;
}
while ( pDocList && pDocList->ui64DocId != ui64NodeId)
{
pDocList = pDocList->pNext;
}
if (pDocList)
{
displayMessage( "Document already selected",
NE_XFLM_FAILURE,
NULL,
FLM_RED,
FLM_WHITE);
break;
}
// Retrieve the selected document
if( m_pEditStatusWin)
{
FTXWinSetCursorPos( m_pEditStatusWin, 0, 0);
FTXWinPrintf( m_pEditStatusWin,
"Retrieving selected document from the database ...");
FTXWinClearToEOL( m_pEditStatusWin);
}
if( RC_BAD( tmpRc = retrieveNodeFromDb( uiCollection, ui64NodeId, 0)))
{
if( m_pEditStatusWin)
{
FTXWinClearLine( m_pEditStatusWin, 0, 0);
}
displayMessage( "Unable to retrieve selected document",
RC_SET( tmpRc),
NULL,
FLM_RED,
FLM_WHITE);
break;
}
// Add the document to the document list.
if (RC_BAD( tmpRc = addDocumentToList( uiCollection, ui64NodeId)))
{
if ( m_pEditStatusWin)
{
FTXWinClearLine( m_pEditStatusWin, 0, 0);
}
displayMessage( "Unable to add document to document list",
RC_SET(tmpRc),
NULL,
FLM_RED,
FLM_WHITE);
break;
}
bRefreshEditWindow = TRUE;
break;
}
/*
Retrieve a node
*/
case 'R':
case 'r':
case FKB_ALT_R:
{
FLMUINT uiCollection;
char szResponse[ 32];
FLMUINT uiSrcLen;
FLMUINT uiNodeId;
FLMUINT64 ui64Tmp;
szResponse [0] = 0;
requestInput( "[READ] Node Number",
szResponse,
sizeof( szResponse),
&uiTermChar);
if( uiTermChar == FKB_ESCAPE)
{
break;
}
if( (uiSrcLen = (FLMUINT)f_strlen( szResponse)) == 0)
{
uiNodeId = 0;
}
else
{
if( RC_BAD( tmpRc = getNumber( szResponse, &ui64Tmp, NULL)))
{
displayMessage( "Invalid node number",
RC_SET( tmpRc),
NULL,
FLM_RED,
FLM_WHITE);
break;
}
uiNodeId = (FLMUINT)ui64Tmp;
}
if (!m_pDocList)
{
if( RC_BAD( tmpRc = selectCollection( &uiCollection,
&uiTermChar)))
{
displayMessage( "Error getting collection",
RC_SET(tmpRc),
NULL,
FLM_RED,
FLM_WHITE);
break;
}
if( uiTermChar != FKB_ENTER)
{
break;
}
m_uiCollection = uiCollection;
}
if( RC_BAD( tmpRc = retrieveNodeFromDb( uiCollection, uiNodeId, 0)))
{
if( m_pEditStatusWin)
{
FTXWinClearLine( m_pEditStatusWin, 0, 0);
}
displayMessage( "Unable to retrieve node",
RC_SET( tmpRc),
NULL,
FLM_RED,
FLM_WHITE);
break;
}
// VISIT: Check to see if this is a document, we can add it to the list.
bRefreshEditWindow = TRUE;
break;
}
/*
Retrieve nodes via XPATH
*/
case 'F':
case 'f':
case FKB_ALT_F:
doQuery( pszQuery, uiSzQueryBufSize);
break;
/*
Clear all records from the current editor buffer.
NOTE: This will discard all changes
*/
case 'C':
case 'c':
case FKB_ALT_C:
{
char szResponse[ 2];
szResponse [0] = 0;
requestInput(
"Clear buffer and discard modifications? (Y/N)",
szResponse, 2, &uiTermChar);
if( uiTermChar == FKB_ESCAPE)
{
break;
}
if( szResponse [0] == 'y' || szResponse [0] == 'Y')
{
setScrFirstRow( NULL);
if (RC_BAD( rc = setCurrentRow(NULL, 0)))
{
goto Exit;
}
bRefreshEditWindow = TRUE;
}
break;
}
/*
Global administration options (including statistics gathering)
*/
case '#':
{
szAction[ 0] = '\0';
requestInput(
"Statistics (b = begin, e = end, r = reset)",
szAction, sizeof( szAction), &uiTermChar);
if( uiTermChar == FKB_ESCAPE)
{
break;
}
if( m_pEditStatusWin)
{
FTXWinSetCursorPos( m_pEditStatusWin, 0, 0);
}
if( szAction [0] == 'b' || szAction [0] == 'B')
{
if( m_pEditStatusWin)
{
FTXWinPrintf( m_pEditStatusWin,
"Starting statistics ...");
FTXWinClearToEOL( m_pEditStatusWin);
}
if( RC_BAD( tmpRc = globalConfig(
F_DOMEDIT_CONFIG_STATS_START)))
{
displayMessage( "Error Starting Statistics",
RC_SET( tmpRc),
NULL,
FLM_RED,
FLM_WHITE);
break;
}
}
else if( szAction [0] == 'e' || szAction [0] == 'E')
{
if( m_pEditStatusWin)
{
FTXWinPrintf( m_pEditStatusWin,
"Stopping statistics ...");
FTXWinClearToEOL( m_pEditStatusWin);
}
if( RC_BAD( tmpRc = globalConfig(
F_DOMEDIT_CONFIG_STATS_STOP)))
{
displayMessage( "Error Stopping Statistics",
RC_SET( tmpRc),
NULL,
FLM_RED,
FLM_WHITE);
break;
}
}
else if( szAction [0] == 'r' || szAction [0] == 'R')
{
if( m_pEditStatusWin)
{
FTXWinPrintf( m_pEditStatusWin,
"Resetting statistics ...");
FTXWinClearToEOL( m_pEditStatusWin);
}
if( RC_BAD( tmpRc = globalConfig( F_DOMEDIT_CONFIG_STATS_RESET)))
{
displayMessage( "Error Resetting Statistics",
RC_SET( tmpRc),
NULL,
FLM_RED,
FLM_WHITE);
break;
}
}
else
{
displayMessage( "Invalid Request",
RC_SET( NE_XFLM_FAILURE),
NULL,
FLM_RED,
FLM_WHITE);
break;
}
bRefreshStatusWindow = TRUE;
break;
}
case '?':
{
showHelp( &uiHelpKey);
break;
}
case FKB_F10:
{
if( m_bMonochrome)
{
m_bMonochrome = FALSE;
}
else
{
m_bMonochrome = TRUE;
}
bRefreshEditWindow = TRUE;
break;
}
case FKB_F8: /* Index Manager */
{
char szDbPath [F_PATH_MAX_SIZE];
F_Db * pTmpDb = NULL;
if( m_pDb == NULL)
{
break;
}
if( pIxManagerThrd)
{
pIxManagerThrd->Release();
pIxManagerThrd = NULL;
}
(void)m_pDb->getDbControlFileName( szDbPath, sizeof( szDbPath));
if (RC_OK( tmpRc = pDbSystem->dbOpen( szDbPath,
NULL,
NULL, NULL, TRUE,
(IF_Db **)&pTmpDb)))
{
pThreadMgr->createThread( &pIxManagerThrd,
flstIndexManagerThread,
"index_manager", 0, 0, (void *)pTmpDb);
}
else
{
displayMessage( "Failed to open database",
RC_SET( tmpRc),
NULL,
FLM_RED,
FLM_WHITE);
}
break;
}
case FKB_F9: /* Memory Manager */
{
if( pMemManagerThrd)
{
pMemManagerThrd->Release();
pMemManagerThrd = NULL;
}
pThreadMgr->createThread( &pMemManagerThrd,
flstMemoryManagerThread, "memory_manager");
break;
}
case FKB_DELETE:
{
if (RC_BAD( tmpRc = deleteRow( &m_pCurRow)))
{
displayMessage( "Delete operation failed",
RC_SET( tmpRc),
NULL,
FLM_RED,
FLM_WHITE);
break;
}
bRefreshEditWindow = TRUE;
break;
}
case FKB_ESCAPE:
case 'Q':
case 'q':
case 'Z':
case 'z':
case FKB_ALT_Q:
case FKB_ALT_Z:
{
bDoneEditing = TRUE;
break;
}
default:
{
/*
Unrecognized key ... ignore.
*/
break;
}
}
}
else
{
f_sleep( 1);
}
}
Exit:
f_free( &pszQuery);
if( pIxManagerThrd)
{
pIxManagerThrd->Release();
}
if( pMemManagerThrd)
{
pMemManagerThrd->Release();
}
if( pThreadMgr)
{
pThreadMgr->Release();
}
if( pDbSystem)
{
pDbSystem->Release();
}
if( m_pEditWindow)
{
(void) FTXWinFree( &m_pEditWindow);
}
if( m_pEditStatusWin)
{
(void) FTXWinFree( &m_pEditStatusWin);
}
return( rc);
}
/****************************************************************************
Desc: Draw the screen - refresh the display
*****************************************************************************/
RCODE F_DomEditor::refreshEditWindow(
DME_ROW_INFO ** ppFirstRow,
DME_ROW_INFO * pCursorRow,
FLMUINT * puiCurRow)
{
FLMUINT uiLoop;
FLMUINT uiNumCols;
FLMUINT uiNumRows;
DME_ROW_INFO * pFirstRow;
DME_ROW_INFO * pTmpRow;
FLMUINT uiCurRow;
FLMBOOL bCurrentVisible = FALSE;
FLMBOOL bStartedTrans = FALSE;
RCODE rc = NE_XFLM_OK;
flmAssert( m_bSetupCalled == TRUE);
if( pCursorRow == NULL)
{
*ppFirstRow = NULL;
*puiCurRow = 0;
}
FTXWinGetCanvasSize( m_pEditWindow, &uiNumCols, &uiNumRows);
/*
See if the cursor row is already being displayed.
*/
uiCurRow = 0;
pFirstRow = *ppFirstRow;
pTmpRow = pFirstRow;
for( uiLoop = 0; uiLoop < uiNumRows; uiLoop++)
{
if( pCursorRow == pTmpRow)
{
uiCurRow = uiLoop;
bCurrentVisible = TRUE;
break;
}
if (RC_BAD( rc = getNextRow( pTmpRow, &pTmpRow)))
{
goto Exit;
}
if (pTmpRow == NULL)
{
break;
}
checkDocument(&m_pCurDoc, pTmpRow);
}
/*
If the current node is not displayed, scroll the screen
so that the node is visible.
*/
if( !bCurrentVisible)
{
uiCurRow = *puiCurRow;
pFirstRow = pCursorRow;
while( uiCurRow && pFirstRow)
{
if (RC_BAD( rc = getPrevRow( pFirstRow, &pTmpRow)))
{
goto Exit;
}
if( pTmpRow)
{
pFirstRow = pTmpRow;
}
uiCurRow--;
}
}
*ppFirstRow = pFirstRow;
*puiCurRow = uiCurRow;
// Turn display refresh off temporarily
FTXSetRefreshState( TRUE);
// Start a transaction
if( RC_BAD( rc = m_pDb->checkTransaction( XFLM_READ_TRANS, &bStartedTrans)))
{
goto Exit;
}
// Refresh all rows of the edit window. All rows beyond the end
// of the tree are cleared.
pTmpRow = *ppFirstRow;
for( uiLoop = 0; uiLoop < uiNumRows; uiLoop++)
{
if( pTmpRow && pTmpRow == pCursorRow)
{
refreshRow( uiLoop, pTmpRow, TRUE);
*puiCurRow = uiLoop;
}
else
{
refreshRow( uiLoop, pTmpRow, FALSE);
}
if( pTmpRow)
{
if (RC_BAD( rc = getNextRow( pTmpRow, &pTmpRow)))
{
goto Exit;
}
}
}
Exit:
if( bStartedTrans)
{
m_pDb->transAbort();
}
/*
Re-enable display refresh
*/
FTXSetRefreshState( FALSE);
return( rc);
}
/****************************************************************************
Desc: Get the domnode
*****************************************************************************/
RCODE F_DomEditor::getDomNode(
FLMUINT64 ui64NodeId,
FLMUINT uiAttrNameId,
F_DOMNode ** ppDomNode
)
{
RCODE rc = NE_XFLM_OK;
if (uiAttrNameId)
{
if (RC_BAD( rc = m_pDb->getAttribute( m_uiCollection, ui64NodeId,
uiAttrNameId,
(IF_DOMNode **)ppDomNode)))
{
goto Exit;
}
}
else
{
if (RC_BAD( rc = m_pDb->getNode( m_uiCollection, ui64NodeId, ppDomNode)))
{
goto Exit;
}
}
Exit:
return rc;
}
/****************************************************************************
Name: F_DomEditorDefaultDispHook
Desc: Default line display format routine
*****************************************************************************/
RCODE F_DomEditorDefaultDispHook(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pRow,
FLMUINT * puiNumVals)
{
RCODE rc = NE_XFLM_OK;
FLMUINT uiFlags = 0;
if( !pRow)
{
goto Exit;
}
pDomEditor->getControlFlags( pRow, &uiFlags);
// Are we just displaying a value, or should we use the Dom?
if (pRow->bUseValue)
{
rc = formatRow( pDomEditor, pRow, puiNumVals, uiFlags);
goto Exit;
}
// Need to find out what type of node we have to display.
if (RC_BAD( rc = getDOMNode( pDomEditor, pRow)))
{
goto Exit;
}
switch (pRow->eType)
{
case DOCUMENT_NODE:
{
if (RC_BAD( rc = formatDocumentNode( pDomEditor, pRow, puiNumVals, uiFlags)))
{
goto Exit;
}
break;
}
case ELEMENT_NODE:
{
// It is possible to have data embedded in the element node.
if (uiFlags & F_DOMEDIT_FLAG_ELEMENT_DATA)
{
if (RC_BAD( rc = formatDataNode( pDomEditor, pRow, puiNumVals, uiFlags, NULL, NULL)))
{
goto Exit;
}
}
else
{
if (RC_BAD( rc = formatElementNode( pDomEditor, pRow, puiNumVals, uiFlags)))
{
goto Exit;
}
}
break;
}
case DATA_NODE:
{
if (RC_BAD( rc = formatDataNode( pDomEditor, pRow, puiNumVals, uiFlags, NULL, NULL)))
{
goto Exit;
}
break;
}
case CDATA_SECTION_NODE:
{
if (RC_BAD( rc = formatDataNode( pDomEditor, pRow, puiNumVals, uiFlags,
"<![CDATA[", "]]>")))
{
goto Exit;
}
break;
}
case COMMENT_NODE:
{
if (RC_BAD( rc = formatDataNode( pDomEditor, pRow, puiNumVals, uiFlags,
"<!--", "-->")))
{
goto Exit;
}
break;
}
case PROCESSING_INSTRUCTION_NODE:
{
if (RC_BAD( rc = formatProcessingInstruction( pDomEditor, pRow, puiNumVals, uiFlags)))
{
goto Exit;
}
break;
}
case ATTRIBUTE_NODE:
{
if (RC_BAD( rc = formatAttributeNode( pDomEditor, pRow, puiNumVals, uiFlags)))
{
goto Exit;
}
break;
}
case INVALID_NODE:
break; // Don't know just yet what to do, but will figure it out soon.
default:
{
flmAssert( 0);
rc = RC_SET( NE_XFLM_FAILURE);
goto Exit;
}
}
Exit:
// Don't hold on to the Dom node when finished.
if ( pRow->pDomNode)
{
pRow->pDomNode->Release();
pRow->pDomNode = NULL;
}
return( rc);
}
/****************************************************************************
Desc:
*****************************************************************************/
RCODE F_DomEditor::refreshRow(
FLMUINT uiRow,
DME_ROW_INFO * pRow,
FLMBOOL bSelected)
{
FLMUINT uiNumCols;
FLMUINT uiNumRows;
FLMUINT uiNumVals;
FLMUINT uiLoop;
RCODE rc = NE_XFLM_OK;
flmAssert( m_bSetupCalled == TRUE);
FTXWinGetCanvasSize( m_pEditWindow, &uiNumCols, &uiNumRows);
FTXWinSetCursorPos( m_pEditWindow, 0, uiRow);
FTXWinClearLine( m_pEditWindow, 0, uiRow);
if (!pRow)
{
goto Exit;
}
f_memset( m_dispColumns, 0, sizeof( m_dispColumns));
uiNumVals = 0;
/*
Call the display formatter
*/
if( m_pDisplayHook)
{
if( RC_BAD( rc = m_pDisplayHook( this, pRow, &uiNumVals)))
{
goto Exit;
}
}
else
{
if( RC_BAD( rc = F_DomEditorDefaultDispHook( this, pRow, &uiNumVals)))
{
goto Exit;
}
}
for( uiLoop = 0; uiLoop < uiNumVals; uiLoop++)
{
FTXWinSetCursorPos( m_pEditWindow, m_dispColumns[ uiLoop].uiCol, uiRow);
FTXWinCPrintf( m_pEditWindow, m_dispColumns[ uiLoop].uiBackground,
m_dispColumns[ uiLoop].uiForeground, "%s", m_dispColumns[ uiLoop].szString);
}
if( bSelected)
{
eColorType uiBackground = m_bMonochrome ? FLM_LIGHTGRAY : FLM_CYAN;
eColorType uiForeground = m_bMonochrome ? FLM_BLACK : FLM_WHITE;
FTXWinPaintRow( m_pEditWindow, &uiBackground, &uiForeground, uiRow);
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Repositions the cursor to display at the top of
the editor window
*****************************************************************************/
void F_DomEditor::setCurrentAtTop( void)
{
m_uiCurRow = 0;
m_pCurRow = m_pScrFirstRow;
}
/****************************************************************************
Desc: Repositions the cursor (and current node) to display at the bottom of
the editor window
*****************************************************************************/
void F_DomEditor::setCurrentAtBottom( void)
{
FLMUINT uiNumRows;
flmAssert( m_pEditWindow != NULL);
FTXWinGetCanvasSize( m_pEditWindow, NULL, &uiNumRows);
uiNumRows--;
m_pCurRow = m_pScrLastRow;
m_uiCurRow = uiNumRows;
}
/****************************************************************************
Name: displayMessage
Desc:
*****************************************************************************/
RCODE F_DomEditor::displayMessage(
const char * pszMessage,
RCODE rcOfMessage,
FLMUINT * puiTermChar,
eColorType uiBackground,
eColorType uiForeground)
{
RCODE rc = NE_XFLM_OK;
char szErr [20];
f_sprintf( szErr, "Error=0x%04X", (unsigned)rcOfMessage);
flmAssert( m_bSetupCalled == TRUE);
if( puiTermChar)
{
*puiTermChar = 0;
}
FTXDisplayMessage( m_pScreen, m_bMonochrome ? FLM_LIGHTGRAY : uiBackground,
m_bMonochrome ? FLM_BLACK : uiForeground, pszMessage, szErr, puiTermChar);
return( rc);
}
/****************************************************************************
Name: openNewDb
Desc:
*****************************************************************************/
RCODE F_DomEditor::openNewDb( void)
{
RCODE rc = NE_XFLM_OK;
char szResponse [100];
FLMUINT uiChar;
IF_DbSystem * pDbSystem = NULL;
if( RC_BAD( rc = FlmAllocDbSystem( &pDbSystem)))
{
goto Exit;
}
szResponse [0] = 0;
flmAssert( m_pDb == NULL);
for (;;)
{
if (RC_BAD( rc = requestInput( "Enter name of DB to open",
szResponse, sizeof( szResponse), &uiChar)))
{
goto Exit;
}
if (uiChar == FKB_ESCAPE)
{
break;
}
if (RC_BAD( rc = pDbSystem->dbOpen( szResponse, NULL, NULL, NULL, TRUE,
(IF_Db **)&m_pDb)))
{
displayMessage( "Unable to open database", rc,
NULL, FLM_RED, FLM_WHITE);
m_pDb = NULL;
continue;
}
m_bOpenedDb = TRUE;
break;
}
Exit:
if( pDbSystem)
{
pDbSystem->Release();
}
return( rc);
}
/****************************************************************************
Name: requestInput
Desc:
*****************************************************************************/
RCODE F_DomEditor::requestInput(
const char * pszMessage,
char * pszResponse,
FLMUINT uiMaxRespLen,
FLMUINT * puiTermChar)
{
RCODE rc = NE_XFLM_OK;
FLMUINT uiNumCols;
FLMUINT uiNumRows;
FLMUINT uiNumWinRows = 3;
FLMUINT uiNumWinCols;
FTX_WINDOW * pWindow = NULL;
IF_FileHdl * pFileHdl = NULL;
IF_FileSystem * pFileSystem = NULL;
flmAssert( m_bSetupCalled == TRUE);
if( RC_BAD( rc = FlmGetFileSystem( &pFileSystem)))
{
goto Exit;
}
FTXScreenGetSize( m_pScreen, &uiNumCols, &uiNumRows);
uiNumWinCols = uiNumCols - 8;
if( RC_BAD( rc = FTXWinInit( m_pScreen, uiNumWinCols,
uiNumWinRows, &pWindow)))
{
goto Exit;
}
FTXWinSetScroll( pWindow, FALSE);
FTXWinSetCursorType( pWindow, FLM_CURSOR_UNDERLINE);
FTXWinSetBackFore( pWindow, m_bMonochrome ? FLM_BLACK : FLM_CYAN, FLM_WHITE);
FTXWinClear( pWindow);
FTXWinDrawBorder( pWindow);
FTXWinMove( pWindow, (uiNumCols - uiNumWinCols) / 2,
(uiNumRows - uiNumWinRows) / 2);
FTXWinOpen( pWindow);
for( ;;)
{
FTXWinClear( pWindow);
FTXWinPrintf( pWindow, "%s: ", pszMessage);
if( RC_BAD( rc = FTXLineEdit( pWindow, pszResponse,
uiMaxRespLen, uiMaxRespLen, NULL, puiTermChar)))
{
goto Exit;
}
if( *puiTermChar == FKB_F1)
{
FLMUINT uiBytesRead;
char * pszSrc;
char * pszDest;
if( RC_BAD( rc = pFileSystem->openFile( pszResponse, FLM_IO_RDONLY,
&pFileHdl)))
{
displayMessage( "Unable to open file", rc,
NULL, FLM_RED, FLM_WHITE);
continue;
}
if( RC_BAD( rc = pFileHdl->read( 0, uiMaxRespLen,
pszResponse, &uiBytesRead)))
{
if( rc == NE_FLM_IO_END_OF_FILE)
{
rc = NE_XFLM_OK;
}
else
{
goto Exit;
}
}
pFileHdl->Release();
pFileHdl = NULL;
pszResponse[ uiBytesRead] = '\0';
// Convert newlines to spaces. Multiple consecutive newlines
// will be converted to a single space.
pszSrc = pszDest = pszResponse;
while (*pszSrc)
{
if (*pszSrc == '\r' || *pszSrc == '\n')
{
*pszDest = ' ';
pszDest++;
pszSrc++;
while (*pszSrc == '\r' || *pszSrc == '\n')
{
pszSrc++;
}
}
else
{
if (pszDest != pszSrc)
{
*pszDest = *pszSrc;
}
pszSrc++;
pszDest++;
}
}
*pszDest = 0;
}
else
{
break;
}
}
Exit:
if( pFileHdl)
{
pFileHdl->Release();
}
if( pFileSystem)
{
pFileSystem->Release();
}
if( pWindow)
{
FTXWinFree( &pWindow);
}
return( rc);
}
/****************************************************************************
Name: getControlFlags
Desc:
*****************************************************************************/
RCODE F_DomEditor::getControlFlags(
DME_ROW_INFO * pCurRow,
FLMUINT * puiFlags)
{
RCODE rc = NE_XFLM_OK;
flmAssert( m_bSetupCalled == TRUE);
if ( !pCurRow)
{
goto Exit;
}
*puiFlags = pCurRow->uiFlags;
Exit:
return( rc);
}
/****************************************************************************
Name: setControlFlags
Desc:
*****************************************************************************/
RCODE F_DomEditor::setControlFlags(
DME_ROW_INFO * pCurRow,
FLMUINT uiFlags)
{
RCODE rc = NE_XFLM_OK;
flmAssert( m_bSetupCalled == TRUE);
pCurRow->uiFlags = uiFlags;
return( rc);
}
/****************************************************************************
Desc: Get the previous row to display.
*****************************************************************************/
RCODE F_DomEditor::getPrevRow(
DME_ROW_INFO * pCurRow,
DME_ROW_INFO ** ppPrevRow,
FLMBOOL bFetchPrevRow
)
{
RCODE rc = NE_XFLM_OK;
DME_ROW_INFO * pPrevRow = NULL;
DME_ROW_INFO * pDocList = m_pCurDoc;
F_DOMNode * pChildDomNode = NULL;
F_DOMNode * pSiblingDomNode = NULL;
F_DOMNode * pParentDomNode = NULL;
FLMBOOL bCurRowDataLocal;
flmAssert( m_bSetupCalled == TRUE);
if (pCurRow == NULL)
{
goto Exit;
}
// Get the previous row.
pPrevRow = pCurRow->pPrev;
// Got it, we're done...
if (pPrevRow)
{
goto Exit;
}
if (!bFetchPrevRow)
{
goto Exit;
}
// If we were on the first display line, we will need to see about fetching
// the previous row
if (pCurRow == m_pScrFirstRow)
{
if (m_bDocList)
{
if (RC_BAD( rc = getPrevTitle( pCurRow, &pPrevRow)))
{
goto Exit;
}
if (pPrevRow == NULL)
{
goto Exit;
}
goto InsertRow;
}
if (pCurRow->uiFlags & F_DOMEDIT_FLAG_NODOM)
{
goto Exit;
}
if (RC_BAD( rc = getDOMNode( this, pCurRow)))
{
goto Exit;
}
if (RC_BAD( rc = pCurRow->pDomNode->isDataLocalToNode( m_pDb, &bCurRowDataLocal)))
{
goto Exit;
}
if ((pCurRow->uiFlags & F_DOMEDIT_FLAG_ENDTAG) &&
(!(pCurRow->uiFlags & F_DOMEDIT_FLAG_NOCHILD) || bCurRowDataLocal))
{
if (bCurRowDataLocal && pCurRow->pDomNode->getNodeType() == ELEMENT_NODE)
{
pChildDomNode = pCurRow->pDomNode;
pChildDomNode->AddRef();
}
else if (RC_BAD( rc = pCurRow->pDomNode->getLastChild( m_pDb, (IF_DOMNode **)&pChildDomNode)))
{
flmAssert( rc != NE_XFLM_NOT_FOUND && rc != NE_XFLM_DOM_NODE_NOT_FOUND);
goto Exit;
}
if (RC_BAD( rc = buildNewRow( (FLMINT)pCurRow->uiLevel+1,
pChildDomNode,
&pPrevRow)))
{
goto Exit;
}
if (!bCurRowDataLocal)
{
pPrevRow->uiFlags = pCurRow->uiFlags | F_DOMEDIT_FLAG_ENDTAG;
if (RC_BAD( rc = pChildDomNode->isDataLocalToNode( m_pDb, &pPrevRow->bHasElementData)))
{
goto Exit;
}
}
else
{
pPrevRow->uiFlags = pCurRow->uiFlags & ~F_DOMEDIT_FLAG_ENDTAG;
}
if (bCurRowDataLocal)
{
pPrevRow->uiFlags |= F_DOMEDIT_FLAG_ELEMENT_DATA;
}
if (m_pRowAnchor)
{
pPrevRow->bExpanded = !m_pRowAnchor->bSingleLevel;
}
goto InsertRow;
}
if (pCurRow->eType != DOCUMENT_NODE &&
!(pCurRow->uiFlags & F_DOMEDIT_FLAG_ELEMENT_DATA))
{
if (RC_BAD( rc = pCurRow->pDomNode->getPreviousSibling(
m_pDb,
(IF_DOMNode **)&pSiblingDomNode)))
{
if (rc != NE_XFLM_NOT_FOUND && rc != NE_XFLM_DOM_NODE_NOT_FOUND)
{
goto Exit;
}
}
if (RC_OK( rc))
{
// Build a new row.
if (RC_BAD( rc = buildNewRow( (FLMINT)pCurRow->uiLevel,
pSiblingDomNode,
&pPrevRow)))
{
goto Exit;
}
pPrevRow->uiFlags = pCurRow->uiFlags & ~(F_DOMEDIT_FLAG_ENDTAG);
if (m_pRowAnchor)
{
pPrevRow->bExpanded = !m_pRowAnchor->bSingleLevel && pPrevRow->bHasChildren;
}
if ( pPrevRow->bExpanded)
{
pPrevRow->uiFlags |= F_DOMEDIT_FLAG_ENDTAG;
}
goto InsertRow;
}
}
if (!(pCurRow->uiFlags & F_DOMEDIT_FLAG_NOPARENT) ||
(bCurRowDataLocal && pCurRow->uiFlags & F_DOMEDIT_FLAG_ELEMENT_DATA))
{
if (bCurRowDataLocal && pCurRow->uiFlags & F_DOMEDIT_FLAG_ELEMENT_DATA)
{
pParentDomNode = pCurRow->pDomNode;
pParentDomNode->AddRef();
}
else if (RC_BAD( rc = pCurRow->pDomNode->getParentNode(
m_pDb,
(IF_DOMNode **)&pParentDomNode)))
{
if (rc != NE_XFLM_NOT_FOUND && rc != NE_XFLM_DOM_NODE_NOT_FOUND)
{
goto Exit;
}
}
if (RC_OK( rc))
{
if (RC_BAD( rc = buildNewRow( (FLMINT)pCurRow->uiLevel - 1,
pParentDomNode,
&pPrevRow)))
{
goto Exit;
}
pPrevRow->uiFlags = pCurRow->uiFlags & ~(F_DOMEDIT_FLAG_ENDTAG | F_DOMEDIT_FLAG_ELEMENT_DATA);
if (RC_BAD( rc = pParentDomNode->isDataLocalToNode( m_pDb, &pPrevRow->bHasElementData)))
{
goto Exit;
}
pPrevRow->bExpanded = TRUE;
goto InsertRow;
}
}
rc = NE_XFLM_OK;
// Is there a previous document that we can display?
// The pPrevRow should always be NULL at this point.
flmAssert( pPrevRow == NULL);
if (pDocList)
{
pDocList = pDocList->pPrev;
}
if (pDocList)
{
if (RC_BAD( rc = getDOMNode( this, pDocList)))
{
goto Exit;
}
// Build a new row.
if (RC_BAD( rc = buildNewRow( -1,
pDocList->pDomNode,
&pPrevRow)))
{
goto Exit;
}
goto InsertRow;
}
else
{
goto Exit;
}
InsertRow:
// Insert at the front.
if (RC_BAD( rc = insertRow( pPrevRow, NULL)))
{
goto Exit;
}
m_pCurRow = m_pScrFirstRow;
// Need to remove the last row.
if (m_uiNumRows > m_uiEditCanvasRows)
{
releaseLastRow();
}
}
Exit:
if (pSiblingDomNode)
{
pSiblingDomNode->Release();
}
if (pChildDomNode)
{
pChildDomNode->Release();
}
if (pParentDomNode)
{
pParentDomNode->Release();
}
if (pCurRow && pCurRow->pDomNode)
{
pCurRow->pDomNode->Release();
pCurRow->pDomNode = NULL;
}
if ( m_pCurDoc && m_pCurDoc->pDomNode)
{
m_pCurDoc->pDomNode->Release();
m_pCurDoc->pDomNode = NULL;
}
if (pDocList && pDocList->pDomNode)
{
pDocList->pDomNode->Release();
pDocList->pDomNode = NULL;
}
if (pPrevRow && pPrevRow->pDomNode)
{
pPrevRow->pDomNode->Release();
pPrevRow->pDomNode = NULL;
}
*ppPrevRow = pPrevRow;
return rc;
}
/****************************************************************************
Desc: Get the next row. If the current row is the last row being displayed,
we need to also remove the first row.
*****************************************************************************/
RCODE F_DomEditor::getNextRow(
DME_ROW_INFO * pCurRow,
DME_ROW_INFO ** ppNextRow,
FLMBOOL bFetchNextRow,
FLMBOOL bIgnoreAnchor
)
{
RCODE rc = NE_XFLM_OK;
DME_ROW_INFO * pNextRow = NULL;
DME_ROW_INFO * pDocList = m_pCurDoc;
F_DOMNode * pChildDomNode = NULL;
F_DOMNode * pSiblingDomNode = NULL;
F_DOMNode * pParentDomNode = NULL;
FLMBOOL bCurRowDataLocal;
flmAssert( m_bSetupCalled == TRUE);
if (pCurRow == NULL)
{
goto Exit;
}
pNextRow = pCurRow->pNext;
// Got it, we're done...
if (pNextRow)
{
goto Exit;
}
if (!bFetchNextRow)
{
goto Exit;
}
// If we were on the last display line, we will need to see about fetching
// the next row
if (m_uiNumRows <= m_uiEditCanvasRows)
{
if (m_bDocList)
{
if (RC_BAD( rc = getNextTitle( pCurRow, &pNextRow)))
{
goto Exit;
}
if (pNextRow == NULL)
{
goto Exit;
}
goto InsertRow;
}
if (pCurRow->uiFlags & F_DOMEDIT_FLAG_NODOM)
{
goto Exit;
}
// If the current row was expanded or there is an anchor row, we will
// need to check the Anchor to see how we are expanding it. Either
// deep or single level.
if (RC_BAD( rc = getDOMNode( this, pCurRow)))
{
goto Exit;
}
if (RC_BAD( rc = pCurRow->pDomNode->isDataLocalToNode( m_pDb, &bCurRowDataLocal)))
{
goto Exit;
}
if (m_pRowAnchor && !bIgnoreAnchor && pCurRow->bExpanded)
{
if (( m_pRowAnchor->bSingleLevel &&
m_pRowAnchor->uiAnchorLevel == pCurRow->uiLevel) ||
(!m_pRowAnchor->bSingleLevel))
{
if (!(pCurRow->uiFlags & F_DOMEDIT_FLAG_ENDTAG))
{
if (bCurRowDataLocal && pCurRow->pDomNode->getNodeType() == ELEMENT_NODE &&
!(pCurRow->uiFlags & F_DOMEDIT_FLAG_ELEMENT_DATA))
{
pChildDomNode = pCurRow->pDomNode;
pChildDomNode->AddRef();
}
// Get the first child.
else if (RC_BAD( rc = pCurRow->pDomNode->getFirstChild(
m_pDb, (IF_DOMNode **)&pChildDomNode)))
{
if (rc != NE_XFLM_NOT_FOUND && rc != NE_XFLM_DOM_NODE_NOT_FOUND)
{
goto Exit;
}
}
if (RC_OK( rc))
{
// Build a new row.
if (RC_BAD( rc = buildNewRow( (FLMINT)pCurRow->uiLevel+1,
pChildDomNode,
&pNextRow)))
{
goto Exit;
}
pNextRow->uiFlags = pCurRow->uiFlags & ~(F_DOMEDIT_FLAG_ENDTAG);
if (bCurRowDataLocal && pCurRow->pDomNode->getNodeType() == ELEMENT_NODE)
{
pNextRow->uiFlags |= F_DOMEDIT_FLAG_ELEMENT_DATA;
}
if (!bCurRowDataLocal)
{
if (RC_BAD( rc = pChildDomNode->isDataLocalToNode( m_pDb, &pNextRow->bHasElementData)))
{
goto Exit;
}
}
pNextRow->bExpanded = !m_pRowAnchor->bSingleLevel;
goto InsertRow;
}
}
}
}
rc = NE_XFLM_OK;
if (pCurRow->bExpanded && !bIgnoreAnchor)
{
if ((!(pCurRow->uiFlags & F_DOMEDIT_FLAG_ENDTAG)) &&
(!(pCurRow->uiFlags & F_DOMEDIT_FLAG_NOCHILD) || bCurRowDataLocal))
{
if (bCurRowDataLocal && pCurRow->pDomNode->getNodeType() == ELEMENT_NODE &&
!(pCurRow->uiFlags & F_DOMEDIT_FLAG_ELEMENT_DATA))
{
pChildDomNode = pCurRow->pDomNode;
pChildDomNode->AddRef();
}
// Get the first child.
else if (RC_BAD( rc = pCurRow->pDomNode->getFirstChild(
m_pDb, (IF_DOMNode **)&pChildDomNode)))
{
if (rc != NE_XFLM_NOT_FOUND && rc != NE_XFLM_DOM_NODE_NOT_FOUND)
{
goto Exit;
}
}
if (RC_OK( rc))
{
// Build a new row.
if (RC_BAD( rc = buildNewRow( (FLMINT)pCurRow->uiLevel+1,
pChildDomNode,
&pNextRow)))
{
goto Exit;
}
pNextRow->uiFlags = pCurRow->uiFlags & ~(F_DOMEDIT_FLAG_ENDTAG);
if (bCurRowDataLocal && pCurRow->pDomNode->getNodeType() == ELEMENT_NODE)
{
pNextRow->uiFlags |= F_DOMEDIT_FLAG_ELEMENT_DATA;
}
if (m_pRowAnchor)
{
pNextRow->bExpanded = !m_pRowAnchor->bSingleLevel;
}
goto InsertRow;
}
}
}
rc = NE_XFLM_OK;
if (pCurRow->eType != DOCUMENT_NODE)
{
if (RC_BAD( rc = pCurRow->pDomNode->getNextSibling(
m_pDb,
(IF_DOMNode **)&pSiblingDomNode)))
{
if (rc != NE_XFLM_NOT_FOUND && rc != NE_XFLM_DOM_NODE_NOT_FOUND)
{
goto Exit;
}
}
if (RC_OK( rc))
{
// Build a new row.
if (RC_BAD( rc = buildNewRow( (FLMINT)pCurRow->uiLevel,
pSiblingDomNode,
&pNextRow)))
{
goto Exit;
}
pNextRow->uiFlags = pCurRow->uiFlags & ~(F_DOMEDIT_FLAG_ENDTAG);
if (m_pRowAnchor)
{
pNextRow->bExpanded = !m_pRowAnchor->bSingleLevel && pNextRow->bHasChildren;
}
goto InsertRow;
}
}
rc = NE_XFLM_OK;
// No sibling node found. Must go up one level to parent if we can
if (!(pCurRow->uiFlags & F_DOMEDIT_FLAG_NOPARENT) ||
(bCurRowDataLocal && pCurRow->uiFlags & F_DOMEDIT_FLAG_ELEMENT_DATA))
{
if (bCurRowDataLocal && (pCurRow->uiFlags & F_DOMEDIT_FLAG_ELEMENT_DATA))
{
pParentDomNode = pCurRow->pDomNode;
pParentDomNode->AddRef();
}
else if (RC_BAD( rc = pCurRow->pDomNode->getParentNode(
m_pDb,
(IF_DOMNode **)&pParentDomNode)))
{
if (rc != NE_XFLM_NOT_FOUND && rc != NE_XFLM_DOM_NODE_NOT_FOUND)
{
goto Exit;
}
}
if (RC_OK( rc))
{
if (RC_BAD( rc = buildNewRow( (FLMINT)pCurRow->uiLevel - 1,
pParentDomNode,
&pNextRow)))
{
goto Exit;
}
pNextRow->uiFlags = (pCurRow->uiFlags & ~F_DOMEDIT_FLAG_ELEMENT_DATA) | F_DOMEDIT_FLAG_ENDTAG;
pNextRow->bExpanded = TRUE;
if (RC_BAD( rc = pParentDomNode->isDataLocalToNode( m_pDb, &pNextRow->bHasElementData)))
{
goto Exit;
}
goto InsertRow;
}
}
rc = NE_XFLM_OK;
// If nothing was found, is there another document in the list that we
// can display? Getting to this point indicates that we could not find
// another row to display in the current document.
flmAssert( pNextRow == NULL);
if (pDocList)
{
pDocList = pDocList->pNext;
}
if (pDocList)
{
if (RC_BAD( rc = getDOMNode( this, pDocList)))
{
goto Exit;
}
// Build a new row.
if (RC_BAD( rc = buildNewRow( -1,
pDocList->pDomNode,
&pNextRow)))
{
goto Exit;
}
goto InsertRow;
}
else
{
goto Exit;
}
InsertRow:
if (RC_BAD( rc = insertRow( pNextRow,
pCurRow)))
{
goto Exit;
}
// Need to remove the first row.
if (m_uiNumRows > m_uiEditCanvasRows)
{
releaseRow( &m_pScrFirstRow);
m_uiNumRows--;
}
// Set the new last row
m_pScrLastRow = pNextRow;
// If there is an anchor row, then did we just display it's end tag?
if (m_pRowAnchor)
{
if (m_pRowAnchor->ui64NodeId == pNextRow->ui64NodeId)
{
// We can remove the anchor now.
f_free( &m_pRowAnchor);
}
}
}
Exit:
if (pSiblingDomNode)
{
pSiblingDomNode->Release();
}
if (pChildDomNode)
{
pChildDomNode->Release();
}
if (pParentDomNode)
{
pParentDomNode->Release();
}
if (pCurRow && pCurRow->pDomNode)
{
pCurRow->pDomNode->Release();
pCurRow->pDomNode = NULL;
}
if (m_pCurDoc && m_pCurDoc->pDomNode)
{
m_pCurDoc->pDomNode->Release();
m_pCurDoc->pDomNode = NULL;
}
if (pDocList && pDocList->pDomNode)
{
pDocList->pDomNode->Release();
pDocList->pDomNode = NULL;
}
if (pNextRow && pNextRow->pDomNode)
{
pNextRow->pDomNode->Release();
pNextRow->pDomNode = NULL;
}
*ppNextRow = pNextRow;
return rc;
}
/****************************************************************************
Desc: Set's root row - first row in the list.
*****************************************************************************/
void F_DomEditor::setScrFirstRow(
DME_ROW_INFO * pScrFirstRow
)
{
m_uiNumRows = 0;
if (m_pScrFirstRow)
{
while (m_pScrFirstRow)
{
releaseRow( &m_pScrFirstRow);
}
}
if (m_pDocList)
{
while (m_pDocList)
{
releaseRow( &m_pDocList);
}
m_pCurDoc = NULL;
}
if (pScrFirstRow)
{
m_pScrFirstRow = pScrFirstRow;
m_uiNumRows++;
m_pScrLastRow = pScrFirstRow;
while (m_pScrLastRow->pNext)
{
m_pScrLastRow = m_pScrLastRow->pNext;
m_uiNumRows++;
}
}
else
{
m_pScrLastRow = m_pScrFirstRow;
f_free( &m_pRowAnchor);
}
}
/****************************************************************************
Desc: Build a new row structure. Note that when deleting the row, it will
also be necessary to delete the value buffer and release the Dom object.
*****************************************************************************/
RCODE F_DomEditor::buildNewRow(
FLMINT iLevel,
F_DOMNode * pDomNode,
DME_ROW_INFO ** ppNewRow
)
{
RCODE rc = NE_XFLM_OK;
DME_ROW_INFO * pNewRow;
F_DOMNode * pCurrDOMNode = NULL;
// Build the new row
if( RC_BAD( rc = f_alloc( sizeof( DME_ROW_INFO), &pNewRow)))
{
goto Exit;
}
f_memset( pNewRow, 0, sizeof( DME_ROW_INFO));
// Determine the node level if it isn't passed in.
if (iLevel == -1)
{
iLevel = 0;
pCurrDOMNode = pDomNode;
pCurrDOMNode->AddRef();
while (RC_OK( rc = pCurrDOMNode->getParentNode(
m_pDb, (IF_DOMNode **)&pCurrDOMNode)))
{
iLevel++;
}
if (rc != NE_XFLM_NOT_FOUND && rc != NE_XFLM_DOM_NODE_NOT_FOUND)
{
goto Exit;
}
pCurrDOMNode->Release();
pCurrDOMNode = NULL;
rc = NE_XFLM_OK;
}
pNewRow->eType = pDomNode->getNodeType();
if (pNewRow->eType == ATTRIBUTE_NODE)
{
if( RC_BAD( rc = pDomNode->getParentId( m_pDb, &pNewRow->ui64NodeId)))
{
goto Exit;
}
}
else
{
if( RC_BAD( rc = pDomNode->getNodeId( m_pDb, &pNewRow->ui64NodeId)))
{
goto Exit;
}
}
if( RC_BAD( rc = pDomNode->getDocumentId( m_pDb, &pNewRow->ui64DocId)))
{
goto Exit;
}
pNewRow->uiLevel = (FLMUINT)iLevel;
pDomNode->getNameId( m_pDb, &pNewRow->uiNameId);
pNewRow->bExpanded = FALSE;
if ( pDomNode->getNodeType() != ATTRIBUTE_NODE)
{
if (RC_BAD( rc = pDomNode->hasChildren( m_pDb, &pNewRow->bHasChildren)))
{
goto Exit;
}
if (RC_BAD( rc = pDomNode->hasAttributes( m_pDb, &pNewRow->bHasAttributes)))
{
goto Exit;
}
}
else
{
pNewRow->bHasChildren = FALSE;
pNewRow->bHasAttributes = FALSE;
}
//pNewRow->pDomNode = pDomNode;
*ppNewRow = pNewRow;
pNewRow = NULL;
Exit:
if (pCurrDOMNode)
{
pCurrDOMNode->Release();
}
if (pNewRow)
{
if ( pNewRow->puzValue)
{
f_free( pNewRow->puzValue);
}
if (pNewRow->pDomNode)
{
pNewRow->pDomNode->Release();
}
f_free( &pNewRow);
}
return rc;
}
/****************************************************************************
Desc: Expands a row to reveal it immediate children.
*****************************************************************************/
RCODE F_DomEditor::expandRow(
DME_ROW_INFO * pRow,
FLMBOOL bOneLevel,
DME_ROW_INFO ** ppLastRow
)
{
RCODE rc = NE_XFLM_OK;
DME_ROW_INFO * pNewRow = NULL;
DME_ROW_INFO * pPrevRow = pRow;
F_DOMNode * pDomNode = NULL;
F_DOMNode * pChildNode = NULL;
FLMBOOL bHaveFirstChild = FALSE;
FLMBOOL bRowHasElementData = pRow->bHasElementData;
// Is this row already expanded, or does it not have any children and it doesn't have any data?
if ( pRow->bExpanded || (!pRow->bHasChildren && !pRow->bHasElementData))
{
goto Exit;
}
// Get the Dom Node if it isn't already attached to the row.
if (RC_BAD( rc = getDOMNode( this, pRow)))
{
goto Exit;
}
while (!(pRow == m_pScrLastRow && m_uiNumRows >= m_uiEditCanvasRows) &&
(!(pPrevRow == m_pScrLastRow && m_uiNumRows >= m_uiEditCanvasRows)))
{
if (bRowHasElementData)
{
pDomNode = pRow->pDomNode;
pDomNode->AddRef();
}
else if (!bHaveFirstChild)
{
if (RC_BAD( rc = pRow->pDomNode->getFirstChild( m_pDb,
(IF_DOMNode **)&pDomNode)))
{
if (rc != NE_XFLM_NOT_FOUND && rc != NE_XFLM_DOM_NODE_NOT_FOUND)
{
goto Exit;
}
break;
}
bHaveFirstChild = TRUE;
}
else
{
if (RC_BAD( rc = pChildNode->getNextSibling( m_pDb,
(IF_DOMNode **)&pDomNode)))
{
if (rc != NE_XFLM_NOT_FOUND && rc != NE_XFLM_DOM_NODE_NOT_FOUND)
{
goto Exit;
}
break;
}
}
if (RC_BAD( rc = buildNewRow( pRow->uiLevel + 1,
pDomNode,
&pNewRow)))
{
goto Exit;
}
if (bRowHasElementData)
{
pNewRow->uiFlags |= F_DOMEDIT_FLAG_ELEMENT_DATA;
bRowHasElementData = FALSE;
}
else
{
// If the new row DOM node is an element node and it has embedded data,
// we need to set the bHasElementData flag.
if (pDomNode->getNodeType() == ELEMENT_NODE)
{
FLMBOOL bDataIsLocal;
if (RC_BAD( rc = pDomNode->isDataLocalToNode( m_pDb, &bDataIsLocal)))
{
goto Exit;
}
if (bDataIsLocal)
{
pNewRow->bHasElementData = TRUE;
}
else
{
pNewRow->bHasElementData = FALSE;
}
}
}
if (pChildNode)
{
pChildNode->Release();
pChildNode = NULL;
}
pChildNode = pDomNode;
pDomNode = NULL;
// Link the row in
if (RC_BAD( rc = insertRow( pNewRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pNewRow;
pNewRow = NULL;
if (m_uiNumRows > m_uiEditCanvasRows)
{
releaseLastRow();
}
// Recursively expand...
if (!bOneLevel && (pPrevRow->bHasChildren || pPrevRow->bHasElementData))
{
if (RC_BAD( rc = expandRow( pPrevRow,
bOneLevel,
&pPrevRow)))
{
goto Exit;
}
}
}
if (!(pPrevRow == m_pScrLastRow && m_uiNumRows >= m_uiEditCanvasRows))
{
// Now build the end row
if (RC_BAD( rc = buildNewRow( pRow->uiLevel,
pRow->pDomNode,
&pNewRow)))
{
goto Exit;
}
// Now set the flags and link this row after the current row.
pNewRow->uiFlags |= F_DOMEDIT_FLAG_ENDTAG;
pNewRow->bExpanded = TRUE;
pNewRow->bHasElementData = pRow->bHasElementData;
// Link the row in
if (RC_BAD(rc = insertRow( pNewRow,
pPrevRow)))
{
goto Exit;
}
pPrevRow = pNewRow;
pNewRow = NULL;
if (m_uiNumRows > m_uiEditCanvasRows)
{
releaseLastRow();
}
}
// Mark that the current row has been expanded...
pRow->bExpanded = TRUE;
if (pPrevRow->pDomNode)
{
pPrevRow->pDomNode->Release();
pPrevRow->pDomNode = NULL;
}
if (ppLastRow)
{
*ppLastRow = pPrevRow;
}
Exit:
if (pPrevRow->pDomNode)
{
pPrevRow->pDomNode->Release();
pPrevRow->pDomNode = NULL;
}
if (pNewRow)
{
if (pNewRow->puzValue)
{
f_free( &pNewRow->puzValue);
}
if (pNewRow->pDomNode)
{
pNewRow->pDomNode->Release();
pNewRow->pDomNode = NULL;
}
f_free( &pNewRow);
}
if (pDomNode)
{
pDomNode->Release();
}
if ( pRow->pDomNode)
{
pRow->pDomNode->Release();
pRow->pDomNode = NULL;
}
if (pChildNode)
{
pChildNode->Release();
}
if (pDomNode)
{
pDomNode->Release();
}
return rc;
}
/****************************************************************************
Desc: Collapses a row to reveal it immediate children.
*****************************************************************************/
RCODE F_DomEditor::collapseRow(
DME_ROW_INFO ** ppRow
)
{
RCODE rc = NE_XFLM_OK;
DME_ROW_INFO * pTmpRow = NULL;
DME_ROW_INFO * pReleaseRow = NULL;
DME_ROW_INFO * pRow = *ppRow;
FLMUINT uiLevel;
FLMBOOL bIgnoreAnchor;
// Is this row already collapsed, or does it not have any children?
if ( !pRow->bExpanded || !pRow->bHasChildren && !pRow->bHasElementData)
{
goto Exit;
}
uiLevel = pRow->uiLevel;
// Are we looking at the first or last entry to be collapsed?
if (pRow->uiFlags & F_DOMEDIT_FLAG_ENDTAG)
{
for (pTmpRow = pRow->pPrev;
pTmpRow && pTmpRow->uiLevel >= uiLevel;
)
{
FLMUINT uiOldLevel = pTmpRow->uiLevel;
pReleaseRow = pTmpRow;
pTmpRow = pTmpRow->pPrev;
releaseRow( &pReleaseRow);
m_uiNumRows--;
if (uiOldLevel == uiLevel)
{
break;
}
}
pRow->bExpanded = FALSE;
pRow->uiFlags &= ~(FLMUINT)F_DOMEDIT_FLAG_ENDTAG;
// If we deleted the first row, we must reset it.
if (pTmpRow == NULL)
{
m_pScrFirstRow = pRow;
}
}
else
{
pRow->bExpanded = FALSE;
pTmpRow = pRow->pNext;
while (pTmpRow && pTmpRow->uiLevel >= uiLevel)
{
FLMUINT uiOldLevel = pTmpRow->uiLevel;
releaseRow( &pTmpRow);
m_uiNumRows--;
if ( uiOldLevel == uiLevel)
{
break;
}
}
// If there is no last row, then we need to set it to the current row.
if (pTmpRow == NULL)
{
m_pScrLastRow = pRow;
}
}
// If we just collapsed the anchored row, we don't want the anchor to
// interfere with getting the rest of the appropriate rows. If we leave the
// row anchor there, we will just expand again - oops.
if (m_pRowAnchor)
{
if (m_pRowAnchor->ui64NodeId == pRow->ui64NodeId)
{
f_free( &m_pRowAnchor);
}
}
// Now, let's see if we can fill the screen with more rows.
bIgnoreAnchor = !m_pScrLastRow->bExpanded;
while (m_uiNumRows < m_uiEditCanvasRows)
{
// Set the docList to sync with the last row displayed.
checkDocument(&m_pCurDoc, m_pScrLastRow);
if (RC_BAD( rc = getNextRow( m_pScrLastRow, &pTmpRow, TRUE, bIgnoreAnchor)))
{
goto Exit;
}
if (pTmpRow == NULL)
{
break;
}
m_pScrLastRow = pTmpRow;
bIgnoreAnchor = FALSE;
// Make sure our document list and last row are in sync. This prevents
// us from filling the screen with bogus rows.
}
// Resync the docList with the cursor row.
checkDocument(&m_pCurDoc, pRow);
Exit:
return rc;
}
/****************************************************************************
Desc:
*****************************************************************************/
/*
NODE_p F_DomEditor::findRow(
FLMUINT uiCollection,
FLMUINT uiDrn,
DME_ROW_INFO * pStartRow)
{
FLMUINT uiSourceCont;
FLMUINT uiSourceDrn;
DME_ROW_INFO * pTmpRow;
DME_ROW_INFO * pCurRow = m_pRoot;
FLMBOOL bForward = TRUE;
flmAssert( m_bSetupCalled == TRUE);
if( pStartRow)
{
pCurRow = getRootRow( pStartRow);
}
else if( m_pCurRow)
{
pTmpRow = getRootRow( m_pCurRow);
if( RC_OK( GedGetRecSource( pTmpNd, NULL,
&uiSourceCont, &uiSourceDrn)))
{
pCurNd = pTmpNd;
if( uiSourceCont > uiCollection ||
(uiSourceCont == uiCollection && uiSourceDrn > uiDrn))
{
pCurNd = getPrevRecord( pCurNd);
bForward = FALSE;
}
}
}
while( pCurNd)
{
if( RC_OK( GedGetRecSource( pCurNd, NULL,
&uiSourceCont, &uiSourceDrn)))
{
if( uiSourceCont == uiCollection && uiSourceDrn == uiDrn)
{
break;
}
if( bForward)
{
if( uiSourceCont > uiCollection ||
(uiSourceCont == uiCollection && uiSourceDrn > uiDrn))
{
pCurNd = NULL;
break;
}
}
else
{
if( uiSourceCont < uiCollection ||
(uiSourceCont == uiCollection && uiSourceDrn < uiDrn))
{
pCurNd = NULL;
break;
}
}
}
if( bForward)
{
pCurNd = getNextRecord( pCurNd);
}
else
{
pCurNd = getPrevRecord( pCurNd);
}
// Release CPU to prevent CPU hog
f_yieldCPU();
}
return( pCurNd);
}
*/
/****************************************************************************
Desc:
*****************************************************************************/
RCODE F_DomEditor::clearSelections( void)
{
RCODE rc = NE_XFLM_OK;
DME_ROW_INFO * pTmpRow = NULL;
FLMUINT uiFlags = 0;
flmAssert( m_bSetupCalled == TRUE);
/*
Clear the "selected" flags
*/
pTmpRow = m_pScrFirstRow;
while( pTmpRow)
{
(void)getControlFlags( pTmpRow, &uiFlags);
if( (uiFlags & F_DOMEDIT_FLAG_SELECTED))
{
uiFlags &= ~F_DOMEDIT_FLAG_SELECTED;
if( RC_BAD( rc = setControlFlags( pTmpRow, uiFlags)))
{
goto Exit;
}
}
pTmpRow = pTmpRow->pNext;
}
Exit:
return( rc);
}
/****************************************************************************
Desc:
*****************************************************************************/
RCODE F_DomEditor::setCurrentRow(
DME_ROW_INFO * pCurRow,
FLMUINT uiCurRow
)
{
RCODE rc = NE_XFLM_OK;
flmAssert( m_bSetupCalled == TRUE);
if (pCurRow)
{
refreshRow( m_uiCurRow, m_pCurRow, TRUE);
}
m_pCurRow = pCurRow;
if (uiCurRow <= m_uiEditCanvasRows)
{
m_uiCurRow = uiCurRow;
}
if (pCurRow)
{
refreshRow( m_uiCurRow, m_pCurRow, FALSE);
}
return( rc);
}
/****************************************************************************
Desc:
*****************************************************************************/
DME_ROW_INFO * F_DomEditor::getCurrentRow(
FLMUINT * puiCurRow
)
{
flmAssert( m_bSetupCalled == TRUE);
*puiCurRow = m_uiCurRow;
return( m_pCurRow);
}
/****************************************************************************
Desc:
*****************************************************************************/
RCODE F_DomEditor::setFirstRow(
DME_ROW_INFO * pRow
)
{
RCODE rc = NE_XFLM_OK;
flmAssert( m_bSetupCalled == TRUE);
m_pScrFirstRow = pRow;
return( rc);
}
/****************************************************************************
Desc:
*****************************************************************************/
RCODE F_DomEditor::getDisplayValue(
DME_ROW_INFO * pRow,
char * pszBuf,
FLMUINT uiBufSize)
{
RCODE rc = NE_XFLM_OK;
flmAssert( m_bSetupCalled == TRUE);
/*
This is a stupid check, but keep it for now.
*/
if( uiBufSize <= 32 || !pRow || !pszBuf)
{
flmAssert( 0);
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
*pszBuf = '\0';
if (pRow->uiLength > uiBufSize)
{
f_sprintf( pszBuf, "%*s...", uiBufSize - 3, pRow->puzValue);
}
else
{
f_sprintf( pszBuf, "%*s", pRow->uiLength, pRow->puzValue);
}
if( m_pEventHook)
{
if( RC_BAD( rc = m_pEventHook( this, F_DOMEDIT_EVENT_GETDISPVAL,
(void *)(pRow), m_EventData)))
{
goto Exit;
}
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Can we edit this row?
*****************************************************************************/
FLMBOOL F_DomEditor::canEditRow(
DME_ROW_INFO * pCurRow
)
{
RCODE rc = NE_XFLM_OK;
FLMBOOL bCanEdit = TRUE;
eDomNodeType eType;
FLMBOOL bHasAttrs;
flmAssert( m_bSetupCalled == TRUE);
if( m_bReadOnly || !pCurRow)
{
bCanEdit = FALSE;
goto Exit;
}
if (pCurRow->uiFlags & F_DOMEDIT_FLAG_ENDTAG ||
pCurRow->uiFlags & F_DOMEDIT_FLAG_COMMENT ||
pCurRow->uiFlags & F_DOMEDIT_FLAG_READ_ONLY)
{
bCanEdit = FALSE;
goto Exit;
}
if (pCurRow->ui64NodeId)
{
if (RC_BAD( rc = getDOMNode( this, pCurRow)))
{
bCanEdit = FALSE;
goto Exit;
}
eType = pCurRow->pDomNode->getNodeType();
switch (eType)
{
// case DATA_NODE:
// case CDATA_SECTION_NODE:
// case COMMENT_NODE:
// case ATTRIBUTE_NODE:
case ELEMENT_NODE:
if (RC_BAD( rc = pCurRow->pDomNode->hasAttributes( m_pDb, &bHasAttrs)))
{
goto Exit;
}
if (!bHasAttrs)
{
bCanEdit = FALSE;
}
else
{
bCanEdit = TRUE;
}
break;
case PROCESSING_INSTRUCTION_NODE:
case DOCUMENT_NODE:
case INVALID_NODE:
{
bCanEdit = FALSE;
break;
}
default:
{
bCanEdit = TRUE;
break;
}
}
}
Exit:
if (pCurRow->pDomNode)
{
pCurRow->pDomNode->Release();
pCurRow->pDomNode = NULL;
}
return( bCanEdit);
}
/****************************************************************************
Desc:
*****************************************************************************/
FLMBOOL F_DomEditor::canDeleteRow(
DME_ROW_INFO * pCurRow
)
{
FLMUINT uiFlags = 0;
FLMBOOL bCanDelete = TRUE;
flmAssert( m_bSetupCalled == TRUE);
if( m_bReadOnly || !pCurRow)
{
bCanDelete = FALSE;
goto Exit;
}
(void)getControlFlags( pCurRow, &uiFlags);
if( uiFlags & (F_DOMEDIT_FLAG_READ_ONLY | F_DOMEDIT_FLAG_NO_DELETE))
{
bCanDelete = FALSE;
goto Exit;
}
Exit:
return( bCanDelete);
}
/****************************************************************************
Desc: Retrieve the list of Documents in the database - return the selected
document.
*****************************************************************************/
RCODE F_DomEditor::retrieveDocumentList(
FLMUINT uiCollection,
FLMUINT64 * pui64NodeId,
FLMUINT * puiTermChar
)
{
DME_ROW_INFO * pTmpRow = NULL;
DME_ROW_INFO * pPriorRow = NULL;
FLMUINT uiFlags;
F_DomEditor * pDocumentList = NULL;
RCODE rc = NE_XFLM_OK;
F_DOMNode * pDOMNode = NULL;
F_DOMNode * pSiblingNode = NULL;
FLMUINT uiDocumentCount;
FLMUNICODE * puzTitle = NULL;
FLMUINT64 ui64DocumentID;
FLMBOOL bGotFirstDoc;
flmAssert( m_bSetupCalled == TRUE);
if( pui64NodeId)
{
*pui64NodeId = 0;
}
if( puiTermChar)
{
*puiTermChar = 0;
}
// Initialize the name table.
if( !m_pNameTable)
{
if( RC_BAD( rc = refreshNameTable()))
{
goto Exit;
}
}
if( (pDocumentList = f_new F_DomEditor) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
if( RC_BAD( rc = pDocumentList->Setup( m_pScreen)))
{
goto Exit;
}
pDocumentList->setParent( this);
pDocumentList->setReadOnly( TRUE);
pDocumentList->setShutdown( m_pbShutdown);
pDocumentList->setTitle( "Document List - Select One");
pDocumentList->setKeyHook( F_DomEditorSelectionKeyHook, 0);
pDocumentList->setSource( m_pDb, uiCollection);
if( m_pDb == NULL)
{
goto Exit;
}
// Get the document list.
uiDocumentCount = 0;
uiFlags = (F_DOMEDIT_FLAG_HIDE_LEVEL | F_DOMEDIT_FLAG_HIDE_EXPAND |
F_DOMEDIT_FLAG_LIST_ITEM | F_DOMEDIT_FLAG_READ_ONLY | F_DOMEDIT_FLAG_NODOM);
bGotFirstDoc = FALSE;
while (uiDocumentCount < m_uiEditCanvasRows)
{
if (!bGotFirstDoc)
{
if (RC_BAD( rc = m_pDb->getFirstDocument(
uiCollection, (IF_DOMNode **)&pDOMNode)))
{
goto Exit;
}
bGotFirstDoc = TRUE;
}
else
{
if (RC_BAD( rc = pDOMNode->getNextDocument(
m_pDb, (IF_DOMNode **)&pSiblingNode)))
{
if (rc != NE_XFLM_EOF_HIT && rc != NE_XFLM_DOM_NODE_NOT_FOUND)
{
goto Exit;
}
rc = NE_XFLM_OK;
break;
}
(void)pDOMNode->Release();
pDOMNode = pSiblingNode;
pSiblingNode = NULL;
}
if( RC_BAD( rc = pDOMNode->getNodeId( m_pDb, &ui64DocumentID)))
{
goto Exit;
}
if( RC_BAD( rc = makeNewRow( &pTmpRow, NULL, ui64DocumentID)))
{
goto Exit;
}
pTmpRow->uiIndex = uiDocumentCount;
pTmpRow->ui64DocId = ui64DocumentID;
pTmpRow->uiFlags = uiFlags;
// Link the rows into the list of titles to display.
if (RC_BAD( rc = pDocumentList->insertRow( pTmpRow, pPriorRow)))
{
goto Exit;
}
pPriorRow = pTmpRow;
pTmpRow = NULL;
uiDocumentCount++;
}
if (pDOMNode)
{
pDOMNode->Release();
pDOMNode = NULL;
}
pDocumentList->setDocList( TRUE);
// Set the rows...
pDocumentList->setCurrentAtTop();
if( RC_BAD( rc = pDocumentList->interactiveEdit( m_uiULX, m_uiULY, m_uiLRX, m_uiLRY)))
{
goto Exit;
}
if( (pTmpRow = pDocumentList->getScrFirstRow()) == NULL)
{
goto Exit;
}
while( pTmpRow)
{
pDocumentList->getControlFlags( pTmpRow, &uiFlags);
if( uiFlags & F_DOMEDIT_FLAG_SELECTED)
{
uiFlags &= ~F_DOMEDIT_FLAG_SELECTED;
pDocumentList->setControlFlags( pTmpRow, uiFlags);
if( pui64NodeId)
{
*pui64NodeId = pTmpRow->ui64NodeId;
}
pTmpRow = NULL;
break;
}
if (RC_BAD( rc = pDocumentList->getNextRow( pTmpRow, &pTmpRow)))
{
goto Exit;
}
}
if( puiTermChar)
{
*puiTermChar = pDocumentList->getLastKey();
}
Exit:
// Cleanup ...
f_free( &puzTitle);
if (pDocumentList)
{
pDocumentList->Release();
}
if (pTmpRow)
{
releaseRow( &pTmpRow);
}
if (pSiblingNode)
{
pSiblingNode->Release();
}
if (pDOMNode)
{
pDOMNode->Release();
}
return rc;
}
/****************************************************************************
Desc: Retrieve the range of nodes from the database...
*****************************************************************************/
RCODE F_DomEditor::retrieveNodeFromDb(
FLMUINT uiCollection,
FLMUINT64 ui64NodeId,
FLMUINT uiAttrNameId)
{
RCODE rc = NE_XFLM_OK;
F_DOMNode * pDomNode = NULL;
DME_ROW_INFO * pTmpRow = NULL;
DME_ROW_INFO * pPriorRow = NULL;
// Can we put this node on the screen?
if (m_uiNumRows < m_uiEditCanvasRows)
{
if (uiAttrNameId)
{
rc = m_pDb->getAttribute( uiCollection, ui64NodeId, uiAttrNameId,
(IF_DOMNode **)&pDomNode);
}
else
{
rc = m_pDb->getNode( uiCollection, ui64NodeId, &pDomNode);
}
if( RC_BAD( rc))
{
if( rc != NE_XFLM_NOT_FOUND &&
rc != NE_XFLM_EOF_HIT &&
rc != NE_XFLM_BOF_HIT &&
rc != NE_XFLM_DOM_NODE_NOT_FOUND)
{
goto Exit;
}
else
{
rc = NE_XFLM_OK;
goto Exit;
}
}
// Find the last row
pPriorRow = getScrLastRow();
// Now build the new rows
if (RC_BAD( rc = buildNewRow( -1,
pDomNode,
&pTmpRow)))
{
goto Exit;
}
if (RC_BAD( rc = insertRow( pTmpRow, pPriorRow)))
{
goto Exit;
}
// Make the new node current.
m_pCurRow = pTmpRow;
if (RC_BAD( rc = expandRow( pTmpRow, FALSE, NULL)))
{
goto Exit;
}
// We need to mark the starting row since the expansion is
// incomplete.
if (m_pRowAnchor)
{
f_free( &m_pRowAnchor);
}
if( RC_BAD( rc = f_alloc( sizeof( DME_ROW_ANCHOR), &m_pRowAnchor)))
{
goto Exit;
}
f_memset( m_pRowAnchor, 0, sizeof(DME_ROW_ANCHOR));
m_pRowAnchor->ui64NodeId = pTmpRow->ui64NodeId;
m_pRowAnchor->uiAnchorLevel = pTmpRow->uiLevel;
m_pRowAnchor->bSingleLevel = FALSE;
}
Exit:
if( pDomNode)
{
pDomNode->Release();
}
return( rc);
}
/****************************************************************************
Desc:
*****************************************************************************/
RCODE F_DomEditor::displayAttributes(
DME_ROW_INFO * pRow
)
{
RCODE rc = NE_XFLM_OK;
F_DomEditor * pAttrList = NULL;
F_DOMNode * pDOMNode = NULL;
F_DOMNode * pAttrNode = NULL;
FLMUINT uiAttributeCount;
FLMBOOL bGotFirstAttr;
FLMUINT uiFlags;
FLMUINT64 ui64DocumentID;
FLMUINT uiAttrNameId;
DME_ROW_INFO * pTmpRow=NULL;
DME_ROW_INFO * pPriorRow=NULL;
flmAssert( m_bSetupCalled == TRUE);
if (!pRow)
{
displayMessage(
"Node DOM Nodes to display attributes for",
NE_XFLM_FAILURE, NULL, FLM_RED, FLM_WHITE);
goto Exit;
}
if ( pRow->eType != ELEMENT_NODE)
{
displayMessage(
"DOM Node is not an ELEMENT_NODE",
NE_XFLM_FAILURE, NULL, FLM_RED, FLM_WHITE);
goto Exit;
}
if (!pRow->bHasAttributes)
{
displayMessage(
"DOM Node does not have attributes",
NE_XFLM_FAILURE, NULL, FLM_RED, FLM_WHITE);
goto Exit;
}
// Make sure we have a name table....
if( !m_pNameTable)
{
if( RC_BAD( rc = refreshNameTable()))
{
goto Exit;
}
}
if( (pAttrList = f_new F_DomEditor) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
if( RC_BAD( rc = pAttrList->Setup( m_pScreen)))
{
goto Exit;
}
pAttrList->setParent( this);
pAttrList->setReadOnly( FALSE); // Allow editing these attributes.
pAttrList->setShutdown( m_pbShutdown);
pAttrList->setTitle( "Element Attribute List");
pAttrList->setKeyHook( F_DomEditorSelectionKeyHook, 0);
pAttrList->setSource( m_pDb, m_uiCollection);
if( m_pDb == NULL)
{
goto Exit;
}
// Get the DOMnode of the current element.
if (RC_BAD( rc = getDomNode( pRow->ui64NodeId,
pRow->eType == ATTRIBUTE_NODE
? pRow->uiNameId
: 0,
&pDOMNode)))
{
goto Exit;
}
// Get the attribute list.
uiAttributeCount = 0;
uiFlags = (F_DOMEDIT_FLAG_HIDE_LEVEL | F_DOMEDIT_FLAG_HIDE_EXPAND |
F_DOMEDIT_FLAG_NOPARENT | F_DOMEDIT_FLAG_NOCHILD);
bGotFirstAttr = FALSE;
while (uiAttributeCount < m_uiEditCanvasRows)
{
if (!bGotFirstAttr)
{
if (RC_BAD( rc = pDOMNode->getFirstAttribute( m_pDb,
(IF_DOMNode **)&pAttrNode)))
{
goto Exit;
}
bGotFirstAttr = TRUE;
(void)pDOMNode->Release();
pDOMNode = NULL;
}
else
{
if (RC_BAD( rc = pAttrNode->getNextSibling(
m_pDb, (IF_DOMNode **)&pAttrNode)))
{
if (rc != NE_XFLM_EOF_HIT && rc != NE_XFLM_DOM_NODE_NOT_FOUND)
{
goto Exit;
}
rc = NE_XFLM_OK;
break;
}
}
if( RC_BAD( rc = pAttrNode->getParentId( m_pDb, &ui64DocumentID)))
{
goto Exit;
}
if (RC_BAD( rc = pAttrNode->getNameId( m_pDb, &uiAttrNameId)))
{
goto Exit;
}
if (RC_BAD( rc = makeNewRow( &pTmpRow, NULL, ui64DocumentID)))
{
goto Exit;
}
pTmpRow->eType = ATTRIBUTE_NODE;
pTmpRow->uiNameId = uiAttrNameId;
pTmpRow->uiIndex = uiAttributeCount;
pTmpRow->ui64DocId = ui64DocumentID;
pTmpRow->uiFlags = uiFlags;
// Link the rows into the list of titles to display.
if (RC_BAD( rc = pAttrList->insertRow( pTmpRow, pPriorRow)))
{
goto Exit;
}
pPriorRow = pTmpRow;
pTmpRow = NULL;
uiAttributeCount++;
}
if (pDOMNode)
{
pDOMNode->Release();
pDOMNode = NULL;
}
pAttrList->setDocList( FALSE);
// Set the rows...
pAttrList->setCurrentAtTop();
if( RC_BAD( rc = pAttrList->interactiveEdit( m_uiULX, m_uiULY, m_uiLRX, m_uiLRY)))
{
goto Exit;
}
Exit:
// Cleanup ...
if (pAttrList)
{
pAttrList->Release();
}
if (pTmpRow)
{
releaseRow( &pTmpRow);
}
if (pAttrNode)
{
pAttrNode->Release();
}
if (pDOMNode)
{
pDOMNode->Release();
}
return rc;
}
/****************************************************************************
Desc:
*****************************************************************************/
FSTATIC void domGetOutputFileName(
FTX_WINDOW * pWindow,
char * pszOutputFileName,
FLMUINT uiOutputFileNameBufSize)
{
FLMUINT uiChar;
*pszOutputFileName = 0;
FTXWinPrintf( pWindow, "Enter Output File Name: ");
if( RC_BAD( FTXLineEdit( pWindow, pszOutputFileName,
uiOutputFileNameBufSize - 1, uiOutputFileNameBufSize - 1,
NULL, &uiChar)))
{
*pszOutputFileName = 0;
}
FTXWinPrintf( pWindow, "\n");
}
/****************************************************************************
Desc:
*****************************************************************************/
RCODE F_DomEditor::displayNodeInfo(
DME_ROW_INFO * pRow
)
{
RCODE rc = NE_XFLM_OK;
FTX_WINDOW * pWindow = NULL;
FLMUINT uiChar;
FLMUINT uiTermChar;
char szOutputFile [200];
if (RC_BAD( rc = createStatusWindow(
"Node Information",
FLM_GREEN, FLM_WHITE, NULL, NULL, &pWindow)))
{
goto Exit;
}
FTXWinOpen( pWindow);
for (;;)
{
if (m_uiCollection == XFLM_DATA_COLLECTION)
{
FTXWinPrintf( pWindow, "\nInfo Type (N,ENTER=Node Only, S=Subtree, D=directory View, ESC=Cancel): ");
}
else
{
FTXWinPrintf( pWindow, "\nInfo Type (N,ENTER=Node Only, S=Subtree, ESC=Cancel): ");
}
FTXWinInputChar( pWindow, &uiChar);
FTXWinSetCursorPos( pWindow, 0, 0);
FTXWinClear( pWindow);
switch (uiChar)
{
case 'D':
case 'd':
if (m_uiCollection == XFLM_DATA_COLLECTION)
{
domGetOutputFileName( pWindow, szOutputFile, sizeof( szOutputFile));
domDisplayEntryInfo( pWindow, szOutputFile, m_pDb, pRow->ui64NodeId, TRUE);
}
else
{
FTXDisplayMessage( m_pScreen, m_bMonochrome ? FLM_LIGHTGRAY : FLM_RED,
m_bMonochrome ? FLM_BLACK : FLM_WHITE,
"Invalid option", NULL, &uiTermChar);
uiChar = 0;
}
break;
case 'S':
case 's':
domGetOutputFileName( pWindow, szOutputFile, sizeof( szOutputFile));
domDisplayNodeInfo( pWindow, szOutputFile, m_pDb, m_uiCollection, pRow->ui64NodeId, TRUE, TRUE);
break;
case 'N':
case 'n':
case FKB_ENTER:
domGetOutputFileName( pWindow, szOutputFile, sizeof( szOutputFile));
domDisplayNodeInfo( pWindow, szOutputFile, m_pDb, m_uiCollection, pRow->ui64NodeId, FALSE, TRUE);
break;
case FKB_ESC:
break;
default:
FTXDisplayMessage( m_pScreen, m_bMonochrome ? FLM_LIGHTGRAY : FLM_RED,
m_bMonochrome ? FLM_BLACK : FLM_WHITE,
"Invalid option", NULL, &uiTermChar);
uiChar = 0;
break;
}
if (uiChar)
{
break;
}
}
Exit:
if (pWindow)
{
FTXWinFree( &pWindow);
}
return rc;
}
/****************************************************************************
Desc:
*****************************************************************************/
RCODE F_DomEditor::exportNode(
DME_ROW_INFO * pRow
)
{
RCODE rc = NE_XFLM_OK;
FTX_WINDOW * pWindow = NULL;
IF_DOMNode * pNode = NULL;
FLMUINT uiChar;
FLMUINT uiTermChar;
char szFileName [80];
eExportFormatType eFormat = XFLM_EXPORT_INDENT;
IF_OStream * pFileOStream = NULL;
IF_DbSystem * pDbSystem = NULL;
if( RC_BAD( rc = FlmAllocDbSystem( &pDbSystem)))
{
goto Exit;
}
if (RC_BAD( rc = createStatusWindow(
"Export Node Subtree",
FLM_GREEN, FLM_WHITE, NULL, NULL, &pWindow)))
{
goto Exit;
}
FTXWinOpen( pWindow);
szFileName [0] = 0;
FTXWinClear( pWindow);
for (;;)
{
FTXWinSetCursorPos( pWindow, 2, 1);
FTXWinClearLine( pWindow, 2, 1);
FTXWinPrintf( pWindow, "Enter Export File Name: ");
if( RC_BAD( rc = FTXLineEdit( pWindow, szFileName,
sizeof( szFileName) - 1, sizeof( szFileName) - 1,
NULL, &uiChar)))
{
goto Exit;
}
if (!szFileName [0])
{
goto Exit;
}
if (RC_BAD( rc = pDbSystem->openFileOStream( szFileName,
TRUE, &pFileOStream)))
{
displayMessage( "Error creating export file",
rc, NULL, FLM_RED, FLM_WHITE);
}
else
{
break;
}
}
for (;;)
{
FTXWinSetCursorPos( pWindow, 2, 2);
FTXWinClearLine( pWindow, 2, 2);
FTXWinPrintf( pWindow,
"Format (I,ENTER=Indent, N=Newline, D=Indent Data, X=None, ESC=Cancel): ");
FTXWinInputChar( pWindow, &uiChar);
switch (uiChar)
{
case 'I':
case 'i':
case FKB_ENTER:
eFormat = XFLM_EXPORT_INDENT;
FTXWinPrintf( pWindow, "I");
break;
case 'N':
case 'n':
eFormat = XFLM_EXPORT_NEW_LINE;
FTXWinPrintf( pWindow, "N");
break;
case 'D':
case 'd':
eFormat = XFLM_EXPORT_INDENT_DATA;
FTXWinPrintf( pWindow, "D");
break;
case 'X':
case 'x':
eFormat = XFLM_EXPORT_NO_FORMAT;
FTXWinPrintf( pWindow, "X");
break;
case FKB_ESC:
goto Exit;
default:
FTXDisplayMessage( m_pScreen, m_bMonochrome ? FLM_LIGHTGRAY : FLM_RED,
m_bMonochrome ? FLM_BLACK : FLM_WHITE,
"Invalid option", NULL, &uiTermChar);
uiChar = 0;
break;
}
if (uiChar)
{
break;
}
}
if (pRow->eType == ATTRIBUTE_NODE)
{
rc = m_pDb->getAttribute( m_uiCollection, pRow->ui64NodeId,
pRow->uiNameId,
(IF_DOMNode **)&pNode);
}
else
{
rc = m_pDb->getNode( m_uiCollection, pRow->ui64NodeId, &pNode);
}
if (RC_BAD( rc))
{
displayMessage( "Error getting node", rc, NULL, FLM_RED, FLM_WHITE);
goto Exit;
}
if( RC_BAD( rc = m_pDb->exportXML( pNode, pFileOStream, eFormat)))
{
displayMessage( "Error exporting data", rc, NULL, FLM_RED, FLM_WHITE);
goto Exit;
}
FTXWinSetCursorPos( pWindow, 2, 3);
FTXWinClearLine( pWindow, 2, 3);
FTXWinPrintf( pWindow, "Export Done, press any character to exit: ");
FTXWinInputChar( pWindow, &uiChar);
Exit:
if (pFileOStream)
{
pFileOStream->Release();
}
if (pNode)
{
pNode->Release();
}
if (pWindow)
{
FTXWinFree( &pWindow);
}
if( pDbSystem)
{
pDbSystem->Release();
}
return rc;
}
/****************************************************************************
Desc: Retrieve information about the document and add it to the document linked
list.
*****************************************************************************/
RCODE F_DomEditor::addDocumentToList(
FLMUINT uiCollection,
FLMUINT64 ui64DocumentId
)
{
RCODE rc = NE_XFLM_OK;
F_DOMNode * pDomNode = NULL;
DME_ROW_INFO * pTmpRow;
DME_ROW_INFO * pLastRow = m_pDocList;
if( RC_BAD( rc = m_pDb->getNode( uiCollection,
ui64DocumentId,
&pDomNode)))
{
if( rc != NE_XFLM_NOT_FOUND && rc != NE_XFLM_EOF_HIT &&
rc != NE_XFLM_BOF_HIT && rc != NE_XFLM_DOM_NODE_NOT_FOUND)
{
goto Exit;
}
else
{
rc = NE_XFLM_OK;
}
}
// Now build the new row
if (RC_BAD( buildNewRow( -1,
pDomNode,
&pTmpRow)))
{
goto Exit;
}
if (m_pDocList == NULL)
{
m_pDocList = pTmpRow;
m_pCurDoc = pTmpRow;
}
else
{
for (;;)
{
if (pLastRow->pNext)
{
pLastRow = pLastRow->pNext;
}
else
{
pLastRow->pNext = pTmpRow;
pTmpRow->pPrev = pLastRow;
break;
}
}
if (m_pCurRow->ui64DocId != m_pCurDoc->ui64DocId)
{
m_pCurDoc = pTmpRow;
}
}
Exit:
if (pDomNode)
{
pDomNode->Release();
}
return rc;
}
/****************************************************************************
Desc: Allows the user to interactively select a Collection
*****************************************************************************/
RCODE F_DomEditor::selectCollection(
FLMUINT * puiCollection,
FLMUINT * puiTermChar)
{
RCODE rc = NE_XFLM_OK;
DME_ROW_INFO * pTmpRow = NULL;
DME_ROW_INFO * pPrevRow = NULL;
FLMUINT uiFlags;
FLMUNICODE uzItemName[ 128];
FLMUINT uiId;
FLMUINT uiNextPos;
F_DomEditor * pCollectionList = NULL;
flmAssert( m_bSetupCalled == TRUE);
if( puiCollection)
{
*puiCollection = 0;
}
if( puiTermChar)
{
*puiTermChar = 0;
}
// Initialize the name table.
if( !m_pNameTable)
{
if( RC_BAD( rc = refreshNameTable()))
{
goto Exit;
}
}
if( (pCollectionList = f_new F_DomEditor) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
if( RC_BAD( rc = pCollectionList->Setup( m_pScreen)))
{
goto Exit;
}
pCollectionList->setParent( this);
pCollectionList->setReadOnly( TRUE);
pCollectionList->setShutdown( m_pbShutdown);
pCollectionList->setTitle( "Collections - Select One");
pCollectionList->setKeyHook( F_DomEditorSelectionKeyHook, 0);
pCollectionList->setSource( m_pDb, XFLM_DICT_COLLECTION);
if( m_pDb == NULL)
{
goto Exit;
}
uiFlags = (F_DOMEDIT_FLAG_HIDE_LEVEL | F_DOMEDIT_FLAG_HIDE_EXPAND |
F_DOMEDIT_FLAG_LIST_ITEM | F_DOMEDIT_FLAG_READ_ONLY);
asciiToUnicode( "Default Data", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], 0, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
pTmpRow->uiNameId = XFLM_DATA_COLLECTION;
if (RC_BAD( rc = pCollectionList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "Dictionary Definitions", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], 0, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
pTmpRow->uiNameId = XFLM_DICT_COLLECTION;
if (RC_BAD( rc = pCollectionList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "Maintenance", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], 0, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
pTmpRow->uiNameId = XFLM_MAINT_COLLECTION;
if (RC_BAD( rc = pCollectionList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
uiNextPos = 0;
while( RC_OK( rc = m_pNameTable->getNextTagTypeAndNameOrder(
ELM_COLLECTION_TAG,
&uiNextPos, uzItemName, NULL, sizeof( uzItemName), &uiId)))
{
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], 0, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
pTmpRow->uiNameId = uiId;
if (RC_BAD( rc = pCollectionList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
}
if (rc != NE_XFLM_EOF_HIT)
{
goto Exit;
}
rc = NE_XFLM_OK;
// Set the start row.
pCollectionList->setCurrentAtTop();
if( RC_BAD( rc = pCollectionList->interactiveEdit(
m_uiULX, m_uiULY, m_uiLRX, m_uiLRY)))
{
goto Exit;
}
if( (pTmpRow = pCollectionList->getScrFirstRow()) == NULL)
{
goto Exit;
}
while( pTmpRow)
{
pCollectionList->getControlFlags( pTmpRow, &uiFlags);
if( uiFlags & F_DOMEDIT_FLAG_SELECTED)
{
uiFlags &= ~F_DOMEDIT_FLAG_SELECTED;
pCollectionList->setControlFlags( pTmpRow, uiFlags);
if( puiCollection)
{
*puiCollection = pTmpRow->uiNameId;
}
pTmpRow = NULL;
break;
}
if (RC_BAD( rc = pCollectionList->getNextRow( pTmpRow, &pTmpRow)))
{
goto Exit;
}
}
if( puiTermChar)
{
*puiTermChar = pCollectionList->getLastKey();
}
Exit:
if( pCollectionList)
{
pCollectionList->Release();
pCollectionList = NULL;
}
if (pTmpRow)
{
releaseRow( &pTmpRow);
}
return( rc);
}
/****************************************************************************
Desc: Creates a new DME_ROW_INFO structure and stores the puzValue and Id.
NOTE: puzValue must be a null terminated string.
*****************************************************************************/
FSTATIC RCODE makeNewRow(
DME_ROW_INFO ** ppTmpRow,
FLMUNICODE * puzValue,
FLMUINT64 ui64Id,
FLMBOOL bUseValue
)
{
RCODE rc = NE_XFLM_OK;
DME_ROW_INFO * pTmpRow = NULL;
FLMUINT uiLength;
if( RC_BAD( rc = f_alloc( sizeof( DME_ROW_INFO), &pTmpRow)))
{
goto Exit;
}
f_memset( pTmpRow, 0, sizeof( DME_ROW_INFO));
if (bUseValue)
{
uiLength = unicodeStrLen( puzValue);
if (RC_BAD( rc = f_calloc( (uiLength*2)+2, &pTmpRow->puzValue)))
{
goto Exit;
}
f_memcpy( pTmpRow->puzValue, puzValue, (uiLength*2)+2);
pTmpRow->uiLength = uiLength*2;
}
pTmpRow->ui64NodeId = ui64Id;
pTmpRow->bUseValue = bUseValue;
*ppTmpRow = pTmpRow;
pTmpRow = NULL;
Exit:
if (pTmpRow)
{
releaseRow( &pTmpRow);
}
return rc;
}
/****************************************************************************
Desc: Calculates the length of a Unicode string.
*****************************************************************************/
FSTATIC FLMUINT unicodeStrLen(
FLMUNICODE * puzStr
)
{
FLMUINT uiLength;
FLMUNICODE * puzTmp;
if (!puzStr)
{
return 0;
}
for (puzTmp = puzStr, uiLength = 0;
*puzTmp != (FLMUNICODE)0;
uiLength++, puzTmp++);
return uiLength;
}
/****************************************************************************
Name: getNumber
Desc: Converts a text string to a number
*****************************************************************************/
RCODE F_DomEditor::getNumber(
char * pszBuf,
FLMUINT64 * pui64Value,
FLMINT64 * pi64Value)
{
char * pszTmp = NULL;
FLMUINT64 ui64Value = 0;
FLMUINT uiDigits = 0;
FLMUINT uiHexOffset = 0;
FLMBOOL bNeg = FALSE;
FLMBOOL bHex = FALSE;
RCODE rc = NE_XFLM_OK;
if( pui64Value)
{
*pui64Value = 0;
}
if( pi64Value)
{
*pi64Value = 0;
}
if( f_strnicmp( pszBuf, "0x", 2) == 0)
{
uiHexOffset = 2;
bHex = TRUE;
}
else if( *pszBuf == 'x' || *pszBuf == 'X')
{
uiHexOffset = 1;
bHex = TRUE;
}
else
{
pszTmp = pszBuf;
while( *pszTmp)
{
if( (*pszTmp >= '0' && *pszTmp <= '9') ||
(*pszTmp >= 'A' && *pszTmp <= 'F') ||
(*pszTmp >= 'a' && *pszTmp <= 'f') ||
(*pszTmp == '-'))
{
if( (*pszTmp >= 'A' && *pszTmp <= 'F') ||
(*pszTmp >= 'a' && *pszTmp <= 'f'))
{
bHex = TRUE;
}
}
else
{
rc = RC_SET( NE_XFLM_CONV_ILLEGAL);
goto Exit;
}
pszTmp++;
}
uiHexOffset = 0;
}
if( bHex)
{
pszTmp = &(pszBuf[ uiHexOffset]);
uiDigits = f_strlen( pszTmp);
if( !uiDigits)
{
rc = RC_SET( NE_XFLM_CONV_ILLEGAL);
goto Exit;
}
while( *pszTmp)
{
ui64Value <<= 4;
if( *pszTmp >= '0' && *pszTmp <= '9')
{
ui64Value |= *pszTmp - '0';
}
else if( *pszTmp >= 'a' && *pszTmp <= 'f')
{
ui64Value |= (*pszTmp - 'a') + 10;
}
else if( *pszTmp >= 'A' && *pszTmp <= 'F')
{
ui64Value |= (*pszTmp - 'A') + 10;
}
else
{
rc = RC_SET( NE_XFLM_CONV_ILLEGAL);
goto Exit;
}
pszTmp++;
}
}
else if( (*pszBuf >= '0' && *pszBuf <= '9') || *pszBuf == '-')
{
pszTmp = pszBuf;
if( *pszTmp == '-')
{
bNeg = TRUE;
pszTmp++;
}
uiDigits = f_strlen( pszTmp);
while( *pszTmp)
{
if( *pszTmp >= '0' && *pszTmp <= '9')
{
FLMUINT64 ui64NewVal = ui64Value;
if( ui64NewVal > (~((FLMUINT64)0) / 10))
{
rc = RC_SET( NE_XFLM_CONV_NUM_OVERFLOW);
goto Exit;
}
ui64NewVal *= 10;
ui64NewVal += *pszTmp - '0';
if( ui64NewVal < ui64Value)
{
rc = RC_SET( NE_XFLM_CONV_NUM_OVERFLOW);
goto Exit;
}
ui64Value = ui64NewVal;
}
else
{
rc = RC_SET( NE_XFLM_CONV_BAD_DIGIT);
goto Exit;
}
pszTmp++;
}
}
else
{
rc = RC_SET( NE_XFLM_CONV_BAD_DIGIT);
goto Exit;
}
if( bNeg)
{
if( pi64Value)
{
#if defined( FLM_GNUC)
if( ui64Value > 0x7FFFFFFFFFFFFFFFULL)
#else
if( ui64Value > 0x7FFFFFFFFFFFFFFF)
#endif
{
rc = RC_SET( NE_XFLM_CONV_NUM_UNDERFLOW);
goto Exit;
}
*pi64Value = -((FLMINT64)ui64Value);
}
else
{
rc = RC_SET( NE_XFLM_CONV_ILLEGAL);
goto Exit;
}
}
else
{
if( pui64Value)
{
*pui64Value = ui64Value;
}
else
{
rc = RC_SET( NE_XFLM_CONV_ILLEGAL);
goto Exit;
}
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Shows a help screen
*****************************************************************************/
RCODE F_DomEditor::showHelp(
FLMUINT * puiKeyRV
)
{
RCODE rc = NE_XFLM_OK;
DME_ROW_INFO * pPrevRow = NULL;
DME_ROW_INFO * pTmpRow = NULL;
FLMUINT uiFlags;
F_DomEditor * pHelpList = NULL;
FLMUNICODE uzItemName[ 128];
flmAssert( m_bSetupCalled == TRUE);
if( (pHelpList = f_new F_DomEditor) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
if( RC_BAD( rc = pHelpList->Setup( m_pScreen)))
{
goto Exit;
}
pHelpList->setParent( this);
pHelpList->setReadOnly( TRUE);
pHelpList->setShutdown( m_pbShutdown);
pHelpList->setTitle( "HELP");
pHelpList->setKeyHook( F_DomEditorSelectionKeyHook, 0);
pHelpList->setSource( m_pDb, m_uiCollection);
uiFlags = (F_DOMEDIT_FLAG_HIDE_LEVEL | F_DOMEDIT_FLAG_HIDE_EXPAND |
F_DOMEDIT_FLAG_LIST_ITEM | F_DOMEDIT_FLAG_READ_ONLY);
asciiToUnicode( "Keyboard Commands", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], 0, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "? Help (this screen)", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], (FLMUINT)'?', TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "# Database statistics", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], '#', TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "UP Position cursor to the previous field", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], FKB_UP, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "DOWN Position cursor to the next field", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], FKB_DOWN, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "PG UP Position cursor to the previous page", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], FKB_PGUP, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "PG DOWN Position cursor to the next page", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], FKB_PGDN, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "HOME Position cursor to the top of the buffer", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], FKB_HOME, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "END Position cursor to the bottom of the buffer", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], FKB_END, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "DELETE Delete the current node", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], FKB_DELETE, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "A Display DOM Node attributes", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], 'A', TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "C Clear all entries from the buffer", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], 'C', TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "D Display Node Information", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], 'C', TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "F Find nodes in the database via an XPATH query", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], 'F', TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "I Show index keys and references", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], 'I', TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "L List documents to select", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], 'L', TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "N add a New node to the database", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], 'N', TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "R Retrieve a node from the database", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], 'R', TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "S Refresh the current display window", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], 'S', TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "V View the current node value", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], 'V', TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "X Export Node", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], 'C', TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "RIGHT Expand context one level", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], FKB_RIGHT, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "LEFT Collapse context", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], FKB_LEFT, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "PLUS Expand to full context", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], FKB_PLUS, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "MINUS collapse context", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], FKB_MINUS, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "ENTER Edit the current node's value", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], FKB_ENTER, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "F8 Index manager", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], FKB_F8, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "F9 Memory manager", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], FKB_F9, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "F10 Toggle display colors on/off", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], FKB_F10, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "ESC, Q, Exit", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], 'Q', TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pHelpList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
// Call the applications help hook to extend the help screen.
// if( m_pHelpHook)
// {
// if( RC_BAD( rc = m_pHelpHook( this, m_pHelpHook)))
// {
// goto Exit;
// }
// }
pHelpList->setCurrentAtTop();
// Show the help screen
if( RC_BAD( rc = pHelpList->interactiveEdit( m_uiULX, m_uiULY, m_uiLRX,
m_uiLRY, TRUE, 0)))
{
goto Exit;
}
if( pHelpList->getLastKey() != FKB_ENTER)
{
goto Exit;
}
if ( puiKeyRV)
{
*puiKeyRV = 0;
}
// Find the selected item
if( (pTmpRow = pHelpList->getScrFirstRow()) == NULL)
{
goto Exit;
}
while( pTmpRow)
{
pHelpList->getControlFlags( pTmpRow, &uiFlags);
if( uiFlags & F_DOMEDIT_FLAG_SELECTED)
{
if( puiKeyRV)
{
*puiKeyRV = (FLMUINT)pTmpRow->ui64NodeId;
}
pTmpRow = NULL;
break;
}
if (RC_BAD( rc = pHelpList->getNextRow( pTmpRow, &pTmpRow)))
{
goto Exit;
}
}
Exit:
if( pHelpList)
{
pHelpList->Release();
}
return( rc);
}
/****************************************************************************
Name: createStatusWindow
Desc: Creates a window for displaying an operation's status
*****************************************************************************/
RCODE F_DomEditor::createStatusWindow(
const char * pszTitle,
eColorType uiBack,
eColorType uiFore,
FLMUINT * puiCols,
FLMUINT * puiRows,
FTX_WINDOW ** ppWindow)
{
FLMUINT uiNumRows;
FLMUINT uiNumCols;
FLMUINT uiNumWinRows = 0;
FLMUINT uiNumWinCols = 0;
FTX_WINDOW * pWindow = NULL;
RCODE rc = NE_XFLM_OK;
*ppWindow = NULL;
FTXScreenGetSize( m_pScreen, &uiNumCols, &uiNumRows);
if( puiCols)
{
uiNumWinCols = *puiCols;
}
if( puiRows)
{
uiNumWinRows = *puiRows;
}
if( uiNumWinCols <= 2 || uiNumWinRows < 3)
{
uiNumWinCols = uiNumCols - 2;
uiNumWinRows = uiNumRows - 2;
}
if( RC_BAD( rc = FTXWinInit( m_pScreen, uiNumWinCols,
uiNumWinRows, &pWindow)))
{
goto Exit;
}
if( puiCols)
{
*puiCols = uiNumWinCols;
}
if( puiRows)
{
*puiRows = uiNumWinRows;
}
FTXWinMove( pWindow, (FLMUINT)((uiNumCols - uiNumWinCols) / 2),
(FLMUINT)((uiNumRows - uiNumWinRows) / 2));
FTXWinSetScroll( pWindow, TRUE);
FTXWinSetLineWrap( pWindow, TRUE);
FTXWinSetCursorType( pWindow, FLM_CURSOR_INVISIBLE);
if( m_bMonochrome)
{
uiBack = FLM_LIGHTGRAY;
uiFore = FLM_BLACK;
FTXWinSetBackFore( pWindow, uiBack, uiFore);
}
else
{
FTXWinSetBackFore( pWindow, uiBack, uiFore);
}
FTXWinClear( pWindow);
FTXWinDrawBorder( pWindow);
if( pszTitle)
{
FTXWinSetTitle( pWindow, pszTitle, uiBack, uiFore);
}
*ppWindow = pWindow;
Exit:
return( rc);
}
/****************************************************************************
Name: ViewOnlyKeyHook
*****************************************************************************/
FSTATIC RCODE f_ViewOnlyKeyHook(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pCurRow,
FLMUINT uiKeyIn,
FLMUINT * puiKeyOut,
void * //pvKeyData
)
{
RCODE rc = NE_XFLM_OK;
switch( uiKeyIn)
{
case FKB_HOME:
case FKB_END:
case FKB_UP:
case FKB_DOWN:
case FKB_PGUP:
case FKB_PGDN:
case FKB_ESCAPE:
{
*puiKeyOut = uiKeyIn;
break;
}
// Special case
case FKB_DELETE:
{
*puiKeyOut = 0;
if (pCurRow->uiFlags & F_DOMEDIT_FLAG_COMMENT)
{
if (RC_BAD( rc = pDomEditor->viewOnlyDeleteIxKey()))
{
goto Exit;
}
}
break;
}
default:
{
*puiKeyOut = 0;
break;
}
}
Exit:
return( rc);
}
/****************************************************************************
Name: f_KeyEditorKeyHook
*****************************************************************************/
FSTATIC RCODE f_KeyEditorKeyHook(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pCurRow,
FLMUINT uiKeyIn,
FLMUINT * puiKeyOut,
void * //pvKeyData
)
{
RCODE rc = NE_XFLM_OK;
DME_ROW_INFO * pTmpRow = NULL;
FLMUINT uiCurRow;
switch( uiKeyIn)
{
case FKB_UP:
{
(void)pDomEditor->getCurrentRow( &uiCurRow);
if (uiCurRow)
{
if (RC_BAD( rc = pDomEditor->getPrevRow( pCurRow,
&pTmpRow,
FALSE)))
{
goto Exit;
}
if (pTmpRow != NULL)
{
uiCurRow--;
if ( RC_BAD( rc = pDomEditor->setCurrentRow( pTmpRow, uiCurRow)))
{
goto Exit;
}
}
}
*puiKeyOut = 0;
break;
}
case FKB_DOWN:
{
(void)pDomEditor->getCurrentRow( &uiCurRow);
if (RC_BAD( rc = pDomEditor->getNextRow(
pCurRow, &pTmpRow, FALSE)))
{
goto Exit;
}
if (pTmpRow != NULL)
{
uiCurRow++;
if ( RC_BAD( rc = pDomEditor->setCurrentRow( pTmpRow, uiCurRow)))
{
goto Exit;
}
}
*puiKeyOut = 0;
break;
}
case FKB_ENTER:
{
if( !pDomEditor->canEditRow( pCurRow))
{
pDomEditor->displayMessage( "The row cannot be edited",
RC_SET( NE_XFLM_ILLEGAL_OP), NULL, FLM_RED, FLM_WHITE);
}
else if( RC_BAD( rc = pDomEditor->editIndexRow( pCurRow)))
{
pDomEditor->displayMessage( "The field could not be edited", rc,
NULL, FLM_RED, FLM_WHITE);
}
*puiKeyOut = 0;
break;
}
case FKB_ESCAPE: /* Quit key editor */
// case FKB_ALT_Q: /* Done editing keys */
case FKB_ALT_Z: /* Done, but don't quit */
{
*puiKeyOut = uiKeyIn;
break;
}
case 'n':
case 'N':
{
// Option to edit the node id.
if( !pDomEditor->canEditRow( pCurRow))
{
pDomEditor->displayMessage( "The row cannot be edited",
RC_SET( NE_XFLM_ILLEGAL_OP), NULL, FLM_RED, FLM_WHITE);
}
else if( RC_BAD( rc = pDomEditor->editIndexNode( pCurRow)))
{
pDomEditor->displayMessage( "The field could not be edited", rc,
NULL, FLM_RED, FLM_WHITE);
}
*puiKeyOut = 0;
break;
}
default:
{
*puiKeyOut = 0;
break;
}
}
Exit:
return( rc);
}
/****************************************************************************
Name: SelectionOnlyKeyHook
*****************************************************************************/
RCODE F_DomEditorSelectionKeyHook(
F_DomEditor *, //pDomEditor,
DME_ROW_INFO *, //pCurRow,
FLMUINT uiKeyIn,
FLMUINT * puiKeyOut,
void * //pvKeyData
)
{
RCODE rc = NE_XFLM_OK;
switch( uiKeyIn)
{
case FKB_HOME:
case FKB_END:
case FKB_UP:
case FKB_DOWN:
case FKB_PGUP:
case FKB_PGDN:
case FKB_ESCAPE:
case FKB_ENTER:
case FKB_DELETE:
{
*puiKeyOut = uiKeyIn;
break;
}
default:
{
*puiKeyOut = 0;
break;
}
}
return( rc);
}
/***************************************************************************
Name:
Desc:
****************************************************************************/
RCODE F_DomEditor::globalConfig(
FLMUINT uiOption)
{
RCODE rc = NE_XFLM_OK;
if( m_pDb == NULL)
{
rc = RC_SET( NE_XFLM_NOT_IMPLEMENTED);
goto Exit;
}
switch( uiOption)
{
case F_DOMEDIT_CONFIG_STATS_START:
{
//eConfigOp = FLM_START_STATS;
break;
}
case F_DOMEDIT_CONFIG_STATS_STOP:
{
//eConfigOp = FLM_STOP_STATS;
break;
}
case F_DOMEDIT_CONFIG_STATS_RESET:
{
//eConfigOp = FLM_RESET_STATS;
break;
}
default:
{
rc = RC_SET( NE_XFLM_NOT_IMPLEMENTED);
goto Exit;
}
}
// if( RC_BAD( rc = FlmConfig( eConfigOp, 0, 0)))
// {
// goto Exit;
// }
Exit:
return( rc);
}
/*============================================================================
Name: asciiUCMixToUC
Desc: Accepts a buffer with regular ascii, and 4 ascii chars representing
unicode and converts all the chars to unicode. UC_MARKER defines the
char which marks the beginning of a unicode sequence.
============================================================================*/
RCODE F_DomEditor::asciiUCMixToUC(
char * pszAscii,
FLMUNICODE * puzUnicode,
FLMUINT uiMaxUniChars)
{
char * pszTmp;
char * pszTerm;
char szNumBuf[ 32];
FLMUINT uiUniCount = 0;
FLMUINT64 ui64Value;
RCODE rc = NE_XFLM_OK;
flmAssert( uiMaxUniChars > 0);
uiMaxUniChars--; // Leave space for the terminator
while( uiUniCount < uiMaxUniChars && *pszAscii)
{
if( pszAscii[ 0] == '~' && pszAscii[ 1] == '[')
{
pszAscii += 2;
if( (pszTerm = f_strchr( pszAscii, ']')) == NULL)
{
rc = RC_SET( NE_XFLM_CONV_ILLEGAL);
goto Exit;
}
while( *pszAscii && *pszAscii != ']')
{
pszTmp = f_strchr( pszAscii, ' ');
if( !pszTmp || pszTmp > pszTerm)
{
pszTmp = pszTerm;
}
f_memcpy( szNumBuf, pszAscii, pszTmp - pszAscii);
szNumBuf[ pszTmp - pszAscii] = 0;
if( RC_BAD( rc = getNumber( szNumBuf, &ui64Value, NULL)))
{
goto Exit;
}
puzUnicode[ uiUniCount++] = (FLMUNICODE)ui64Value;
pszAscii += (pszTmp - pszAscii);
while( *pszAscii == ' ')
{
pszAscii++;
}
}
if( *pszAscii == ']')
{
pszAscii++;
}
}
else
{
puzUnicode[ uiUniCount++] = (FLMUNICODE)(*pszAscii);
pszAscii++;
}
}
puzUnicode[ uiUniCount] = 0;
Exit:
return rc;
}
/*============================================================================
Name: UCToAsciiUCMix
============================================================================*/
RCODE F_DomEditor::UCToAsciiUCMix(
FLMUNICODE * puzUnicode,
char * pszAscii,
FLMUINT uiMaxAsciiChars)
{
char szTmpBuf[ 32];
FLMUINT uiAsciiCount = 0;
FLMBOOL bEscaped = FALSE;
RCODE rc = NE_XFLM_OK;
flmAssert( uiMaxAsciiChars > 0);
uiMaxAsciiChars--; // Leave space for the terminator
while( uiAsciiCount < uiMaxAsciiChars && *puzUnicode)
{
if( *puzUnicode >= 0x0020 && *puzUnicode <= 0x007E)
{
if( bEscaped)
{
pszAscii[ uiAsciiCount++] = ']';
bEscaped = FALSE;
}
if( uiAsciiCount == uiMaxAsciiChars)
{
rc = RC_SET( NE_XFLM_CONV_DEST_OVERFLOW);
goto Exit;
}
pszAscii[ uiAsciiCount++] = (char)*puzUnicode;
}
else
{
if( !bEscaped)
{
if( (uiAsciiCount + 2) >= uiMaxAsciiChars)
{
rc = RC_SET( NE_XFLM_CONV_DEST_OVERFLOW);
goto Exit;
}
pszAscii[ uiAsciiCount++] = '~';
pszAscii[ uiAsciiCount++] = '[';
bEscaped = TRUE;
}
else
{
pszAscii[ uiAsciiCount++] = ' ';
}
pszAscii[ uiAsciiCount] = '\0';
f_sprintf( szTmpBuf, "0x%04X", (unsigned)*puzUnicode);
if( (uiAsciiCount +f_strlen( szTmpBuf)) >= uiMaxAsciiChars)
{
rc = RC_SET( NE_XFLM_CONV_DEST_OVERFLOW);
goto Exit;
}
f_strcat( &(pszAscii[ uiAsciiCount]), szTmpBuf);
uiAsciiCount += f_strlen( szTmpBuf);
}
puzUnicode++;
}
if( bEscaped)
{
if( uiAsciiCount == uiMaxAsciiChars)
{
rc = RC_SET( NE_XFLM_CONV_DEST_OVERFLOW);
goto Exit;
}
pszAscii[ uiAsciiCount++] = ']';
bEscaped = FALSE;
}
pszAscii[ uiAsciiCount] = '\0';
Exit:
return rc;
}
/***************************************************************************
Name: domEditVerifyRun
Desc: Makes sure the utility is still allowed to run
*****************************************************************************/
RCODE domEditVerifyRun( void)
{
F_TMSTAMP curDate;
FLMUINT uiExpireYear = 0;
FLMUINT uiExpireMonth = 0;
FLMUINT uiExpireDay = 0;
RCODE rc = NE_XFLM_OK;
const char * pszDate = __DATE__;
// Get the compilation date of this module.
// If cannot get it, return NE_XFLM_OK.
if (!domeditStrToDate( pszDate, &uiExpireYear,
&uiExpireMonth, &uiExpireDay))
{
goto Exit;
}
// Add four months to it.
if (uiExpireMonth <= 8)
{
uiExpireMonth += 4;
}
else
{
uiExpireMonth -= 8;
uiExpireYear++;
}
// Adjust the day if necessary - we don't have to be too precise here
// because we don't really care if we give them a day or two extra
// for the expiration date.
switch (uiExpireMonth)
{
case 2:
if (uiExpireDay > 28)
{
uiExpireDay = 28;
}
break;
case 4:
case 6:
case 9:
case 11:
if (uiExpireDay > 30)
{
uiExpireDay = 30;
}
break;
default:
break;
}
f_timeGetTimeStamp( &curDate);
curDate.month++;
if(((FLMUINT)curDate.year > uiExpireYear) ||
((FLMUINT)curDate.year == uiExpireYear &&
(FLMUINT)curDate.month > uiExpireMonth) ||
((FLMUINT)curDate.year == uiExpireYear &&
(FLMUINT)curDate.month == uiExpireMonth &&
(FLMUINT)curDate.day > uiExpireDay))
{
rc = RC_SET( NE_XFLM_ILLEGAL_OP);
goto Exit;
}
Exit:
return( rc);
}
/****************************************************************************
Desc: This routine converts the passed in string to a year, month, and day.
****************************************************************************/
FSTATIC FLMBOOL domeditStrToDate(
const char * s,
FLMUINT * puiYear,
FLMUINT * puiMonth,
FLMUINT * puiDay)
{
char szToken [80];
FLMUINT uiLoop;
FLMBOOL bHaveNum = FALSE;
FLMBOOL bHaveDay = FALSE;
FLMBOOL bHaveMonth = FALSE;
FLMUINT uiNum1;
FLMUINT uiSaveNum = 0;
FLMBOOL bSlashFormat = FALSE;
FLMBOOL bDashFormat = FALSE;
FLMBOOL bNoFormat = FALSE;
for (;;)
{
// Get the next token from the string
s = domeditSkipChars( s, " \t\n\r");
uiLoop = 0;
while (((*s >= 'a') && (*s <= 'z')) ||
((*s >= 'A') && (*s <= 'Z')) ||
((*s >= '0') && (*s <= '9')))
{
if (uiLoop < sizeof( szToken) - 1)
{
szToken [uiLoop++] = *s;
}
s++;
}
szToken [uiLoop] = 0;
// See if it is a number
if ((uiLoop) &&
(domeditIsNum( szToken, &uiNum1)))
{
if ((bHaveMonth) && (bHaveDay))
{
if (uiNum1 > 65535)
{
goto Year_Error;
}
*puiYear = uiNum1;
// Make sure we have a valid day of the month.
// NOTE: The test for Feb. 29 will allow it in
// some cases where it shouldn't have, but at
// least it will never disallow it when it should
// have allowed it.
switch (*puiMonth)
{
case 2:
if ((*puiDay > 29) ||
((*puiDay == 29) &&
(*puiYear % 4 != 0)))
{
goto Day_Error;
}
break;
case 4:
case 6:
case 9:
case 11:
if (*puiDay > 30)
{
goto Day_Error;
}
break;
default:
break;
}
return( TRUE);
}
else if (bHaveMonth)
{
if ((uiNum1 < 1) || (uiNum1 > 31))
{
goto Day_Error;
}
bHaveDay = TRUE;
*puiDay = uiNum1;
}
else if (bHaveDay)
{
if ((uiNum1 < 1) || (uiNum1 > 12))
{
goto Month_Error;
}
bHaveMonth = TRUE;
*puiMonth = uiNum1;
}
else if (bHaveNum)
{
if ((uiNum1 >= 1) && (uiNum1 <= 12))
{
flmAssert( 0);
return( FALSE);
}
else if ((uiNum1 < 1) || (uiNum1 > 31))
{
goto MonthDay_Error;
}
else
{
bHaveDay = TRUE;
bHaveMonth = TRUE;
*puiMonth = uiSaveNum;
*puiDay = uiNum1;
}
}
else if ((uiNum1 < 1) || (uiNum1 > 31))
{
goto MonthDay_Error;
}
else
{
if (uiNum1 <= 12)
{
bHaveNum = TRUE;
uiSaveNum = uiNum1;
}
else
{
bHaveDay = TRUE;
*puiDay = uiNum1;
}
}
}
else if (bHaveMonth)
{
if (bHaveDay)
{
goto Year_Error;
}
else
{
goto Day_Error;
}
}
else
{
// See if it is a month string
for (uiLoop = 0; uiLoop < 12; uiLoop++)
{
if (f_stricmp( pszDomeditMonths [uiLoop], szToken) == 0)
{
bHaveMonth = TRUE;
*puiMonth = (uiLoop+1);
break;
}
}
if (uiLoop == 12)
{
for (uiLoop = 0; uiLoop < 12; uiLoop++)
{
if (f_stricmp( pszDomeditFullMonthNames [uiLoop],
szToken) == 0)
{
bHaveMonth = TRUE;
*puiMonth = (uiLoop+1);
break;
}
}
if (uiLoop == 12)
{
goto Month_Error;
}
}
}
s = domeditSkipChars( s, " \t\n\r");
if (bNoFormat)
{
if ((bHaveMonth) && (bHaveDay) && (*s == ','))
{
s++;
}
}
else if (bSlashFormat)
{
if (*s != '/')
{
goto Invalid_Format;
}
s++;
}
else if (bDashFormat)
{
if (*s != '-')
{
goto Invalid_Format;
}
s++;
}
else if (*s == '/')
{
bSlashFormat = TRUE;
s++;
}
else if (*s == '-')
{
bDashFormat = TRUE;
s++;
}
else
{
bNoFormat = TRUE;
}
}
Invalid_Format:
Year_Error:
Month_Error:
Day_Error:
MonthDay_Error:
flmAssert( 0);
return( FALSE);
}
/****************************************************************************
Desc: This routine determines if the passed in token is a number. If so,
the number is returned.
****************************************************************************/
FSTATIC FLMBOOL domeditIsNum(
const char * pszToken,
FLMUINT * puiNum)
{
FLMBOOL bIsNum = FALSE;
const char * pszBuffer;
FLMUINT uiLen;
// Make sure all characters are between 0 and 9
pszBuffer = pszToken;
// See if it is a HEX number.
if ((*pszBuffer == '0') && (*(pszBuffer + 1) == 'x'))
{
pszBuffer += 2;
uiLen = 0;
while ((*pszBuffer) &&
(((*pszBuffer >= '0') && (*pszBuffer <= '9')) ||
((*pszBuffer >= 'a') && (*pszBuffer <= 'f')) ||
((*pszBuffer >= 'A') && (*pszBuffer <= 'F'))))
{
uiLen++;
pszBuffer++;
}
if ((!uiLen) || (uiLen > 8) || (*pszBuffer))
{
goto Exit;
}
// Convert the pszToken to a number
*puiNum = 0;
pszBuffer = pszToken + 2;
while (*pszBuffer)
{
if ((*pszBuffer >= '0') && (*pszBuffer <= '9'))
{
*puiNum = (*puiNum << 4) + *pszBuffer - '0';
}
else if ((*pszBuffer >= 'a') && (*pszBuffer <= 'f'))
{
*puiNum = (*puiNum << 4) + *pszBuffer - 'a' + 10;
}
else
{
*puiNum = (*puiNum << 4) + *pszBuffer - 'A' + 10;
}
pszBuffer++;
}
}
else
{
FLMUINT uiLeadingZeroes = 0;
// Skip leading zeroes
while (*pszBuffer == '0')
{
uiLeadingZeroes++;
pszBuffer++;
}
pszToken = pszBuffer;
uiLen = 0;
while ((*pszBuffer) && (*pszBuffer >= '0') && (*pszBuffer <= '9'))
{
uiLen++;
pszBuffer++;
}
if ((!uiLen) && (uiLeadingZeroes))
{
*puiNum = 0;
bIsNum = TRUE;
goto Exit;
}
if ((!uiLen) || (uiLen > 10) || (*pszBuffer))
{
goto Exit;
}
// Make sure there are not more characters than we can handle
if ((uiLen == 10) && (f_strcmp( pszToken, "4294967295") > 0))
{
goto Exit;
}
// Convert the pszToken to a number
*puiNum = 0;
pszBuffer = pszToken;
while (*pszBuffer)
{
*puiNum = *puiNum * 10 + *pszBuffer - '0';
pszBuffer++;
}
}
bIsNum = TRUE;
Exit:
return( bIsNum);
}
/****************************************************************************
Desc: This routine skips the characters in the string specified by
pszCharsToSkip.
****************************************************************************/
FSTATIC char * domeditSkipChars(
const char * pszStr,
const char * pszCharsToSkip)
{
const char * pszTmp;
while (*pszStr)
{
pszTmp = pszCharsToSkip;
while ((*pszTmp) && (*pszTmp != *pszStr))
{
pszTmp++;
}
if (*pszTmp)
{
pszStr++;
}
else
{
break;
}
}
return( (char *)pszStr);
}
/****************************************************************************
Desc:
****************************************************************************/
RCODE _domEditBackgroundThread(
IF_Thread * pThread)
{
FLMUINT uiCount = 0;
while( !pThread->getShutdownFlag())
{
uiCount++;
if( !(uiCount % 50))
{
if( RC_BAD( domEditVerifyRun()))
{
gv_bShutdown = TRUE;
break;
}
}
f_sleep( 1000);
}
return( NE_XFLM_OK);
}
/****************************************************************************
Desc: Updates the name table from the database
*****************************************************************************/
RCODE F_DomEditor::refreshNameTable( void)
{
DME_NAME_TABLE_INFO nametableInfo;
RCODE rc = NE_XFLM_OK;
flmAssert( m_bSetupCalled == TRUE);
if (m_pNameTable)
{
m_pNameTable->Release();
m_pNameTable = NULL;
}
/*
Call the callback to build the name table
*/
f_memset( &nametableInfo, 0, sizeof( DME_NAME_TABLE_INFO));
if( m_pEventHook)
{
if( RC_BAD( rc = m_pEventHook( this, F_DOMEDIT_EVENT_NAME_TABLE,
(void *)(&nametableInfo), m_EventData)))
{
goto Exit;
}
if (nametableInfo.bInitialized)
{
if ((m_pNameTable = nametableInfo.pNameTable) != NULL)
{
m_pNameTable->AddRef();
}
}
}
// Try the default initialization if no name table came back from
// the event hook.
if (!m_pNameTable)
{
// addRef is done by getNameTable.
if (RC_BAD( rc = m_pDb->getNameTable( &m_pNameTable)))
{
if (rc != NE_XFLM_NO_NAME_TABLE)
{
goto Exit;
}
// If there is no name table (could be that m_pDb == NULL),
// create one with at least the dictionary tags.
if ((m_pNameTable = f_new F_NameTable) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
if (RC_BAD( rc = m_pNameTable->addReservedDictTags()))
{
goto Exit;
}
}
}
Exit:
return( rc);
}
/*=============================================================================
Desc: Convert an ascii string to unicode
*============================================================================*/
FSTATIC void asciiToUnicode(
const char * pszAsciiString,
FLMUNICODE * puzString)
{
FLMUINT uiLoop = 0;
// Convert to a unicode string.
for( uiLoop=0; *pszAsciiString; pszAsciiString++)
{
if (*pszAsciiString == '&')
{
const char * pszTmp = pszAsciiString + 1;
if (*pszTmp == '#')
{
FLMUNICODE * puzTmpPtr = &puzString[ uiLoop];
pszTmp++;
*puzTmpPtr = (FLMUNICODE)f_atoud( pszTmp);
uiLoop++;
pszAsciiString += 6;
}
else
{
puzString[ uiLoop++] = (FLMUNICODE)*pszAsciiString;
}
}
else
{
puzString[ uiLoop++] = (FLMUNICODE)*pszAsciiString;
}
}
puzString[ uiLoop] = (FLMUNICODE)0;
return;
}
/*=============================================================================
Desc: Convert a unicode string to ascii - separate buffer
*============================================================================*/
FSTATIC RCODE unicodeToAscii(
FLMUNICODE * puzString,
char * pszString,
FLMUINT uiLength
)
{
RCODE rc = NE_XFLM_OK;
char * pszDest;
FLMINT iLength = uiLength;
pszDest = pszString;
while( iLength > 0 && *puzString)
{
if (*puzString < 32 || *puzString > 126)
{
if (iLength >= 7)
{
f_sprintf( pszDest, "&#%04u;",(unsigned)*puzString);
pszDest += 7;
iLength -= 7;
}
else
{
rc = RC_SET( NE_XFLM_CONV_DEST_OVERFLOW);
goto Exit;
}
}
else
{
*pszDest = (char)*puzString;
pszDest++;
iLength--;
}
puzString++;
}
if (iLength < 0)
{
rc = RC_SET( NE_XFLM_CONV_DEST_OVERFLOW);
goto Exit;
}
if (pszDest && uiLength)
{
*pszDest = '\0';
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Get's a DOM node's name, allocating memory as needed.
****************************************************************************/
RCODE F_DomEditor::getNodeName(
F_DOMNode * pDOMNode,
DME_ROW_INFO * pRow,
FLMUNICODE ** ppuzName,
FLMUINT * puiBufSize
)
{
RCODE rc = NE_XFLM_OK;
FLMUINT uiLen = 0;
FLMUINT uiPrefixLen = 0;
FLMUINT uiNameId;
FLMUINT uiPrefixId;
FLMUINT uiType;
FLMUNICODE * puzBuffer = NULL;
FLMUNICODE * puzPrefix = NULL;
FLMUNICODE * puzAppendBuffer = NULL;
if (puiBufSize)
{
*puiBufSize = 0;
}
if (ppuzName)
{
*ppuzName = NULL;
}
if (!pDOMNode)
{
flmAssert( pRow);
}
if (pDOMNode)
{
// See if there is a prefix...
if (RC_BAD( rc = pDOMNode->getPrefixId( m_pDb, &uiPrefixId)))
{
goto Exit;
}
// First we get the name id, then we look up the value in the name table.
if (RC_BAD( rc = pDOMNode->getNameId( m_pDb, &uiNameId)))
{
goto Exit;
}
switch (pDOMNode->getNodeType())
{
case DOCUMENT_NODE:
case ELEMENT_NODE:
case DATA_NODE:
case COMMENT_NODE:
case CDATA_SECTION_NODE:
{
uiType = ELM_ELEMENT_TAG;
break;
}
case ATTRIBUTE_NODE:
{
uiType = ELM_ATTRIBUTE_TAG;
break;
}
default:
uiType = 0;
flmAssert( 0);
break;
}
if (uiPrefixId && ppuzName)
{
if( RC_BAD( rc = pDOMNode->getPrefix( m_pDb,
(FLMUNICODE *)NULL, 0, &uiPrefixLen)))
{
goto Exit;
}
// Allocate a buffer to hold the data.
uiPrefixLen = (uiPrefixLen + 1) * sizeof( FLMUNICODE);
if (RC_BAD( rc = f_calloc( uiPrefixLen, &puzPrefix)))
{
goto Exit;
}
if( RC_BAD( rc = pDOMNode->getPrefix( m_pDb, puzPrefix,
uiPrefixLen, NULL)))
{
goto Exit;
}
}
}
else if (pRow->pVector)
{
uiNameId = pRow->pVector->getNameId( pRow->uiElementNumber);
uiPrefixLen = 0;
if (pRow->pVector->isAttr( pRow->uiElementNumber))
{
uiType = ELM_ATTRIBUTE_TAG;
}
else
{
uiType = ELM_ELEMENT_TAG;
}
}
else
{
// No name that we can get... Should we return an error?
goto Exit;
}
// Now get the name
if (RC_BAD( rc = m_pNameTable->getFromTagTypeAndNum(
m_pDb, uiType, uiNameId, NULL, NULL, &uiLen)))
{
goto Exit;
}
uiLen *= sizeof( FLMUNICODE);
// The length returned is the number of characters. It does
// not count the null terminator.
// We must allow for them when allocating a buffer.
if (uiLen && ppuzName)
{
FLMUINT uiTmpLen = uiLen + sizeof( FLMUNICODE);
// Allocate a buffer to hold the data.
uiLen = uiTmpLen;
if (RC_BAD( rc = f_calloc( uiTmpLen, &puzBuffer)))
{
goto Exit;
}
// Now get the value...
if (RC_BAD( rc = m_pNameTable->getFromTagTypeAndNum(
m_pDb, uiType, uiNameId, puzBuffer, NULL, &uiTmpLen)))
{
goto Exit;
}
}
// Append the results
if (uiPrefixLen && uiLen && ppuzName)
{
if (RC_BAD( rc = f_calloc( uiLen + uiPrefixLen, &puzAppendBuffer)))
{
goto Exit;
}
f_memcpy( puzAppendBuffer, puzPrefix, uiPrefixLen - 2);
puzAppendBuffer[ (uiPrefixLen >> 1) - 1] = (FLMUNICODE)':';
f_memcpy( &puzAppendBuffer[ uiPrefixLen >> 1], puzBuffer, uiLen - 2);
f_free( &puzPrefix);
puzPrefix = NULL;
f_free( &puzBuffer);
puzBuffer = puzAppendBuffer;
puzAppendBuffer = NULL;
uiLen = uiLen + uiPrefixLen;
}
if (puiBufSize)
{
*puiBufSize = uiLen;
}
if (ppuzName)
{
*ppuzName = puzBuffer;
puzBuffer = NULL;
}
Exit:
if (puzBuffer)
{
f_free( &puzBuffer);
}
if (puzPrefix)
{
f_free( &puzPrefix);
}
if (puzAppendBuffer)
{
f_free( &puzAppendBuffer);
}
return( rc);
}
/****************************************************************************
Desc: Get's a DOM node's value name, allocating memory as needed.
****************************************************************************/
RCODE F_DomEditor::getNodeValue(
F_DOMNode * pDOMNode,
FLMUNICODE ** ppuzValue,
FLMUINT * puiBufSize,
FLMBOOL //bStartTrans
)
{
RCODE rc = NE_XFLM_OK;
FLMUINT uiLen = 0;
FLMUINT uiDataType;
if (puiBufSize)
{
*puiBufSize = 0;
}
*ppuzValue = NULL;
if (RC_BAD( rc = pDOMNode->getDataType( m_pDb, &uiDataType)))
{
goto Exit;
}
switch (uiDataType)
{
case XFLM_NODATA_TYPE:
{
break;
}
case XFLM_TEXT_TYPE:
case XFLM_NUMBER_TYPE:
case XFLM_BINARY_TYPE:
{
if (RC_BAD( rc = pDOMNode->getUnicodeChars(m_pDb, &uiLen)))
{
goto Exit;
}
if (uiLen)
{
// The length returned does not allow for 2 NULL terminators.
// We must allow for them when allocating a buffer.
uiLen *= sizeof(FLMUNICODE);
uiLen += sizeof(FLMUNICODE);
if (RC_BAD( rc = f_calloc( uiLen, ppuzValue)))
{
goto Exit;
}
if (RC_BAD( rc = pDOMNode->getUnicode( m_pDb, *ppuzValue, uiLen, 0, uiLen, &uiLen)))
{
goto Exit;
}
}
break;
}
default:
break;
}
if (puiBufSize)
{
*puiBufSize = uiLen;
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Formats text.
****************************************************************************/
FSTATIC RCODE formatText(
FLMUNICODE * puzBuf,
FLMBOOL bQuoted,
const char * pszPreText,
const char * pszPostText,
char ** ppszString)
{
RCODE rc = NE_XFLM_OK;
FLMUNICODE * puzTmp = NULL;
FLMUNICODE uzNullChar;
char * pszString;
FLMUINT uiMaxStringLen = MAX_DISPLAY_SEGMENT;
FLMUINT uiStringLen = 0;
F_DynaBuf tmpBuf;
flmAssert( ppszString);
pszString = *ppszString;
flmAssert( pszString);
// NOTE: puzBuf may be NULL - treat same as empty string.
if (!puzBuf)
{
uzNullChar = 0;
puzTmp = &uzNullChar;
}
else
{
puzTmp = puzBuf;
}
// If the first character is a carriage return, skip over it.
if (*puzTmp == (FLMUNICODE)'\n')
{
puzTmp++;
}
if (pszPreText)
{
if (RC_BAD( rc = tmpBuf.appendString( pszPreText)))
{
goto Exit;
}
}
if (bQuoted)
{
if (RC_BAD( rc = tmpBuf.appendByte( '"')))
{
goto Exit;
}
}
while (*puzTmp)
{
// Special handling for newline characters - want to add indent
// spaces to each new line.
if (*puzTmp == (FLMUNICODE)'\n')
{
puzTmp++;
// Skip newline if it is the last character in the buffer.
if (*puzTmp == 0)
{
break;
}
// Output whatever buffer we have built up.
if (tmpBuf.getDataLength())
{
tmpBuf.appendByte( 0);
f_sprintf( pszString, "%*.*s",
0, (uiStringLen <= uiMaxStringLen
? uiMaxStringLen - uiStringLen
: 0),
tmpBuf.getBufferPtr());
pszString += tmpBuf.getDataLength() - 1;
uiStringLen += tmpBuf.getDataLength() - 1;
if ((uiStringLen + 1) < uiMaxStringLen)
{
f_sprintf( pszString, " ");
pszString ++;
uiStringLen ++;
}
else
{
break;
}
}
// Output a newline to end this line
tmpBuf.truncateData( 0);
// Have already skipped over the newline, so we just continue.
continue;
}
// Add the character to the buffer.
if (*puzTmp >= 32 && *puzTmp <= 126)
{
if (RC_BAD( rc = tmpBuf.appendByte( (char)*puzTmp)))
{
goto Exit;
}
}
else
{
// Allow browser to render these - flush what we have in
// our buffer up to this point, then output.
if (tmpBuf.getDataLength())
{
tmpBuf.appendByte( 0);
f_sprintf( pszString, "%*.*s",
0, (uiStringLen <= uiMaxStringLen
? uiMaxStringLen - uiStringLen
: 0),
tmpBuf.getBufferPtr());
pszString += tmpBuf.getDataLength() - 1;
uiStringLen += tmpBuf.getDataLength() - 1;
tmpBuf.truncateData( 0);
}
if (uiStringLen + 7 < uiMaxStringLen)
{
f_sprintf( pszString, "&#%04u;", (unsigned)(*puzTmp));
pszString += 7;
uiStringLen += 7;
}
else
{
break;
}
}
puzTmp++;
}
if (tmpBuf.getDataLength())
{
tmpBuf.appendByte( 0);
f_sprintf( pszString, "%*.*s",
0, (uiStringLen <= uiMaxStringLen
? uiMaxStringLen - uiStringLen
: 0),
tmpBuf.getBufferPtr());
pszString += tmpBuf.getDataLength() - 1;
uiStringLen += tmpBuf.getDataLength() - 1;
tmpBuf.truncateData( 0);
}
if (bQuoted)
{
if (RC_BAD( rc = tmpBuf.appendByte( '"')))
{
goto Exit;
}
}
if (pszPostText)
{
if (RC_BAD( rc = tmpBuf.appendString( pszPostText)))
{
goto Exit;
}
}
if (tmpBuf.getDataLength())
{
tmpBuf.appendByte( 0);
f_sprintf( pszString, "%*.*s",
0, (uiStringLen <= uiMaxStringLen
? uiMaxStringLen - uiStringLen
: 0),
tmpBuf.getBufferPtr());
pszString += tmpBuf.getDataLength() - 1;
tmpBuf.truncateData( 0);
}
*ppszString = pszString;
Exit:
return( rc);
}
/*=============================================================================
Desc: Format a Document Node
*============================================================================*/
FSTATIC RCODE formatDocumentNode(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pRow,
FLMUINT * puiNumVals,
FLMUINT uiFlags
)
{
RCODE rc = NE_XFLM_OK;
FLMUNICODE * puzTitle = NULL;
DME_DISP_COLUMN * pDispVals;
FLMUINT uiCol;
F_DOMNode * pAnnotation = NULL;
FLMUNICODE * puzAttrValue = NULL;
char * pszString = NULL;
eColorType uiForeground;
if (pRow->pDomNode)
{
uiForeground = pRow->pDomNode->isQuarantined()
? FLM_LIGHTCYAN
: FLM_YELLOW;
}
else
{
uiForeground = FLM_YELLOW;
}
if ((pDispVals = pDomEditor->getDispColumns()) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
f_memset( pDispVals, 0, sizeof(DME_DISP_COLUMN));
uiCol = pRow->uiLevel * 2;
/*
Output the Expand/Collapse symbol - check the flags
*/
if ( !(uiFlags & F_DOMEDIT_FLAG_HIDE_EXPAND))
{
f_sprintf( pDispVals[ *puiNumVals].szString,
"%s", pRow->bExpanded ? "-" : pRow->bHasChildren ? "+" : " ");
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = FLM_WHITE;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString) + 2;
(*puiNumVals)++;
}
else
{
uiCol += 2;
}
/*
Output the level
*/
if( !(uiFlags & F_DOMEDIT_FLAG_HIDE_LEVEL))
{
f_sprintf( pDispVals[ *puiNumVals].szString,
"%u", pRow->uiLevel);
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = FLM_WHITE;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString) + (pRow->uiLevel * 2) + 1;
(*puiNumVals)++;
}
else
{
uiCol += 2;
}
/*
Output the display value
*/
if ( !(uiFlags & F_DOMEDIT_FLAG_ENDTAG))
{
f_sprintf( pDispVals[ *puiNumVals].szString, pRow->bExpanded ? "<DOC>" :
!pRow->bHasChildren ? "<DOC>" : "<DOC/>");
}
else
{
f_sprintf( pDispVals[ *puiNumVals].szString, "</DOC>");
}
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = pDomEditor->isMonochrome() ? FLM_WHITE : uiForeground;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString) + (pRow->uiLevel * 2) + 1;
(*puiNumVals)++;
if (RC_OK( rc = pRow->pDomNode->getAnnotation(
pDomEditor->getDb(), (IF_DOMNode **)&pAnnotation)))
{
if (RC_OK( rc = pDomEditor->getNodeValue( pAnnotation, &puzAttrValue)))
{
pszString = &pDispVals[ *puiNumVals].szString[0];
if (RC_BAD( rc = formatText(
puzAttrValue, FALSE, "", "", &pszString)))
{
goto Exit;
}
}
}
else
{
if (rc == NE_XFLM_DOM_NODE_NOT_FOUND)
{
rc = NE_XFLM_OK;
}
goto Exit;
}
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = pDomEditor->isMonochrome() ? FLM_WHITE : uiForeground;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
(*puiNumVals)++;
Exit:
if (pAnnotation)
{
pAnnotation->Release();
}
f_free( &puzTitle);
f_free( &puzAttrValue);
return rc;
}
/*=============================================================================
Desc: Format an Element Node
*============================================================================*/
FSTATIC RCODE formatElementNode(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pRow,
FLMUINT * puiNumVals,
FLMUINT uiFlags
)
{
RCODE rc = NE_XFLM_OK;
FLMUNICODE * puzName = NULL;
FLMUNICODE * puzAttrName = NULL;
FLMUNICODE * puzAttrValue = NULL;
FLMUINT uiCol;
DME_DISP_COLUMN * pDispVals;
char * pszString;
F_DOMNode * pAttrNode = NULL;
F_DOMNode * pChildNode = NULL;
FLMBOOL bGotFirstAttr = FALSE;
F_Db * pDb = NULL;
FLMUINT uiAttrLen;
eColorType uiForeground;
FLMBOOL bHasLocalData;
if (RC_BAD( rc = pRow->pDomNode->isDataLocalToNode( pDomEditor->getDb(), &bHasLocalData)))
{
goto Exit;
}
if (pRow->pDomNode)
{
uiForeground = pRow->pDomNode->isQuarantined()
? FLM_LIGHTCYAN
: FLM_WHITE;
}
else
{
uiForeground = FLM_WHITE;
}
if ((pDispVals = pDomEditor->getDispColumns()) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
pDb = pDomEditor->getSource();
f_memset( pDispVals, 0, sizeof(DME_DISP_COLUMN));
uiCol = pRow->uiLevel * 2;
/*
Output the Expand/Collapse symbol - check the flags
*/
if ( !(uiFlags & F_DOMEDIT_FLAG_HIDE_EXPAND))
{
f_sprintf( pDispVals[ *puiNumVals].szString,
"%s", pRow->bExpanded ? "-" : (pRow->bHasChildren || bHasLocalData) ? "+" : " ");
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = FLM_WHITE;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome()
? FLM_BLACK
: FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString) + 2;
(*puiNumVals)++;
}
else
{
uiCol += 2;
}
/*
Output the level
*/
if( !(uiFlags & F_DOMEDIT_FLAG_HIDE_LEVEL))
{
f_sprintf( pDispVals[ *puiNumVals].szString,
"%u", pRow->uiLevel);
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = FLM_WHITE;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome()
? FLM_BLACK
: FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString) + 2;
(*puiNumVals)++;
}
else
{
uiCol += 2;
}
if (RC_BAD( rc = pDomEditor->getNodeName( pRow->pDomNode, NULL, &puzName)))
{
goto Exit;
}
pszString = &pDispVals[ *puiNumVals].szString[
f_strlen(pDispVals[ *puiNumVals].szString)];
if ( !(uiFlags & F_DOMEDIT_FLAG_ENDTAG))
{
f_sprintf( pszString, "<");
pszString++;
}
else
{
f_sprintf( pszString, "</");
pszString += 2;
}
// Save the qualified name...
if (RC_BAD( rc = formatText( puzName, FALSE, NULL, NULL, &pszString)))
{
goto Exit;
}
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = uiForeground;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome()
? FLM_BLACK
: FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString);
(*puiNumVals)++;
if (!(uiFlags & F_DOMEDIT_FLAG_ENDTAG))
{
pszString = &pDispVals[ *puiNumVals].szString[
f_strlen(pDispVals[ *puiNumVals].szString)];
uiAttrLen = 0;
for (;;)
{
if (!bGotFirstAttr)
{
// Get the first attribute
if (RC_BAD(
rc = pRow->pDomNode->getFirstAttribute( pDb,
(IF_DOMNode **)&pAttrNode)))
{
if ( rc == NE_XFLM_NOT_FOUND ||
rc == NE_XFLM_EOF_HIT ||
rc == NE_XFLM_DOM_NODE_NOT_FOUND)
{
rc = NE_XFLM_OK;
break;
}
else
{
goto Exit;
}
}
bGotFirstAttr = TRUE;
}
else
{
if (RC_BAD( rc = pAttrNode->getNextSibling(
pDb, (IF_DOMNode **)&pAttrNode)))
{
if ( rc == NE_XFLM_NOT_FOUND ||
rc == NE_XFLM_EOF_HIT ||
rc == NE_XFLM_DOM_NODE_NOT_FOUND)
{
rc = NE_XFLM_OK;
break;
}
else
{
goto Exit;
}
}
}
if (RC_BAD( rc = pDomEditor->getNodeName( pAttrNode, NULL, &puzAttrName)))
{
goto Exit;
}
if (RC_BAD( rc = formatText(
puzAttrName, FALSE, " ", "=", &pszString)))
{
goto Exit;
}
f_free( &puzAttrName);
// Get the attribute value now. Look for it in the same node first.
if (RC_BAD( rc = pDomEditor->getNodeValue( pAttrNode, &puzAttrValue)))
{
f_sprintf( pszString, "** NO VALUE FOUND **");
}
if (RC_BAD( rc = formatText(
puzAttrValue, FALSE, "", "", &pszString)))
{
goto Exit;
}
f_free( &puzAttrValue);
if ((uiCol + (pszString - &pDispVals[ *puiNumVals].szString[0])) >= 78)
{
f_sprintf( &pDispVals[ *puiNumVals].szString[ 78 - uiCol - 4], "...");
break;
}
}
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = FLM_LIGHTRED;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString);
(*puiNumVals)++;
}
// Add the trailing '>'
f_sprintf( pDispVals[ *puiNumVals].szString, pRow->bExpanded ? ">" :
!pRow->bHasChildren ? ">" : "/>");
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = uiForeground;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString);
(*puiNumVals)++;
Exit:
if (pAttrNode)
{
pAttrNode->Release();
}
if (pChildNode)
{
pChildNode->Release();
}
if (pRow->pDomNode)
{
pRow->pDomNode->Release();
pRow->pDomNode = NULL;
}
f_free( &puzName);
f_free( &puzAttrName);
f_free( &puzAttrValue);
return rc;
}
/******************************************************************************
Desc: Format an attribute for display.
******************************************************************************/
FSTATIC RCODE formatAttributeNode(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pRow,
FLMUINT * puiNumVals,
FLMUINT uiFlags
)
{
RCODE rc = NE_XFLM_OK;
FLMUNICODE * puzName = NULL;
FLMUNICODE * puzAttrName = NULL;
FLMUNICODE * puzAttrValue = NULL;
FLMUINT uiCol;
DME_DISP_COLUMN * pDispVals;
char * pszString;
if ((pDispVals = pDomEditor->getDispColumns()) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
f_memset( pDispVals, 0, sizeof(DME_DISP_COLUMN));
uiCol = pRow->uiLevel * 2;
/*
Output the Expand/Collapse symbol - check the flags
*/
if ( !(uiFlags & F_DOMEDIT_FLAG_HIDE_EXPAND))
{
f_sprintf( pDispVals[ *puiNumVals].szString,
"%s", pRow->bExpanded ? "-" : pRow->bHasChildren ? "+" : " ");
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = FLM_WHITE;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString) + 2;
(*puiNumVals)++;
}
else
{
uiCol += 2;
}
/*
Output the level
*/
if( !(uiFlags & F_DOMEDIT_FLAG_HIDE_LEVEL))
{
f_sprintf( pDispVals[ *puiNumVals].szString,
"%u", pRow->uiLevel);
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = FLM_WHITE;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString) + 2;
(*puiNumVals)++;
}
else
{
uiCol += 2;
}
if (RC_BAD( rc = pDomEditor->getNodeName( pRow->pDomNode, NULL, &puzName)))
{
goto Exit;
}
pszString = &pDispVals[ *puiNumVals].szString[f_strlen(pDispVals[ *puiNumVals].szString)];
if ( !(uiFlags & F_DOMEDIT_FLAG_ENDTAG))
{
f_sprintf( pszString, "<");
pszString++;
}
else
{
f_sprintf( pszString, "</");
pszString += 2;
}
// Save the qualified name...
if (RC_BAD( rc = formatText( puzName, FALSE, " ", "=", &pszString)))
{
goto Exit;
}
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = FLM_WHITE;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString);
(*puiNumVals)++;
// Output the attributes, unless this is a terminator
if (!(uiFlags & F_DOMEDIT_FLAG_ENDTAG))
{
pszString = &pDispVals[ *puiNumVals].szString[f_strlen(pDispVals[ *puiNumVals].szString)];
// Get the attribute value
if (RC_BAD( rc = pDomEditor->getNodeValue( pRow->pDomNode, &puzAttrValue)))
{
goto Exit;
}
if (RC_BAD( rc = formatText( puzAttrValue, TRUE, "", "", &pszString)))
{
goto Exit;
}
f_free( &puzAttrValue);
}
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = FLM_LIGHTRED;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString)+1;
(*puiNumVals)++;
// Add the trailing '>'
f_sprintf( pDispVals[ *puiNumVals].szString, pRow->bHasChildren ? ">" : "/>");
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = FLM_WHITE;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
(*puiNumVals)++;
Exit:
if (pRow->pDomNode)
{
pRow->pDomNode->Release();
pRow->pDomNode = NULL;
}
f_free( &puzName);
f_free( &puzAttrName);
f_free( &puzAttrValue);
return rc;
}
/*=============================================================================
Desc: Format a Text Node
*============================================================================*/
FSTATIC RCODE formatDataNode(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pRow,
FLMUINT * puiNumVals,
FLMUINT uiFlags,
const char * pszPreText,
const char * pszPostText)
{
RCODE rc = NE_XFLM_OK;
FLMUNICODE * puzValue = NULL;
FLMBOOL bStringEmpty;
char * pszString;
FLMUINT uiCol;
DME_DISP_COLUMN * pDispVals;
eColorType uiForeground;
if (pRow->pDomNode)
{
uiForeground = pRow->pDomNode->isQuarantined()
? FLM_LIGHTCYAN
: FLM_WHITE;
}
else
{
uiForeground = FLM_WHITE;
}
if ((pDispVals = pDomEditor->getDispColumns()) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
f_memset( pDispVals, 0, sizeof(DME_DISP_COLUMN));
uiCol = pRow->uiLevel * 2;
// Output the Expand/Collapse symbol - check the flags
if (pRow->bHasChildren)
{
if ( !(uiFlags & F_DOMEDIT_FLAG_HIDE_EXPAND))
{
f_sprintf( pDispVals[ *puiNumVals].szString,
"%s", pRow->bExpanded ? "-" : "+");
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = FLM_WHITE;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString) + 2;
(*puiNumVals)++;
}
}
else
{
uiCol += 3;
}
/*
Output the level
*/
if( !(uiFlags & F_DOMEDIT_FLAG_HIDE_LEVEL))
{
f_sprintf( pDispVals[ *puiNumVals].szString,
"%u", pRow->uiLevel);
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = FLM_WHITE;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString) + 2;
(*puiNumVals)++;
}
else
{
uiCol += 2;
}
if (RC_BAD( rc = pDomEditor->getNodeValue( pRow->pDomNode, &puzValue)))
{
goto Exit;
}
bStringEmpty = FALSE;
if (!puzValue || !(*puzValue) || (*puzValue == '\n' && puzValue [1] == 0))
{
bStringEmpty = TRUE;
}
if (!bStringEmpty || pszPreText || pszPostText)
{
pszString = &pDispVals[ *puiNumVals].szString[
f_strlen(pDispVals[ *puiNumVals].szString)];
if (RC_BAD( rc = formatText( puzValue, FALSE, pszPreText, pszPostText, &pszString)))
{
goto Exit;
}
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = uiForeground;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
(*puiNumVals)++;
}
Exit:
f_free( &puzValue);
return rc;
}
/*=============================================================================
Desc: Format a Processing Instruction Node
*============================================================================*/
FSTATIC RCODE formatProcessingInstruction(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pRow,
FLMUINT * puiNumVals,
FLMUINT uiFlags
)
{
RCODE rc = NE_XFLM_OK;
FLMUNICODE * puzName = NULL;
FLMUNICODE * puzValue = NULL;
char * pszString;
FLMUINT uiCol;
DME_DISP_COLUMN * pDispVals;
if ((pDispVals = pDomEditor->getDispColumns()) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
f_memset( pDispVals, 0, sizeof(DME_DISP_COLUMN));
uiCol = pRow->uiLevel * 2;
/*
Output the Expand/Collapse symbol - check the flags
*/
if ( !(uiFlags & F_DOMEDIT_FLAG_HIDE_EXPAND))
{
f_sprintf( pDispVals[ *puiNumVals].szString,
"%s", pRow->bExpanded ? "-" : "+");
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = FLM_WHITE;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString) + 2;
(*puiNumVals)++;
}
else
{
uiCol += 2;
}
/*
Output the level
*/
if( !(uiFlags & F_DOMEDIT_FLAG_HIDE_LEVEL))
{
f_sprintf( pDispVals[ *puiNumVals].szString,
"%u", pRow->uiLevel);
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = FLM_WHITE;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString) + 2;
(*puiNumVals)++;
}
else
{
uiCol += 2;
}
// Get the target name
if (RC_BAD( rc = pDomEditor->getNodeName( pRow->pDomNode, NULL, &puzName)))
{
goto Exit;
}
// Get the target data
if (RC_BAD( rc = pDomEditor->getNodeValue( pRow->pDomNode, &puzValue)))
{
goto Exit;
}
pszString = &pDispVals[ *puiNumVals].szString[
f_strlen(pDispVals[ *puiNumVals].szString)];
if (RC_BAD( formatText( puzName, FALSE, "<?", " ", &pszString)))
{
goto Exit;
}
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = FLM_WHITE;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString) + 2;
(*puiNumVals)++;
pszString = &pDispVals[ *puiNumVals].szString[
f_strlen(pDispVals[ *puiNumVals].szString)];
if (RC_BAD( formatText( puzValue, FALSE, NULL, "?>", &pszString)))
{
goto Exit;
}
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = FLM_WHITE;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
(*puiNumVals)++;
Exit:
f_free( &puzName);
f_free( &puzValue);
return rc;
}
/*=============================================================================
Desc: Format a generic node without using the DOM.
*============================================================================*/
FSTATIC RCODE formatRow(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pRow,
FLMUINT * puiNumVals,
FLMUINT uiFlags
)
{
RCODE rc = NE_XFLM_OK;
FLMUINT uiCol = 0;
DME_DISP_COLUMN * pDispVals;
if ((pDispVals = pDomEditor->getDispColumns()) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
f_memset( pDispVals, 0, sizeof(DME_DISP_COLUMN));
uiCol = pRow->uiLevel * 2;
/*
Output the Expand/Collapse symbol - check the flags
*/
if ( !(uiFlags & F_DOMEDIT_FLAG_HIDE_EXPAND))
{
f_sprintf( pDispVals[ *puiNumVals].szString,
"%s", pRow->bExpanded ? "-" : "+");
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = FLM_WHITE;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString) + 2;
(*puiNumVals)++;
}
else
{
uiCol += 2;
}
/*
Output the level
*/
if( !(uiFlags & F_DOMEDIT_FLAG_HIDE_LEVEL))
{
f_sprintf( pDispVals[ *puiNumVals].szString,
"%u", pRow->uiLevel);
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = FLM_WHITE;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString) + 2;
(*puiNumVals)++;
}
else
{
uiCol += 2;
}
if (RC_BAD( rc = unicodeToAscii(
pRow->puzValue, pDispVals[ *puiNumVals].szString, unicodeStrLen( pRow->puzValue))))
{
goto Exit;
}
pDispVals[ *puiNumVals].uiCol = (uiFlags & F_DOMEDIT_FLAG_COMMENT ? 0 : uiCol);
pDispVals[ *puiNumVals].uiForeground = FLM_WHITE;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
(*puiNumVals)++;
Exit:
return rc;
}
/******************************************************************************
Desc:
******************************************************************************/
FSTATIC void printNodeType(
DME_ROW_INFO * pRow,
FTX_WINDOW * pStatusWin
)
{
eDomNodeType eType = pRow->eType;
switch (eType)
{
case INVALID_NODE :
FTXWinPrintf( pStatusWin, " | Type: Unknown");
break;
case ELEMENT_NODE:
FTXWinPrintf( pStatusWin, " | Type: Element");
break;
case DATA_NODE:
FTXWinPrintf( pStatusWin, " | Type: Text");
break;
case CDATA_SECTION_NODE:
FTXWinPrintf( pStatusWin, " | Type: CDATA");
break;
case PROCESSING_INSTRUCTION_NODE:
FTXWinPrintf( pStatusWin, " | Type: Processing Instruction");
break;
case COMMENT_NODE:
FTXWinPrintf( pStatusWin, " | Type: Comment");
break;
case DOCUMENT_NODE:
FTXWinPrintf( pStatusWin, " | Type: Document");
break;
case ATTRIBUTE_NODE:
FTXWinPrintf( pStatusWin, " | Type: Attribute");
break;
default:
break;
}
}
/******************************************************************************
Desc:
******************************************************************************/
FSTATIC void releaseRow(
DME_ROW_INFO ** ppRow
)
{
DME_ROW_INFO * pRow = *ppRow;
if (pRow->puzValue)
{
f_free( &pRow->puzValue);
}
if (pRow->pDomNode)
{
pRow->pDomNode->Release();
}
if (pRow->pVector && pRow->uiElementNumber == 0)
{
pRow->pVector->reset();
pRow->pVector->Release();
}
*ppRow = pRow->pNext;
if (pRow->pPrev)
{
pRow->pPrev->pNext = pRow->pNext;
}
if (pRow->pNext)
{
pRow->pNext->pPrev = pRow->pPrev;
}
f_free( &pRow);
}
/******************************************************************************
Desc:
******************************************************************************/
void F_DomEditor::releaseLastRow()
{
DME_ROW_INFO * pLastRow = m_pScrLastRow->pPrev;
flmAssert( pLastRow);
releaseRow( &m_pScrLastRow);
m_pScrLastRow = pLastRow;
m_pScrLastRow->pNext = NULL;
m_uiNumRows--;
}
/******************************************************************************
Desc:
******************************************************************************/
RCODE F_DomEditor::getNextTitle(
DME_ROW_INFO * pRow,
DME_ROW_INFO ** ppNewRow
)
{
RCODE rc = NE_XFLM_OK;
FLMUINT uiIndex = 0;
F_DOMNode * pDOMNode = NULL;
FLMUNICODE * puzTitle=NULL;
FLMUINT64 ui64DocumentID;
FLMUINT64 ui64NodeID;
DME_ROW_INFO * pTmpRow = NULL;
if (RC_BAD( rc = getDomNode(pRow->ui64NodeId,
pRow->eType == ATTRIBUTE_NODE
? pRow->uiNameId
: 0,
&pRow->pDomNode)))
{
goto Exit;
}
if (RC_BAD( rc = pRow->pDomNode->getNextDocument(
m_pDb, (IF_DOMNode **)&pDOMNode)))
{
if (rc == NE_XFLM_NOT_FOUND || rc == NE_XFLM_DOM_NODE_NOT_FOUND)
{
rc = NE_XFLM_OK;
}
goto Exit;
}
if( RC_BAD( rc = pDOMNode->getNodeId( m_pDb, &ui64NodeID)))
{
goto Exit;
}
if( RC_BAD( rc = pDOMNode->getDocumentId( m_pDb, &ui64DocumentID)))
{
goto Exit;
}
if (RC_BAD( rc = makeNewRow( &pTmpRow, NULL, ui64NodeID)))
{
goto Exit;
}
pTmpRow->ui64DocId = ui64DocumentID;
pTmpRow->uiIndex = uiIndex;
pTmpRow->uiFlags = (F_DOMEDIT_FLAG_HIDE_LEVEL |
F_DOMEDIT_FLAG_HIDE_EXPAND |
F_DOMEDIT_FLAG_LIST_ITEM |
F_DOMEDIT_FLAG_READ_ONLY);
*ppNewRow = pTmpRow;
pTmpRow = NULL;
Exit:
if (pTmpRow)
{
releaseRow( &pTmpRow);
}
if (pDOMNode)
{
pDOMNode->Release();
}
f_free( &puzTitle);
return rc;
}
/******************************************************************************
Desc:
******************************************************************************/
RCODE F_DomEditor::getPrevTitle(
DME_ROW_INFO * pRow,
DME_ROW_INFO ** ppNewRow
)
{
RCODE rc = NE_XFLM_OK;
F_DOMNode * pDOMNode = NULL;
FLMUNICODE * puzTitle=NULL;
FLMUINT64 ui64DocumentID;
DME_ROW_INFO * pTmpRow = NULL;
if (RC_BAD( rc = getDomNode(pRow->ui64NodeId,
pRow->eType == ATTRIBUTE_NODE
? pRow->uiNameId
: 0,
&pRow->pDomNode)))
{
goto Exit;
}
if (RC_BAD( rc = pRow->pDomNode->getPreviousDocument(
m_pDb, (IF_DOMNode **)&pDOMNode)))
{
if (rc == NE_XFLM_NOT_FOUND || rc == NE_XFLM_DOM_NODE_NOT_FOUND)
{
rc = NE_XFLM_OK;
}
goto Exit;
}
if( RC_BAD( rc = pDOMNode->getNodeId( m_pDb, &ui64DocumentID)))
{
goto Exit;
}
if (RC_BAD( rc = makeNewRow( &pTmpRow, NULL, ui64DocumentID)))
{
goto Exit;
}
pTmpRow->uiIndex--;
pTmpRow->uiFlags = (F_DOMEDIT_FLAG_HIDE_LEVEL |
F_DOMEDIT_FLAG_HIDE_EXPAND |
F_DOMEDIT_FLAG_LIST_ITEM |
F_DOMEDIT_FLAG_READ_ONLY);
*ppNewRow = pTmpRow;
pTmpRow = NULL;
Exit:
if (pTmpRow)
{
releaseRow( &pTmpRow);
}
if (pDOMNode)
{
pDOMNode->Release();
}
f_free( &puzTitle);
return rc;
}
/******************************************************************************
Desc: Retrieve the dom node if not already present.
******************************************************************************/
FSTATIC RCODE getDOMNode(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pRow
)
{
RCODE rc = NE_XFLM_OK;
if (!pRow->pDomNode)
{
if (RC_BAD( rc = pDomEditor->getDomNode( pRow->ui64NodeId,
pRow->eType == ATTRIBUTE_NODE
? pRow->uiNameId
: 0,
&pRow->pDomNode)))
{
goto Exit;
}
pRow->eType = pRow->pDomNode->getNodeType();
}
Exit:
return rc;
}
/****************************************************************************
Desc: Edit a text buffer
*****************************************************************************/
#define MIN_BUFSIZE 80
RCODE F_DomEditor::editTextBuffer(
char ** ppszBuffer,
FLMUINT uiBufSize,
FLMUINT * puiTermChar
)
{
RCODE rc = NE_XFLM_OK;
char * pszBuffer = *ppszBuffer;
FLMUINT uiNumCols;
FLMUINT uiNumRows;
FLMUINT uiNumWinRows = 3;
FLMUINT uiNumWinCols;
FTX_WINDOW * pWindow = NULL;
IF_FileHdl * pFileHdl = NULL;
flmAssert( m_bSetupCalled == TRUE);
FTXScreenGetSize( m_pScreen, &uiNumCols, &uiNumRows);
uiNumWinCols = uiNumCols - 8;
if( RC_BAD( rc = FTXWinInit( m_pScreen, uiNumWinCols,
uiNumWinRows, &pWindow)))
{
goto Exit;
}
FTXWinSetScroll( pWindow, FALSE);
FTXWinSetCursorType( pWindow, FLM_CURSOR_UNDERLINE);
FTXWinSetBackFore( pWindow, m_bMonochrome ? FLM_BLACK : FLM_CYAN, FLM_WHITE);
FTXWinClear( pWindow);
FTXWinDrawBorder( pWindow);
FTXWinMove( pWindow, (uiNumCols - uiNumWinCols) / 2,
(uiNumRows - uiNumWinRows) / 2);
FTXWinOpen( pWindow);
FTXWinClear( pWindow);
// Adjust the buffer size if needed.
if (uiBufSize < MIN_BUFSIZE)
{
if (RC_BAD( rc = f_realloc( MIN_BUFSIZE, ppszBuffer)))
{
goto Exit;
}
pszBuffer = *ppszBuffer;
if (!uiBufSize)
{
f_memset( pszBuffer, 0, MIN_BUFSIZE);
}
uiBufSize = MIN_BUFSIZE;
}
if( RC_BAD( rc = FTXLineEdit( pWindow, pszBuffer, uiBufSize, uiBufSize,
NULL, puiTermChar)))
{
rc = RC_SET( NE_XFLM_FAILURE);
goto Exit;
}
Exit:
if( pFileHdl)
{
pFileHdl->Release();
}
if( pWindow)
{
FTXWinFree( &pWindow);
}
return( rc);
}
/******************************************************************************
Desc:
******************************************************************************/
RCODE F_DomEditor::editRow(
FLMUINT, //uiCurRow,
DME_ROW_INFO * pCurRow,
FLMBOOL bReadOnly
)
{
RCODE rc = NE_XFLM_OK;
FLMUNICODE * puzBuffer = NULL;
char * pszBuffer = NULL;
FLMUINT uiBufSize;
FLMUINT uiTermChar;
eDomNodeType eType;
FLMUINT uiDataType;
// Get the dom node
if (RC_BAD( rc = getDOMNode( this, pCurRow)))
{
goto Exit;
}
eType = pCurRow->pDomNode->getNodeType();
switch (eType)
{
case ATTRIBUTE_NODE:
{
if (RC_BAD( rc = getNodeValue( pCurRow->pDomNode, &puzBuffer, &uiBufSize)))
{
goto Exit;
}
if (bReadOnly)
{
if (RC_BAD( rc = f_calloc( uiBufSize + 2, &pszBuffer)))
{
goto Exit;
}
if (RC_BAD( rc = unicodeToAscii( puzBuffer, pszBuffer, uiBufSize)))
{
goto Exit;
}
}
else
{
if (RC_BAD( rc = f_calloc( (uiBufSize * 2) + 2, &pszBuffer)))
{
goto Exit;
}
if (RC_BAD( rc = unicodeToAscii( puzBuffer, pszBuffer, uiBufSize)))
{
goto Exit;
}
}
if (bReadOnly)
{
FLMUINT uiRows;
uiRows = uiBufSize / (m_uiEditCanvasCols - 4) + 3;
if (RC_BAD( rc = FTXDisplayScrollWindow( m_pScreen, "View",
pszBuffer, m_uiEditCanvasCols - 4, uiRows > 10 ? 10 : uiRows)))
{
goto Exit;
}
}
else
{
if (RC_BAD( rc = editTextBuffer( &pszBuffer, uiBufSize * 2, &uiTermChar)))
{
goto Exit;
}
}
// Save the results?
if (uiTermChar == FKB_ENTER && !bReadOnly)
{
// Begin a transaction
if (RC_BAD( rc = beginTransaction( XFLM_UPDATE_TRANS)))
{
goto Exit;
}
// Need to know the attribute data type.
if (RC_BAD( pCurRow->pDomNode->getDataType( m_pDb, &uiDataType)))
{
goto Exit;
}
switch (uiDataType)
{
case XFLM_TEXT_TYPE:
{
// Get a new unicode buffer....
f_free( &puzBuffer);
if (RC_BAD( rc = f_calloc( (f_strlen( pszBuffer) * 2) + 2, &puzBuffer)))
{
goto Exit;
}
asciiToUnicode( pszBuffer, puzBuffer);
if (RC_BAD( rc = pCurRow->pDomNode->setUnicode(
m_pDb, puzBuffer, unicodeStrLen(puzBuffer), TRUE)))
{
(void)abortTransaction();
goto Exit;
}
break;
}
case XFLM_NUMBER_TYPE:
{
FLMUINT64 ui64Value;
if( RC_BAD( rc = getNumber( pszBuffer, &ui64Value, NULL)))
{
displayMessage( "Invalid number", rc,
NULL, FLM_RED, FLM_WHITE);
goto Exit;
}
if (RC_BAD( rc = pCurRow->pDomNode->setUINT64( m_pDb, ui64Value)))
{
goto Exit;
}
break;
}
case XFLM_BINARY_TYPE:
{
rc = RC_SET( NE_XFLM_BAD_DATA_TYPE);
goto Exit;
}
}
// Commit the transaction
if (RC_BAD( rc = commitTransaction()))
{
goto Exit;
}
}
break;
}
case DATA_NODE:
case CDATA_SECTION_NODE:
case COMMENT_NODE:
{
if (RC_BAD( rc = getNodeValue( pCurRow->pDomNode, &puzBuffer, &uiBufSize)))
{
goto Exit;
}
if (bReadOnly)
{
if (RC_BAD( rc = f_calloc( uiBufSize + 2, &pszBuffer)))
{
goto Exit;
}
if (RC_BAD( rc = unicodeToAscii( puzBuffer, pszBuffer, uiBufSize)))
{
goto Exit;
}
}
else
{
if (RC_BAD( rc = f_calloc( (uiBufSize * 2) + 2, &pszBuffer)))
{
goto Exit;
}
if (RC_BAD( rc = unicodeToAscii( puzBuffer, pszBuffer, uiBufSize)))
{
goto Exit;
}
}
if (bReadOnly)
{
FLMUINT uiRows;
uiRows = uiBufSize / (m_uiEditCanvasCols - 4) + 3;
if (RC_BAD( rc = FTXDisplayScrollWindow( m_pScreen, "View",
pszBuffer, m_uiEditCanvasCols - 4, uiRows > 10 ? 10 : uiRows)))
{
goto Exit;
}
}
else
{
if (RC_BAD( rc = editTextBuffer( &pszBuffer, uiBufSize, &uiTermChar)))
{
goto Exit;
}
}
// Save the results?
if (uiTermChar == FKB_ENTER && !bReadOnly)
{
// Get a new unicode buffer....
f_free( &puzBuffer);
if (RC_BAD( rc = f_calloc( (f_strlen( pszBuffer) * 2) + 2, &puzBuffer)))
{
goto Exit;
}
asciiToUnicode( pszBuffer, puzBuffer);
// Begin a transaction
if (RC_BAD( rc = beginTransaction( XFLM_UPDATE_TRANS)))
{
goto Exit;
}
if (RC_BAD( rc = pCurRow->pDomNode->setUnicode(
m_pDb, puzBuffer, unicodeStrLen( puzBuffer) * sizeof( FLMUNICODE),
TRUE)))
{
goto Exit;
}
// Commit the transaction
if (RC_BAD( rc = commitTransaction()))
{
goto Exit;
}
}
break;
}
case ELEMENT_NODE:
{
rc = selectElementAttribute( pCurRow, &uiTermChar);
goto Exit;
}
default:
{
break;
}
}
Exit:
if (m_pDb->getTransType() != XFLM_NO_TRANS)
{
(void)abortTransaction();
}
if (pCurRow->pDomNode)
{
pCurRow->pDomNode->Release();
pCurRow->pDomNode = NULL;
}
f_free( &puzBuffer);
f_free( &pszBuffer);
return rc;
}
/******************************************************************************
Desc:
******************************************************************************/
RCODE F_DomEditor::editIndexRow(
DME_ROW_INFO * pCurRow
)
{
RCODE rc = NE_XFLM_OK;
FLMUNICODE * puzBuffer = NULL;
char * pszBuffer = NULL;
FLMUINT uiBufSize = 0;
FLMUINT uiTermChar;
F_DataVector * pVector = pCurRow->pVector;
FLMUINT uiElementNumber = pCurRow->uiElementNumber;
if (!pCurRow->bUseValue)
{
flmAssert( pVector);
// Get the current value in the buffer or display the one in the buffer.
switch( pVector->getDataType( uiElementNumber))
{
case XFLM_TEXT_TYPE:
{
if ((uiBufSize = pVector->getDataLength( uiElementNumber)) > 0)
{
if (RC_BAD( rc = f_calloc( uiBufSize, &pszBuffer)))
{
goto Exit;
}
if (RC_BAD( rc = pVector->getUTF8( uiElementNumber,
(FLMBYTE *)pszBuffer, &uiBufSize)))
{
goto Exit;
}
}
else
{
uiBufSize = 30;
if (RC_BAD( rc = f_calloc( uiBufSize, &pszBuffer)))
{
goto Exit;
}
*pszBuffer = 0;
}
break;
}
case XFLM_NUMBER_TYPE:
{
FLMUINT64 ui64Num;
uiBufSize = 23; // Largest number of charcters in a 64 bit number + 3.
if (RC_BAD( rc = f_calloc( uiBufSize, &pszBuffer)))
{
goto Exit;
}
if (RC_BAD( rc = pVector->getUINT64( uiElementNumber, &ui64Num)))
{
if (rc == NE_XFLM_NOT_FOUND)
{
*pszBuffer = 0;
rc = NE_XFLM_OK;
}
else
{
goto Exit;
}
}
else
{
f_sprintf( pszBuffer, "0x%I64x", ui64Num);
}
break;
}
case XFLM_NODATA_TYPE:
case XFLM_BINARY_TYPE:
default:
{
rc = RC_SET( NE_XFLM_BAD_DATA_TYPE);
break;
}
}
}
else
{
puzBuffer = pCurRow->puzValue;
pCurRow->puzValue = NULL;
uiBufSize = unicodeStrLen( puzBuffer);
if (RC_BAD( rc = unicodeToAscii( puzBuffer, pszBuffer, uiBufSize)))
{
goto Exit;
}
}
if (RC_BAD( rc = editTextBuffer( &pszBuffer, uiBufSize * 2, &uiTermChar)))
{
goto Exit;
}
// Save the results?
if (uiTermChar == FKB_ENTER)
{
switch( pVector->getDataType( uiElementNumber))
{
case XFLM_UNKNOWN_TYPE:
case XFLM_NODATA_TYPE:
case XFLM_TEXT_TYPE:
{
if (RC_BAD( rc = pVector->setUTF8( uiElementNumber,
(FLMBYTE *)pszBuffer)))
{
goto Exit;
}
break;
}
case XFLM_NUMBER_TYPE:
{
FLMUINT64 ui64Num = f_atou64( pszBuffer);
if (RC_BAD( rc = pVector->setUINT64( uiElementNumber, ui64Num)))
{
goto Exit;
}
break;
}
}
}
else
{
pCurRow->puzValue = puzBuffer;
puzBuffer = NULL;
}
Exit:
f_free( &puzBuffer);
f_free( &pszBuffer);
return rc;
}
/******************************************************************************
Desc:
******************************************************************************/
RCODE F_DomEditor::editIndexNode(
DME_ROW_INFO * pCurRow
)
{
RCODE rc = NE_XFLM_OK;
FLMUNICODE * puzBuffer = NULL;
char * pszBuffer = NULL;
FLMUINT uiBufSize = 0;
FLMUINT uiTermChar;
F_DataVector * pVector = pCurRow->pVector;
FLMUINT uiElementNumber = pCurRow->uiElementNumber;
FLMUINT64 ui64NodeId;
if (!pCurRow->bUseValue)
{
flmAssert( pVector);
ui64NodeId = pVector->getID( uiElementNumber);
uiBufSize = 23; // Largest number of charcters in a 64 bit number + 3.
if (RC_BAD( rc = f_calloc( uiBufSize, &pszBuffer)))
{
goto Exit;
}
f_sprintf( pszBuffer, "%I64u", ui64NodeId);
}
else
{
puzBuffer = pCurRow->puzValue;
pCurRow->puzValue = NULL;
uiBufSize = unicodeStrLen( puzBuffer);
if (RC_BAD( rc = unicodeToAscii( puzBuffer, pszBuffer, uiBufSize)))
{
goto Exit;
}
}
if (RC_BAD( rc = editTextBuffer( &pszBuffer, uiBufSize * 2, &uiTermChar)))
{
goto Exit;
}
// Save the results?
if (uiTermChar == FKB_ENTER)
{
FLMUINT64 ui64Num = f_atou64( pszBuffer);
if (RC_BAD( rc = pVector->setID( uiElementNumber, ui64Num)))
{
goto Exit;
}
}
else
{
pCurRow->puzValue = puzBuffer;
puzBuffer = NULL;
}
Exit:
f_free( &puzBuffer);
f_free( &pszBuffer);
return rc;
}
/****************************************************************************
Desc: Allows the user to interactively select and edit the attributes of an
element node
*****************************************************************************/
RCODE F_DomEditor::selectElementAttribute(
DME_ROW_INFO * pRow,
FLMUINT * puiTermChar)
{
RCODE rc = NE_XFLM_OK;
DME_ROW_INFO * pTmpRow = NULL;
DME_ROW_INFO * pPrevRow = NULL;
FLMUINT uiFlags;
F_DomEditor * pAttributeList = NULL;
F_DOMNode * pAttrNode = NULL;
FLMBOOL bGotFirstAttr;
flmAssert( m_bSetupCalled == TRUE);
if( puiTermChar)
{
*puiTermChar = 0;
}
if (pRow->uiFlags & F_DOMEDIT_FLAG_ENDTAG)
{
rc = displayMessage( "Cannot edit Element end tag",
NE_XFLM_FAILURE, puiTermChar, FLM_RED, FLM_WHITE);
goto Exit;
}
// Initialize the name table.
if( !m_pNameTable)
{
if( RC_BAD( rc = refreshNameTable()))
{
goto Exit;
}
}
if( (pAttributeList = f_new F_DomEditor) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
if( RC_BAD( rc = pAttributeList->Setup( m_pScreen)))
{
goto Exit;
}
pAttributeList->setParent( this);
pAttributeList->setReadOnly( FALSE);
pAttributeList->setShutdown( m_pbShutdown);
pAttributeList->setTitle( "Attributes - Select One");
pAttributeList->setKeyHook( F_DomEditorSelectionKeyHook, 0);
pAttributeList->setSource( m_pDb, m_uiCollection);
if( m_pDb == NULL)
{
goto Exit;
}
uiFlags = (F_DOMEDIT_FLAG_HIDE_LEVEL | F_DOMEDIT_FLAG_HIDE_EXPAND |
F_DOMEDIT_FLAG_LIST_ITEM | F_DOMEDIT_FLAG_NOPARENT | F_DOMEDIT_FLAG_NOCHILD);
// Get the dom node for the selected row (element)
if (RC_BAD( rc = getDOMNode( this, pRow)))
{
goto Exit;
}
// Verify that the node is an element node.
if (pRow->pDomNode->getNodeType() != ELEMENT_NODE)
{
rc = displayMessage( "Invalid node type",
NE_XFLM_FAILURE, puiTermChar, FLM_RED, FLM_WHITE);
goto Exit;
}
// Get the attributes...
bGotFirstAttr = FALSE;
for (;;)
{
if (!bGotFirstAttr)
{
// Get the first attribute
if (RC_BAD( rc = pRow->pDomNode->getFirstAttribute( m_pDb,
(IF_DOMNode **)&pAttrNode)))
{
if (rc == NE_XFLM_NOT_FOUND || rc == NE_XFLM_EOF_HIT || rc == NE_XFLM_DOM_NODE_NOT_FOUND)
{
rc = NE_XFLM_OK;
break;
}
else
{
goto Exit;
}
}
if (RC_BAD( rc = buildNewRow( 0,
pAttrNode,
&pTmpRow)))
{
goto Exit;
}
bGotFirstAttr = TRUE;
}
else
{
if (RC_BAD( rc = pAttrNode->getNextSibling(
m_pDb, (IF_DOMNode **)&pAttrNode)))
{
if (rc == NE_XFLM_NOT_FOUND ||
rc == NE_XFLM_EOF_HIT ||
rc == NE_XFLM_DOM_NODE_NOT_FOUND)
{
rc = NE_XFLM_OK;
break;
}
else
{
goto Exit;
}
}
if (RC_BAD( rc = buildNewRow( 0,
pAttrNode,
&pTmpRow)))
{
goto Exit;
}
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pAttributeList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
}
if (pAttrNode)
{
pAttrNode->Release();
pAttrNode = NULL;
}
// Set the start row.
pAttributeList->setCurrentAtTop();
if( RC_BAD( rc = pAttributeList->interactiveEdit(
m_uiULX, m_uiULY, m_uiLRX, m_uiLRY)))
{
goto Exit;
}
if( (pTmpRow = pAttributeList->getScrFirstRow()) == NULL)
{
goto Exit;
}
while( pTmpRow)
{
pAttributeList->getControlFlags( pTmpRow, &uiFlags);
if( uiFlags & F_DOMEDIT_FLAG_SELECTED)
{
uiFlags &= ~F_DOMEDIT_FLAG_SELECTED;
pAttributeList->setControlFlags( pTmpRow, uiFlags);
break;
}
if (RC_BAD( rc = pAttributeList->getNextRow( pTmpRow, &pTmpRow)))
{
goto Exit;
}
}
if (pTmpRow)
{
if (RC_BAD( rc = editRow( 0, pTmpRow)))
{
goto Exit;
}
}
if( puiTermChar)
{
*puiTermChar = pAttributeList->getLastKey();
}
Exit:
if (pAttrNode)
{
pAttrNode->Release();
}
if (pRow->pDomNode)
{
pRow->pDomNode->Release();
pRow->pDomNode = NULL;
}
if( pAttributeList)
{
pAttributeList->Release();
pAttributeList = NULL;
}
return( rc);
}
/******************************************************************************
Desc: Method to delete a node (row)
******************************************************************************/
RCODE F_DomEditor::deleteRow(
DME_ROW_INFO ** ppCurRow
)
{
RCODE rc = NE_XFLM_OK;
DME_ROW_INFO * pRow = *ppCurRow;
FLMBOOL bNextRow = TRUE;
FLMUINT uiTermChar;
char szMessage[ 100];
char szResponse[ 3];
if (!canDeleteRow(pRow))
{
rc = RC_SET( NE_XFLM_ILLEGAL_OP);
goto Exit;
}
// Confirm this action before deleting...
switch (pRow->eType)
{
case DOCUMENT_NODE:
f_sprintf( szMessage, "Delete DOCUMENT_NODE [%,I64u]? ",
pRow->ui64DocId);
break;
case ELEMENT_NODE:
f_sprintf( szMessage, "Delete ELEMENT_NODE [%,I64u]? ",
pRow->ui64NodeId);
break;
case ATTRIBUTE_NODE:
f_sprintf( szMessage, "Delete ATTRIBUTE_NODE [%,I64u]? ",
pRow->ui64NodeId);
break;
case DATA_NODE:
f_sprintf( szMessage, "Delete DATA_NODE [%,I64u]? ",
pRow->ui64NodeId);
break;
default:
f_sprintf( szMessage, "Delete UNKNOWN_NODE [%,I64u]? ",
pRow->ui64NodeId);
break;
}
f_memset( szResponse, 0, sizeof(szResponse));
requestInput( szMessage,
&szResponse[ 0], sizeof( szResponse), &uiTermChar);
if( uiTermChar == FKB_ESCAPE || szResponse[ 0] == 'N' || szResponse[ 0] == 'n')
{
goto Exit;
}
if ( szResponse[ 0] != 'Y' && szResponse[ 0] != 'y')
{
goto Exit;
}
// If the current row is expanded, we first need to collapse it.
if (pRow->bExpanded)
{
if (RC_BAD( rc = collapseRow( &pRow)))
{
goto Exit;
}
}
// Start an update transaction
if( RC_BAD( rc = beginTransaction( XFLM_UPDATE_TRANS)))
{
goto Exit;
}
// Get the dom for this row but don't start a new transaction.
if (RC_BAD( rc = getDOMNode( this, pRow)))
{
goto Exit;
}
if (RC_BAD( rc = pRow->pDomNode->deleteNode( m_pDb)))
{
(void)abortTransaction();
goto Exit;
}
pRow->pDomNode->Release();
pRow->pDomNode = NULL;
if (RC_BAD( rc = commitTransaction()))
{
goto Exit;
}
// return the next or previous row.
if (RC_BAD( rc = getNextRow( pRow, ppCurRow, TRUE)))
{
if (rc == NE_XFLM_DOM_NODE_NOT_FOUND)
{
rc = NE_XFLM_OK;
}
else
{
goto Exit;
}
}
if (*ppCurRow == NULL)
{
if (RC_BAD( rc = getPrevRow( pRow, ppCurRow, TRUE)))
{
if (rc == NE_XFLM_DOM_NODE_NOT_FOUND)
{
rc = NE_XFLM_OK;
}
else
{
goto Exit;
}
}
bNextRow = FALSE;
}
if (m_pScrFirstRow == pRow)
{
m_pScrFirstRow = *ppCurRow;
}
if (m_pScrLastRow == pRow)
{
m_pScrLastRow = *ppCurRow;
}
if (pRow->ui64NodeId == pRow->ui64DocId)
{
DME_ROW_INFO * pDoc = m_pCurDoc;
// will need to remove this Document from the DocList.
checkDocument( &pDoc, pRow);
if (pDoc)
{
if (pDoc->pPrev)
{
pDoc->pPrev->pNext = pDoc->pNext;
}
if (pDoc->pNext)
{
pDoc->pNext->pPrev = pDoc->pPrev;
}
if (m_pDocList == pDoc)
{
m_pDocList = pDoc->pNext;
}
m_pCurDoc = pDoc->pNext;
f_free( &pDoc);
}
}
releaseRow( &pRow);
m_uiNumRows--;
// See if we can get a new last row.
if ( *ppCurRow)
{
while (m_uiNumRows < m_uiEditCanvasRows)
{
if (RC_BAD( rc = getNextRow( pRow, &pRow, TRUE)))
{
goto Exit;
}
if (pRow == NULL)
{
break;
}
}
}
if (pRow)
{
m_pScrLastRow = pRow;
pRow = NULL;
}
// If the new current row is null, then point to the last row - it too may be null
// but in that case, there is nothing to display.
if (*ppCurRow == NULL)
{
*ppCurRow = m_pScrLastRow;
bNextRow = FALSE;
}
// If the new cursor row is a parent of the node we just deleted,
// we need to re-set the bHasChildren flag. There may not be anymore
// children, so we want this to display correctly.
pRow = *ppCurRow;
if (pRow)
{
if (pRow->bExpanded &&
((bNextRow && pRow->uiFlags & F_DOMEDIT_FLAG_ENDTAG) ||
(!bNextRow && !(pRow->uiFlags & F_DOMEDIT_FLAG_ENDTAG))))
{
if (RC_BAD( rc = collapseRow( &pRow)))
{
goto Exit;
}
}
if (RC_BAD( rc = getDOMNode( this, pRow)))
{
goto Exit;
}
if (RC_BAD( rc = pRow->pDomNode->hasChildren(
m_pDb, &pRow->bHasChildren)))
{
goto Exit;
}
}
// Sync the document list to the row.
checkDocument(&m_pCurDoc, pRow);
Exit:
if (pRow)
{
if (pRow->pDomNode)
{
pRow->pDomNode->Release();
pRow->pDomNode = NULL;
}
}
if (m_pDb->getTransType() != XFLM_NO_TRANS)
{
(void)abortTransaction();
}
return rc;
}
/******************************************************************************
Desc:
******************************************************************************/
RCODE F_DomEditor::addSomething(
DME_ROW_INFO ** ppCurRow
)
{
RCODE rc = NE_XFLM_OK;
eDomNodeType eNodeType;
FLMUINT uiTermChar;
// Select the type of Node that we are going to add.
if (RC_BAD( rc = selectNodeType( &eNodeType, &uiTermChar)))
{
goto Exit;
}
if( uiTermChar != FKB_ENTER)
{
goto Exit;
}
switch (eNodeType)
{
case ELEMENT_NODE:
{
if (*ppCurRow)
{
if (RC_BAD( rc = createElementNode( ppCurRow)))
{
goto Exit;
}
}
else
{
if (RC_BAD( rc = createRootElementNode( ppCurRow)))
{
goto Exit;
}
}
break;
}
case ATTRIBUTE_NODE:
{
if (RC_BAD( rc = createAttributeNode( ppCurRow)))
{
goto Exit;
}
break;
}
case DATA_NODE:
case COMMENT_NODE:
case CDATA_SECTION_NODE:
{
if (RC_BAD( rc = createTextNode( ppCurRow, eNodeType)))
{
goto Exit;
}
break;
}
case DOCUMENT_NODE:
{
if (RC_BAD( rc = createDocumentNode( ppCurRow)))
{
goto Exit;
}
if (RC_BAD( rc = addDocumentToList(
m_uiCollection, (*ppCurRow)->ui64DocId)))
{
goto Exit;
}
break;
}
case PROCESSING_INSTRUCTION_NODE:
default:
{
rc = RC_SET( NE_XFLM_FAILURE);
goto Exit;
}
}
Exit:
return rc;
}
/******************************************************************************
Desc:
******************************************************************************/
RCODE F_DomEditor::createDocumentNode(
DME_ROW_INFO ** ppCurRow
)
{
RCODE rc = NE_XFLM_OK;
char szResponse[ 128];
FLMUNICODE * puzTitle = NULL;
FLMUINT uiTitleLen;
FLMUINT uiTermChar;
F_DOMNode * pDocNode = NULL;
DME_ROW_INFO * pNewRow = NULL;
IF_DOMNode * pSource = NULL;
f_memset( szResponse, 0, sizeof(szResponse));
requestInput( "Document Title / Comment",
szResponse, sizeof( szResponse), &uiTermChar);
if( uiTermChar == FKB_ESCAPE)
{
goto Exit;
}
uiTitleLen = f_strlen( szResponse);
if (RC_BAD( rc = f_calloc( (uiTitleLen * 2) + 2, &puzTitle)))
{
goto Exit;
}
asciiToUnicode( szResponse, puzTitle);
// Begin a transaction
if (RC_BAD( rc = beginTransaction( XFLM_UPDATE_TRANS)))
{
goto Exit;
}
// Create a new document node.
if (RC_BAD( m_pDb->createDocument(
m_uiCollection, (IF_DOMNode **)&pDocNode)))
{
goto Exit;
}
// save the source
if( RC_BAD( rc = pDocNode->createAttribute(
m_pDb, ATTR_SOURCE_TAG, &pSource)))
{
goto Exit;
}
if (RC_BAD( rc = pSource->setUnicode(
(IF_Db *)m_pDb, puzTitle, unicodeStrLen(puzTitle), TRUE)))
{
goto Exit;
}
if (m_uiNumRows < m_uiEditCanvasRows)
{
// Create a new row and link it to the end of the list.
if (RC_BAD( rc = buildNewRow( 0,
(F_DOMNode *)pDocNode,
&pNewRow)))
{
goto Exit;
}
if (RC_BAD( rc = insertRow( pNewRow, m_pScrLastRow)))
{
goto Exit;
}
// May Need to remove the first row.
if (m_uiNumRows > m_uiEditCanvasRows)
{
releaseRow( &m_pScrFirstRow);
m_uiNumRows--;
}
*ppCurRow = pNewRow;
pNewRow = NULL;
}
if (RC_BAD( rc = m_pDb->documentDone( pDocNode)))
{
goto Exit;
}
// Commit...
if (RC_BAD( rc = commitTransaction()))
{
goto Exit;
}
Exit:
if (pNewRow)
{
releaseRow( &pNewRow);
}
if (pDocNode)
{
pDocNode->Release();
}
if (pSource)
{
pSource->Release();
}
f_free( &puzTitle);
if (m_pDb->getTransType() != XFLM_NO_TRANS)
{
(void)abortTransaction();
}
return rc;
}
/*=============================================================================
Desc: Method to create a root element node rather than a document node.
=============================================================================*/
RCODE F_DomEditor::createRootElementNode(
DME_ROW_INFO ** ppCurRow
)
{
RCODE rc = NE_XFLM_OK;
char szResponse[ 128];
FLMUNICODE * puzTitle = NULL;
FLMUINT uiTitleLen;
FLMUINT uiTermChar;
F_DOMNode * pRootNode = NULL;
DME_ROW_INFO * pNewRow = NULL;
IF_DOMNode * pSource = NULL;
FLMUINT uiTag;
RCODE tmpRc;
FLMUINT uiCollection;
if( RC_BAD( tmpRc = selectCollection( &uiCollection, &uiTermChar)))
{
displayMessage( "Error getting collection", tmpRc,
NULL, FLM_RED, FLM_WHITE);
}
if( uiTermChar != FKB_ENTER)
{
goto Exit;
}
f_memset( szResponse, 0, sizeof(szResponse));
requestInput( "Element Title / Comment",
szResponse,
sizeof( szResponse),
&uiTermChar);
if( uiTermChar == FKB_ESCAPE)
{
goto Exit;
}
uiTitleLen = f_strlen( szResponse);
if (RC_BAD( rc = f_calloc( (uiTitleLen * 2) + 2, &puzTitle)))
{
goto Exit;
}
asciiToUnicode( szResponse, puzTitle);
// Select the name tag for the element node
if (RC_BAD( rc = selectTag( ELM_ELEMENT_TAG, &uiTag, &uiTermChar)))
{
goto Exit;
}
if( uiTermChar == FKB_ESCAPE)
{
goto Exit;
}
// Begin a transaction
if (RC_BAD( rc = beginTransaction( XFLM_UPDATE_TRANS)))
{
goto Exit;
}
// Create a new document node.
if (RC_BAD( m_pDb->createRootElement( uiCollection,
uiTag,
(IF_DOMNode **)&pRootNode)))
{
goto Exit;
}
// save the source
if (RC_BAD( rc = pRootNode->createAttribute(
m_pDb, ATTR_SOURCE_TAG, &pSource)))
{
goto Exit;
}
if (RC_BAD( rc = pSource->setUnicode( (IF_Db *)m_pDb,
puzTitle,
unicodeStrLen(puzTitle),
TRUE)))
{
goto Exit;
}
if (uiCollection == m_uiCollection)
{
if (m_uiNumRows < m_uiEditCanvasRows)
{
// Create a new row and link it to the end of the list.
if (RC_BAD( rc = buildNewRow( 0,
(F_DOMNode *)pRootNode,
&pNewRow)))
{
goto Exit;
}
if (RC_BAD( rc = insertRow( pNewRow,
m_pScrLastRow)))
{
goto Exit;
}
// May Need to remove the first row.
if (m_uiNumRows > m_uiEditCanvasRows)
{
releaseRow( &m_pScrFirstRow);
m_uiNumRows--;
}
*ppCurRow = pNewRow;
pNewRow = NULL;
}
if (RC_BAD( rc = addDocumentToList( m_uiCollection,
(*ppCurRow)->ui64DocId)))
{
goto Exit;
}
}
if (RC_BAD( rc = m_pDb->documentDone( pRootNode)))
{
goto Exit;
}
// Commit...
if (RC_BAD( rc = commitTransaction()))
{
goto Exit;
}
Exit:
if (pNewRow)
{
releaseRow( &pNewRow);
}
if (pRootNode)
{
pRootNode->Release();
}
if (pSource)
{
pSource->Release();
}
f_free( &puzTitle);
if (m_pDb->getTransType() != XFLM_NO_TRANS)
{
(void)abortTransaction();
}
return rc;
}
/****************************************************************************
Desc: Create an ELEMENT_ NODE Dom node.
*****************************************************************************/
RCODE F_DomEditor::createElementNode(
DME_ROW_INFO ** ppCurRow
)
{
RCODE rc = NE_XFLM_OK;
DME_ROW_INFO * pRow = *ppCurRow;
char szResponse[ 5];
FLMUINT uiTermChar;
FLMUINT uiTag;
F_DOMNode * pRefNode = NULL;
F_DOMNode * pElementNode = NULL;
FLMUINT64 ui64RootId;
FLMBOOL bAddSibling = FALSE;
f_memset( szResponse, 0, sizeof(szResponse));
requestInput( "Create a Root Element?",
szResponse,
sizeof( szResponse),
&uiTermChar);
if( uiTermChar == FKB_ESCAPE)
{
goto Exit;
}
if (szResponse[0] == 'Y' || szResponse[0] == 'y')
{
rc = createRootElementNode( ppCurRow);
goto Exit;
}
if (!pRow)
{
displayMessage( "No DOM Node to add to.",
NE_XFLM_FAILURE, NULL, FLM_RED, FLM_WHITE);
goto Exit;
}
// Verify that the node we are looking at can take an element node. Some
// dom node types can't take a sibling or a child element node.
if (pRow->eType != DOCUMENT_NODE &&
pRow->eType != ELEMENT_NODE)
{
displayMessage( "Invalid DOM node type",
NE_XFLM_FAILURE, NULL, FLM_RED, FLM_WHITE);
goto Exit;
}
// Select the name tag for the element node
if (RC_BAD( rc = selectTag( ELM_ELEMENT_TAG, &uiTag, &uiTermChar)))
{
goto Exit;
}
if (uiTermChar == FKB_ESCAPE)
{
goto Exit;
}
if (RC_BAD( rc = beginTransaction( XFLM_UPDATE_TRANS)))
{
goto Exit;
}
// Get the dom node for this row.
if (RC_BAD( rc = getDomNode( pRow->ui64NodeId,
pRow->eType == ATTRIBUTE_NODE
? pRow->uiNameId
: 0,
&pRefNode)))
{
goto Exit;
}
// Get the root node.
if( RC_BAD( rc = pRefNode->getDocumentId( m_pDb, &ui64RootId)))
{
goto Exit;
}
// We need to make sure we have the right root node.
switch (pRow->eType)
{
case DOCUMENT_NODE:
{
pRow->bHasChildren = TRUE;
// Got it already
break;
}
case ELEMENT_NODE:
{
// If we are inserting as a sibling to this node, we need to get the parent node.
// Do we want to add this element as a child or a sibling to the current node.
f_memset( szResponse, 0, sizeof( szResponse));
requestInput( "Insert as Sibling node?",
szResponse, sizeof( szResponse), &uiTermChar);
if (uiTermChar == FKB_ESCAPE)
{
goto Exit;
}
if ( szResponse[ 0] == 'Y' || szResponse[ 0] == 'y')
{
// Need to get the parent node.
if (RC_BAD( rc = pRefNode->getParentNode(
m_pDb, (IF_DOMNode **)&pRefNode)))
{
goto Exit;
}
bAddSibling = TRUE;
}
}
default:
{
break;
}
}
if (RC_BAD( rc = pRefNode->createNode(
m_pDb, ELEMENT_NODE, uiTag, XFLM_LAST_CHILD,
(IF_DOMNode **)&pElementNode)))
{
goto Exit;
}
if (bAddSibling)
{
DME_ROW_INFO * pNewRow = NULL;
FLMUINT uiLevel = pRow->uiLevel;
// We need to insert the new row into the list
if (RC_BAD( rc = buildNewRow( (FLMINT)pRow->uiLevel,
pElementNode,
&pNewRow)))
{
goto Exit;
}
if (pRow->pDomNode)
{
pRow->pDomNode->Release();
pRow->pDomNode = NULL;
}
while (pRow && pRow->pNext && pRow->pNext->uiLevel >= uiLevel)
{
pRow = pRow->pNext;
}
if (pRow && (pRow != m_pScrLastRow || m_uiNumRows < m_uiEditCanvasRows))
{
if (RC_BAD( rc = insertRow( pNewRow, pRow)))
{
goto Exit;
}
}
}
else
{
pRow->bHasChildren = TRUE;
if (pRow->bExpanded)
{
// Collapse the row, then expand it.
if (RC_BAD( rc = collapseRow( &pRow)))
{
goto Exit;
}
if (RC_BAD( rc = expandRow( pRow, TRUE, NULL)))
{
goto Exit;
}
}
}
if (RC_BAD( rc = m_pDb->documentDone( pRefNode)))
{
goto Exit;
}
if (RC_BAD( rc = commitTransaction()))
{
goto Exit;
}
Exit:
if (pRow->pDomNode)
{
pRow->pDomNode->Release();
pRow->pDomNode = NULL;
}
if (pRefNode)
{
pRefNode->Release();
}
if (pElementNode)
{
pElementNode->Release();
}
if (m_pDb->getTransType() != XFLM_NO_TRANS)
{
(void)abortTransaction();
}
return rc;
}
/****************************************************************************
Desc: Method to create text type nodes.
*****************************************************************************/
RCODE F_DomEditor::createTextNode(
DME_ROW_INFO ** ppCurRow,
eDomNodeType eNodeType
)
{
RCODE rc = NE_XFLM_OK;
DME_ROW_INFO * pRow = *ppCurRow;
DME_ROW_INFO * pNewRow = NULL;
char szResponse[ 5];
FLMUINT uiTermChar;
F_DOMNode * pRefNode = NULL;
F_DOMNode * pTextNode = NULL;
FLMUINT64 ui64RootId;
FLMBOOL bAddSibling = FALSE;
char szTextBuffer[ 120];
FLMUINT uiTextBufLen = sizeof(szTextBuffer);
FLMBOOL bHasChildren = pRow->bHasChildren;
// Verify that the node we are looking at can take the type of
// node either as a child or sibling...
if (pRow->eType != DOCUMENT_NODE &&
pRow->eType != ATTRIBUTE_NODE &&
pRow->eType != ELEMENT_NODE)
{
displayMessage( "Invalid DOM node type",
NE_XFLM_FAILURE, NULL, FLM_RED, FLM_WHITE);
goto Exit;
}
f_memset( szTextBuffer, 0, uiTextBufLen);
requestInput( "Text",
szTextBuffer, uiTextBufLen, &uiTermChar);
if (uiTermChar == FKB_ESCAPE)
{
goto Exit;
}
if (RC_BAD( rc = beginTransaction( XFLM_UPDATE_TRANS)))
{
goto Exit;
}
// Get the dom node for this row.
if (RC_BAD( rc = getDomNode( pRow->ui64NodeId,
pRow->eType == ATTRIBUTE_NODE
? pRow->uiNameId
: 0,
&pRefNode)))
{
goto Exit;
}
// Get the root node.
if( RC_BAD( rc = pRefNode->getDocumentId( m_pDb, &ui64RootId)))
{
goto Exit;
}
// We need to make sure we have the right root node.
switch (pRow->eType)
{
case DOCUMENT_NODE:
{
pRow->bHasChildren = TRUE;
// No parent node for these
break;
}
default:
{
// If we are inserting as a sibling to this node, we need to get the parent node.
// Do we want to add this element as a child or a sibling to the current node.
f_memset( szResponse, 0, sizeof( szResponse));
requestInput( "Insert as Sibling node?",
szResponse, sizeof( szResponse), &uiTermChar);
if (uiTermChar == FKB_ESCAPE)
{
goto Exit;
}
if ( szResponse[ 0] == 'Y' || szResponse[ 0] == 'y')
{
// Need to get the parent node.
if (RC_BAD( pRefNode->getParentNode(
m_pDb, (IF_DOMNode **)&pRefNode)))
{
goto Exit;
}
bAddSibling = TRUE;
}
}
}
if (RC_BAD( rc = pRefNode->createNode(
m_pDb, eNodeType, 0, XFLM_LAST_CHILD,
(IF_DOMNode **)&pTextNode)))
{
goto Exit;
}
if (RC_BAD( rc = pTextNode->setUTF8( m_pDb, (FLMBYTE *)szTextBuffer)))
{
goto Exit;
}
if (bAddSibling)
{
FLMUINT uiLevel = pRow->uiLevel;
// We need to insert the new row into the list
if (RC_BAD( rc = buildNewRow( (FLMINT)pRow->uiLevel,
pTextNode,
&pNewRow)))
{
goto Exit;
}
pTextNode->AddRef();
if (pRow->pDomNode)
{
pRow->pDomNode->Release();
pRow->pDomNode = NULL;
}
while (pRow && pRow->pNext && pRow->pNext->uiLevel >= uiLevel)
{
pRow = pRow->pNext;
}
if (pRow && (pRow != m_pScrLastRow || m_uiNumRows < m_uiEditCanvasRows))
{
if (RC_BAD( rc = insertRow( pNewRow, pRow)))
{
goto Exit;
}
}
}
else
{
pRow->bHasChildren = TRUE;
if (pRow->bExpanded)
{
// Collapse the row, then expand it.
if (RC_BAD( rc = collapseRow( &pRow)))
{
goto Exit;
}
if (RC_BAD( rc = expandRow( pRow, TRUE, NULL)))
{
goto Exit;
}
}
}
if (RC_BAD( rc = m_pDb->documentDone( pRefNode)))
{
goto Exit;
}
if (RC_BAD( rc = commitTransaction()))
{
goto Exit;
}
Exit:
// Restore the bHasChildren flag on error.
if (RC_BAD( rc))
{
pRow->bHasChildren = bHasChildren;
}
if (pRow->pDomNode)
{
pRow->pDomNode->Release();
pRow->pDomNode = NULL;
}
if (pRefNode)
{
pRefNode->Release();
}
if (pTextNode)
{
pTextNode->Release();
}
if (pNewRow && pNewRow->pDomNode)
{
pNewRow->pDomNode->Release();
pNewRow->pDomNode = NULL;
}
if (m_pDb->getTransType() != XFLM_NO_TRANS)
{
(void)abortTransaction();
}
return rc;
}
/****************************************************************************
Desc: Create an ATTRIBUTE_NODE Dom node.
*****************************************************************************/
RCODE F_DomEditor::createAttributeNode(
DME_ROW_INFO ** ppCurRow
)
{
RCODE rc = NE_XFLM_OK;
DME_ROW_INFO * pRow = *ppCurRow;
FLMUINT uiTermChar;
FLMUINT uiTag;
F_DOMNode * pRefNode = NULL;
F_DOMNode * pAttributeNode = NULL;
char szAttrValue[ 128];
FLMUNICODE * puzValue = NULL;
FLMUINT uiValueLen;
F_Dict * pDict;
FLMUINT64 ui64Value;
F_AttrElmInfo defInfo;
FLMUINT uiEncDefId = 0;
// Verify that the node we are looking at can take an element node. Some
// dom node types can't take a sibling or a child element node.
if (pRow->eType != ELEMENT_NODE)
{
displayMessage( "Invalid DOM node type",
NE_XFLM_FAILURE, NULL, FLM_RED, FLM_WHITE);
goto Exit;
}
// Select the name tag for the element node
if (RC_BAD( rc = selectTag( ELM_ATTRIBUTE_TAG, &uiTag, &uiTermChar)))
{
goto Exit;
}
if (uiTermChar == FKB_ESCAPE)
{
goto Exit;
}
f_memset( szAttrValue, 0, sizeof( szAttrValue));
requestInput( "Attribute Value",
szAttrValue, sizeof(szAttrValue), &uiTermChar);
if (uiTermChar == FKB_ESCAPE)
{
goto Exit;
}
// Select the encryption algorithm (if any)
if (RC_BAD( rc = selectEncDef( ELM_ENCDEF_TAG, &uiEncDefId, &uiTermChar)))
{
goto Exit;
}
if (uiTermChar == FKB_ESCAPE)
{
goto Exit;
}
if (RC_BAD( rc = beginTransaction( XFLM_UPDATE_TRANS)))
{
goto Exit;
}
// Determine the data type for the selected attribute tag.
if (RC_BAD( rc = m_pDb->getDictionary( &pDict)))
{
goto Exit;
}
if (RC_BAD( rc = pDict->getAttribute( m_pDb, uiTag, &defInfo)))
{
goto Exit;
}
// Get the dom node for this row.
if (RC_BAD( rc = getDomNode( pRow->ui64NodeId,
pRow->eType == ATTRIBUTE_NODE
? pRow->uiNameId
: 0,
&pRefNode)))
{
goto Exit;
}
if (RC_BAD( rc = pRefNode->createAttribute(
m_pDb, uiTag, (IF_DOMNode **)&pAttributeNode)))
{
goto Exit;
}
switch (defInfo.getDataType())
{
case XFLM_TEXT_TYPE:
{
uiValueLen = (f_strlen( szAttrValue) * 2) + 2;
if (RC_BAD( f_calloc( uiValueLen, &puzValue)))
{
goto Exit;
}
asciiToUnicode( &szAttrValue[0], puzValue);
if (RC_BAD( rc = pAttributeNode->setUnicode( m_pDb,
puzValue,
uiValueLen,
TRUE,
uiEncDefId)))
{
goto Exit;
}
break;
}
case XFLM_NUMBER_TYPE:
{
if( RC_BAD( rc = getNumber( &szAttrValue[ 0], &ui64Value, NULL)))
{
displayMessage( "Invalid node number", rc,
NULL, FLM_RED, FLM_WHITE);
goto Exit;
}
if (RC_BAD( rc = pAttributeNode->setUINT64( m_pDb, ui64Value, uiEncDefId)))
{
goto Exit;
}
break;
}
case XFLM_BINARY_TYPE:
default:
rc = RC_SET( NE_XFLM_BAD_DATA_TYPE);
goto Exit;
}
pRow->bHasAttributes = TRUE;
if (RC_BAD( rc = m_pDb->documentDone( pRefNode)))
{
goto Exit;
}
if (RC_BAD( rc = commitTransaction()))
{
goto Exit;
}
Exit:
f_free( &puzValue);
if (pRow->pDomNode)
{
pRow->pDomNode->Release();
pRow->pDomNode = NULL;
}
if (pRefNode)
{
pRefNode->Release();
}
if (pAttributeNode)
{
pAttributeNode->Release();
}
if (m_pDb->getTransType() != XFLM_NO_TRANS)
{
(void)abortTransaction();
}
return rc;
}
/****************************************************************************
Desc: Allows the user to interactively select a Dom Node type
*****************************************************************************/
RCODE F_DomEditor::selectNodeType(
eDomNodeType * peNodeType,
FLMUINT * puiTermChar
)
{
RCODE rc = NE_XFLM_OK;
DME_ROW_INFO * pTmpRow = NULL;
DME_ROW_INFO * pPrevRow = NULL;
FLMUINT uiFlags;
FLMUNICODE uzItemName[ 128];
F_DomEditor * pNodeTypeList = NULL;
flmAssert( m_bSetupCalled == TRUE);
if( peNodeType)
{
*peNodeType = INVALID_NODE;
}
if( puiTermChar)
{
*puiTermChar = 0;
}
// Initialize the name table.
if( !m_pNameTable)
{
if( RC_BAD( rc = refreshNameTable()))
{
goto Exit;
}
}
if( (pNodeTypeList = f_new F_DomEditor) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
if( RC_BAD( rc = pNodeTypeList->Setup( m_pScreen)))
{
goto Exit;
}
pNodeTypeList->setParent( this);
pNodeTypeList->setReadOnly( TRUE);
pNodeTypeList->setShutdown( m_pbShutdown);
pNodeTypeList->setTitle( "Node Types - Select One");
pNodeTypeList->setKeyHook( F_DomEditorSelectionKeyHook, 0);
pNodeTypeList->setSource( m_pDb, XFLM_DATA_COLLECTION);
if( m_pDb == NULL)
{
goto Exit;
}
uiFlags = (F_DOMEDIT_FLAG_HIDE_LEVEL | F_DOMEDIT_FLAG_HIDE_EXPAND |
F_DOMEDIT_FLAG_LIST_ITEM | F_DOMEDIT_FLAG_READ_ONLY | F_DOMEDIT_FLAG_NODOM);
asciiToUnicode( "Element Node", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], (FLMUINT)ELEMENT_NODE, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pNodeTypeList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "Attribute Node", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], (FLMUINT)ATTRIBUTE_NODE, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pNodeTypeList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "Text Node", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], (FLMUINT)DATA_NODE, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pNodeTypeList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "CData Section Node", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], (FLMUINT)CDATA_SECTION_NODE, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pNodeTypeList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "Processing Instruction Node", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], (FLMUINT)PROCESSING_INSTRUCTION_NODE, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pNodeTypeList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "Comment Node", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], (FLMUINT)COMMENT_NODE, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pNodeTypeList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "Document Node", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], (FLMUINT)DOCUMENT_NODE, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pNodeTypeList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
// Set the start row.
pNodeTypeList->setCurrentAtTop();
if( RC_BAD( rc = pNodeTypeList->interactiveEdit(
m_uiULX, m_uiULY, m_uiLRX, m_uiLRY)))
{
goto Exit;
}
if( (pTmpRow = pNodeTypeList->getScrFirstRow()) == NULL)
{
goto Exit;
}
while( pTmpRow)
{
pNodeTypeList->getControlFlags( pTmpRow, &uiFlags);
if( uiFlags & F_DOMEDIT_FLAG_SELECTED)
{
uiFlags &= ~F_DOMEDIT_FLAG_SELECTED;
pNodeTypeList->setControlFlags( pTmpRow, uiFlags);
if( peNodeType)
{
*peNodeType = (eDomNodeType)pTmpRow->ui64NodeId;
}
pTmpRow = NULL;
break;
}
if (RC_BAD( rc = pNodeTypeList->getNextRow( pTmpRow, &pTmpRow)))
{
goto Exit;
}
}
if( puiTermChar)
{
*puiTermChar = pNodeTypeList->getLastKey();
}
Exit:
if( pNodeTypeList)
{
pNodeTypeList->Release();
pNodeTypeList = NULL;
}
if (pTmpRow)
{
releaseRow( &pTmpRow);
}
return( rc);
}
/*=============================================================================
Desc:
=============================================================================*/
RCODE F_DomEditor::beginTransaction(
eDbTransType eTransType)
{
RCODE rc = NE_XFLM_OK;
if (RC_BAD( rc = m_pDb->transBegin( eTransType)))
{
if (rc == NE_XFLM_TRANS_ACTIVE)
{
if (eTransType != m_pDb->getTransType())
{
if (RC_BAD( rc = m_pDb->transCommit()))
{
(void)m_pDb->transAbort();
}
if (RC_BAD( rc = m_pDb->transBegin( eTransType)))
{
goto Exit;
}
}
}
else
{
goto Exit;
}
rc = NE_XFLM_OK;
}
Exit:
return rc;
}
/*=============================================================================
Desc:
=============================================================================*/
RCODE F_DomEditor::commitTransaction( void)
{
RCODE rc = NE_XFLM_OK;
if (m_pDb->getTransType() != XFLM_NO_TRANS)
{
if (RC_BAD( rc = m_pDb->transCommit()))
{
goto Exit;
}
}
Exit:
return rc;
}
/*=============================================================================
Desc:
=============================================================================*/
RCODE F_DomEditor::abortTransaction( void)
{
RCODE rc = NE_XFLM_OK;
if (m_pDb->getTransType() != XFLM_NO_TRANS)
{
if (RC_BAD( rc = m_pDb->transAbort()))
{
goto Exit;
}
// We need to clear the Abort status flag in the pDb.
if (RC_BAD( rc = m_pDb->transBegin( XFLM_READ_TRANS)))
{
goto Exit;
}
if (RC_BAD( rc = m_pDb->transCommit()))
{
goto Exit;
}
}
Exit:
return rc;
}
/*=============================================================================
Desc: Utility method to make sure the row and document list docId match.
=============================================================================*/
void F_DomEditor::checkDocument(
DME_ROW_INFO ** ppDocRow,
DME_ROW_INFO * pRow
)
{
DME_ROW_INFO * pDocList = *ppDocRow;
// If there is no current row, then we don't care about the document list.
if (!pRow)
{
return;
}
if (!pDocList)
{
return;
}
// If they already match, no need to test.
if ( pRow->ui64DocId == pDocList->ui64DocId)
{
return;
}
// Start from the beginning.
pDocList = m_pDocList;
while (pDocList && pRow->ui64DocId != pDocList->ui64DocId)
{
pDocList = pDocList->pNext;
}
flmAssert( pDocList);
flmAssert( pDocList->ui64DocId == pRow->ui64DocId);
*ppDocRow = pDocList;
}
/*=============================================================================
Desc: Method to ask the user to select which tag they want.
=============================================================================*/
RCODE F_DomEditor::selectTag(
FLMUINT uiTagType,
FLMUINT * puiTag,
FLMUINT * puiTermChar
)
{
RCODE rc = NE_XFLM_OK;
DME_ROW_INFO * pTmpRow = NULL;
DME_ROW_INFO * pPrevRow = NULL;
FLMUINT uiFlags;
FLMUNICODE uzItemName[ 128];
FLMUINT uiId;
FLMUINT uiNextPos;
F_DomEditor * pTagList = NULL;
FLMUINT uiDataType;
flmAssert( m_bSetupCalled == TRUE);
if( puiTag)
{
*puiTag = 0;
}
if( puiTermChar)
{
*puiTermChar = 0;
}
// Initialize the name table.
if( !m_pNameTable)
{
if( RC_BAD( rc = refreshNameTable()))
{
goto Exit;
}
}
if( (pTagList = f_new F_DomEditor) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
if( RC_BAD( rc = pTagList->Setup( m_pScreen)))
{
goto Exit;
}
pTagList->setParent( this);
pTagList->setReadOnly( TRUE);
pTagList->setShutdown( m_pbShutdown);
pTagList->setTitle( "Tag Names - Select One");
pTagList->setKeyHook( F_DomEditorSelectionKeyHook, 0);
pTagList->setSource( m_pDb, XFLM_DICT_COLLECTION);
if( m_pDb == NULL)
{
goto Exit;
}
uiFlags = (F_DOMEDIT_FLAG_HIDE_LEVEL | F_DOMEDIT_FLAG_HIDE_EXPAND |
F_DOMEDIT_FLAG_LIST_ITEM | F_DOMEDIT_FLAG_READ_ONLY | F_DOMEDIT_FLAG_NODOM);
uiNextPos = 0;
while( RC_OK( rc = m_pNameTable->getNextTagTypeAndNameOrder(
uiTagType, &uiNextPos, uzItemName, NULL, sizeof( uzItemName), &uiId, &uiDataType)))
{
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], uiId, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pTagList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
}
if (rc != NE_XFLM_EOF_HIT)
{
goto Exit;
}
rc = NE_XFLM_OK;
// Set the start row.
pTagList->setCurrentAtTop();
if( RC_BAD( rc = pTagList->interactiveEdit(
m_uiULX, m_uiULY, m_uiLRX, m_uiLRY)))
{
goto Exit;
}
if( (pTmpRow = pTagList->getScrFirstRow()) == NULL)
{
goto Exit;
}
while( pTmpRow)
{
pTagList->getControlFlags( pTmpRow, &uiFlags);
if( uiFlags & F_DOMEDIT_FLAG_SELECTED)
{
uiFlags &= ~F_DOMEDIT_FLAG_SELECTED;
pTagList->setControlFlags( pTmpRow, uiFlags);
if( puiTag)
{
*puiTag = (FLMUINT)pTmpRow->ui64NodeId;
}
pTmpRow = NULL;
break;
}
if (RC_BAD( rc = pTagList->getNextRow( pTmpRow, &pTmpRow)))
{
goto Exit;
}
}
if( puiTermChar)
{
*puiTermChar = pTagList->getLastKey();
}
Exit:
if( pTagList)
{
pTagList->Release();
pTagList = NULL;
}
if (pTmpRow)
{
releaseRow( &pTmpRow);
}
return( rc);
}
/****************************************************************************
Name: selectEncDef
*****************************************************************************/
RCODE F_DomEditor::selectEncDef(
FLMUINT uiTagType,
FLMUINT * puiEncDefId,
FLMUINT * puiTermChar)
{
RCODE rc = NE_XFLM_OK;
DME_ROW_INFO * pTmpRow = NULL;
DME_ROW_INFO * pPrevRow = NULL;
FLMUINT uiFlags;
FLMUNICODE uzItemName[ 128];
FLMUNICODE uzNone[] =
{'<','N','o',' ','e','n','c','r','y','p','t','i','o','n','>','\0'};
FLMUINT uiId;
FLMUINT uiNextPos;
F_DomEditor * pEncDefList = NULL;
FLMBOOL bFoundEncDef = FALSE;
flmAssert( m_bSetupCalled == TRUE);
if( puiEncDefId)
{
*puiEncDefId = 0;
}
if( puiTermChar)
{
*puiTermChar = 0;
}
// Initialize the name table.
if( !m_pNameTable)
{
if( RC_BAD( rc = refreshNameTable()))
{
goto Exit;
}
}
if( (pEncDefList = f_new F_DomEditor) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
if( RC_BAD( rc = pEncDefList->Setup( m_pScreen)))
{
goto Exit;
}
pEncDefList->setParent( this);
pEncDefList->setReadOnly( TRUE);
pEncDefList->setShutdown( m_pbShutdown);
pEncDefList->setTitle( "Encryption Algorithm Names - Select One");
pEncDefList->setKeyHook( F_DomEditorSelectionKeyHook, 0);
pEncDefList->setSource( m_pDb, XFLM_DICT_COLLECTION);
if( m_pDb == NULL)
{
goto Exit;
}
uiFlags = (F_DOMEDIT_FLAG_HIDE_LEVEL | F_DOMEDIT_FLAG_HIDE_EXPAND |
F_DOMEDIT_FLAG_LIST_ITEM | F_DOMEDIT_FLAG_READ_ONLY | F_DOMEDIT_FLAG_NODOM);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzNone[0], 0, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pEncDefList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
uiNextPos = 0;
while( RC_OK( rc = m_pNameTable->getNextTagTypeAndNameOrder(
uiTagType, &uiNextPos, uzItemName, NULL, sizeof( uzItemName), &uiId)))
{
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], uiId, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pEncDefList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
bFoundEncDef = TRUE;
}
if (rc != NE_XFLM_EOF_HIT)
{
goto Exit;
}
rc = NE_XFLM_OK;
// Don't bother to ask if there are no encryption algorithms defined.
if (!bFoundEncDef)
{
goto Exit;
}
// Set the start row.
pEncDefList->setCurrentAtTop();
if( RC_BAD( rc = pEncDefList->interactiveEdit(
m_uiULX, m_uiULY, m_uiLRX, m_uiLRY)))
{
goto Exit;
}
if( (pTmpRow = pEncDefList->getScrFirstRow()) == NULL)
{
goto Exit;
}
while( pTmpRow)
{
pEncDefList->getControlFlags( pTmpRow, &uiFlags);
if( uiFlags & F_DOMEDIT_FLAG_SELECTED)
{
uiFlags &= ~F_DOMEDIT_FLAG_SELECTED;
pEncDefList->setControlFlags( pTmpRow, uiFlags);
if( puiEncDefId)
{
*puiEncDefId = (FLMUINT)pTmpRow->ui64NodeId;
}
pTmpRow = NULL;
break;
}
if (RC_BAD( rc = pEncDefList->getNextRow( pTmpRow, &pTmpRow)))
{
goto Exit;
}
}
if( puiTermChar)
{
*puiTermChar = pEncDefList->getLastKey();
}
Exit:
if( pEncDefList)
{
pEncDefList->Release();
pEncDefList = NULL;
}
if (pTmpRow)
{
releaseRow( &pTmpRow);
}
return( rc);
}
/****************************************************************************
Name: selectIndex
Desc: Allows the user to interactively select an index
*****************************************************************************/
RCODE F_DomEditor::selectIndex(
FLMUINT uiFlags,
FLMUINT * puiIndex,
FLMUINT * puiTermChar
)
{
RCODE rc = NE_XFLM_OK;
DME_ROW_INFO * pTmpRow = NULL;
DME_ROW_INFO * pPrevRow = NULL;
FLMUINT uiDispFlags;
F_DomEditor * pIndexList = NULL;
FLMUNICODE uzItemName[ 80];
FLMUINT uiNextPos;
FLMUINT uiId;
flmAssert( m_bSetupCalled == TRUE);
*puiIndex = 0;
if( puiTermChar)
{
*puiTermChar = 0;
}
if( (pIndexList = f_new F_DomEditor) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
if( RC_BAD( rc = pIndexList->Setup( m_pScreen)))
{
goto Exit;
}
pIndexList->setParent( this);
pIndexList->setReadOnly( TRUE);
pIndexList->setShutdown( m_pbShutdown);
pIndexList->setTitle( "Indexes - Select One");
pIndexList->setKeyHook( F_DomEditorSelectionKeyHook, 0);
pIndexList->setSource( m_pDb, XFLM_DICT_COLLECTION);
if( m_pDb == NULL)
{
goto Exit;
}
uiFlags = (F_DOMEDIT_FLAG_HIDE_LEVEL | F_DOMEDIT_FLAG_HIDE_EXPAND |
F_DOMEDIT_FLAG_LIST_ITEM | F_DOMEDIT_FLAG_READ_ONLY | F_DOMEDIT_FLAG_NODOM);
asciiToUnicode( "Dictionary Number Index", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], XFLM_DICT_NUMBER_INDEX, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pIndexList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
asciiToUnicode( "Dictionary Name Index", &uzItemName[0]);
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], XFLM_DICT_NAME_INDEX, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pIndexList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
uiNextPos = 0;
while( RC_OK( rc = m_pNameTable->getNextTagTypeAndNameOrder(
ELM_INDEX_TAG, &uiNextPos, uzItemName,
NULL, sizeof( uzItemName), &uiId)))
{
if (RC_BAD( rc = makeNewRow( &pTmpRow, &uzItemName[0], uiId, TRUE)))
{
goto Exit;
}
pTmpRow->uiFlags = uiFlags;
if (RC_BAD( rc = pIndexList->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
}
if (rc != NE_XFLM_EOF_HIT)
{
goto Exit;
}
rc = NE_XFLM_OK;
// Set the start row.
pIndexList->setCurrentAtTop();
if( RC_BAD( rc = pIndexList->interactiveEdit( m_uiULX, m_uiULY, m_uiLRX, m_uiLRY)))
{
goto Exit;
}
if( (pTmpRow = pIndexList->getScrFirstRow()) == NULL)
{
goto Exit;
}
while( pTmpRow)
{
pIndexList->getControlFlags( pTmpRow, &uiDispFlags);
if( uiDispFlags & F_DOMEDIT_FLAG_SELECTED)
{
uiDispFlags &= ~F_DOMEDIT_FLAG_SELECTED;
pIndexList->setControlFlags( pTmpRow, uiDispFlags);
if (puiIndex)
{
*puiIndex = (FLMUINT)pTmpRow->ui64NodeId;
}
pTmpRow = NULL;
break;
}
if (RC_BAD( rc = pIndexList->getNextRow( pTmpRow, &pTmpRow)))
{
goto Exit;
}
}
if( puiTermChar)
{
*puiTermChar = pIndexList->getLastKey();
}
if( pIndexList->getLastKey() == FKB_ESCAPE)
{
rc = RC_SET( NE_XFLM_NOT_FOUND);
goto Exit;
}
Exit:
if( pIndexList)
{
pIndexList->Release();
pIndexList = NULL;
}
return( rc);
}
/****************************************************************************
Name: indexList
Desc: Allows listing of index keys (and references) by having the user
interactively build from and until keys.
*****************************************************************************/
RCODE F_DomEditor::indexList( void)
{
RCODE rc = NE_XFLM_OK;
FLMUINT uiIndex;
FLMUINT uiTermChar;
F_DomEditor * pKeyEditor = NULL;
F_DataVector * pFromKeyV = NULL;
F_DataVector * pUntilKeyV = NULL;
F_DataVector * pFoundKeyV = NULL;
DME_ROW_INFO * pTmpRow = NULL;
DME_ROW_INFO * pPrevRow = NULL;
FTX_WINDOW * pStatusWindow = NULL;
FLMBYTE * pucUntilKeyBuf = NULL;
FLMBYTE * pucFoundKeyBuf = NULL;
FLMUINT uiUntilKeyLen;
FLMUINT uiFoundKeyLen;
FLMUINT uiSrchFlag;
FLMUINT uiKeyCount = 0;
FLMBOOL bNewKey;
FLMUINT uiElementNumber;
FLMINT iCmp;
FLMBOOL bFirst;
IXD * pIxd;
flmAssert( m_bSetupCalled == TRUE);
if( RC_BAD( rc = selectIndex( 0, &uiIndex, &uiTermChar)))
{
goto Exit;
}
if( uiTermChar != FKB_ENTER)
{
goto Exit;
}
// Initialize the key editor
if( (pKeyEditor = f_new F_DomEditor) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
if( RC_BAD( rc = pKeyEditor->Setup( m_pScreen)))
{
goto Exit;
}
// Configure the editor
pKeyEditor->setParent( this);
pKeyEditor->setShutdown( m_pbShutdown);
pKeyEditor->setTitle( "Index List [ALT-Z to accept]");
pKeyEditor->setSource( m_pDb, uiIndex);
pKeyEditor->setKeyHook( f_KeyEditorKeyHook, NULL);
pKeyEditor->setDisplayHook( f_IndexRangeDispHook, NULL);
// Begin a transaction
if (RC_BAD( rc = beginTransaction( XFLM_READ_TRANS)))
{
goto Exit;
}
if (RC_BAD( rc = m_pDb->getDict()->getIndex( uiIndex, NULL, &pIxd, TRUE)))
{
goto Exit;
}
// Get the first key in the index
if( (pFromKeyV = f_new F_DataVector) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
pFromKeyV->reset();
if (RC_BAD( rc = m_pDb->keyRetrieve( uiIndex, NULL, XFLM_FIRST, pFromKeyV)))
{
goto Exit;
}
if( RC_BAD( rc = pKeyEditor->addComment(
&pPrevRow, "This is the first key in the index")))
{
goto Exit;
}
pPrevRow->uiFlags |= F_DOMEDIT_FLAG_LIST_ITEM;
uiElementNumber = 0;
while( pFromKeyV->getNameId( uiElementNumber))
{
if (RC_BAD( rc = setupIndexRow(
pFromKeyV, uiElementNumber, uiIndex, F_DOMEDIT_FLAG_KEY_FROM, &pTmpRow)))
{
goto Exit;
}
pTmpRow->uiFlags |= F_DOMEDIT_FLAG_LIST_ITEM;
uiElementNumber++;
if (RC_BAD( rc = pKeyEditor->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
}
pFromKeyV = NULL; // Vector is now in the row list
// Get the last key in the index
if( (pUntilKeyV = f_new F_DataVector) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
pUntilKeyV->reset();
if (RC_BAD( rc = m_pDb->keyRetrieve( uiIndex, NULL, XFLM_LAST, pUntilKeyV)))
{
goto Exit;
}
if( RC_BAD( rc = pKeyEditor->addComment(
&pPrevRow, "This is the last key in the index")))
{
goto Exit;
}
pPrevRow->uiFlags |= F_DOMEDIT_FLAG_LIST_ITEM;
uiElementNumber = 0;
while ( pUntilKeyV->getNameId( uiElementNumber))
{
if (RC_BAD( rc = setupIndexRow(
pUntilKeyV, uiElementNumber, uiIndex, F_DOMEDIT_FLAG_KEY_UNTIL, &pTmpRow)))
{
goto Exit;
}
pTmpRow->uiFlags |= F_DOMEDIT_FLAG_LIST_ITEM;
uiElementNumber++;
if (RC_BAD( rc = pKeyEditor->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
}
pUntilKeyV = NULL; // Vector is now in the row list.
// Show the keys and allow them to be edited
pKeyEditor->setCurrentAtTop();
ix_list_retry:
// Allow the user to edit the from / until keys before we start to look for the
// keys in the index.
if( RC_BAD( rc = pKeyEditor->interactiveEdit( m_uiULX, m_uiULY, m_uiLRX, m_uiLRY)))
{
goto Exit;
}
if( pKeyEditor->getLastKey() == FKB_ESCAPE)
{
goto Exit;
}
if( RC_BAD( rc = createStatusWindow(
" Key Retrieval Status (Press ESC to Interrupt) ",
FLM_GREEN, FLM_WHITE, NULL, NULL, &pStatusWindow)))
{
goto Exit;
}
FTXWinOpen( pStatusWindow);
// Get the FROM Key. It may have been changed, so we need to rebuild the vector and do
// another keyRetrieve in order to get the search parameters setup. The display function will
// make sure that any new value will be stored in the puzValue buffer.
pTmpRow = pKeyEditor->m_pScrFirstRow;
while (pTmpRow)
{
if (pTmpRow->uiFlags & F_DOMEDIT_FLAG_KEY_FROM)
{
pFromKeyV = pTmpRow->pVector;
pTmpRow->pVector = NULL;
break;
}
pTmpRow = pTmpRow->pNext;
}
flmAssert( pTmpRow);
// Get the UNTIL Key. It may have been changed, so we need to rebuild the vector and do
// another keyRetrieve in order to get the search parameters setup.
pTmpRow = pKeyEditor->m_pScrFirstRow;
while (pTmpRow)
{
if (pTmpRow->uiFlags & F_DOMEDIT_FLAG_KEY_UNTIL)
{
pUntilKeyV = pTmpRow->pVector;
pTmpRow->pVector = NULL;
break;
}
pTmpRow = pTmpRow->pNext;
}
flmAssert( pTmpRow);
pKeyEditor->releaseAllRows();
bNewKey = TRUE;
// Allocate key buffers for the from & until key so we
// can do comparisons.
if (RC_BAD( rc = f_calloc( XFLM_MAX_KEY_SIZE * 2, &pucUntilKeyBuf)))
{
goto Exit;
}
pucFoundKeyBuf = &pucUntilKeyBuf [XFLM_MAX_KEY_SIZE];
// Get the collated until key.
if (RC_BAD( rc = pUntilKeyV->outputKey(
m_pDb, uiIndex, 0, pucUntilKeyBuf, XFLM_MAX_KEY_SIZE, &uiUntilKeyLen)))
{
goto Exit;
}
// Read the keys
uiSrchFlag = XFLM_INCL | XFLM_MATCH_IDS;
pTmpRow = pPrevRow = NULL;
bFirst = TRUE;
while( !isExiting())
{
// Update the display
FTXWinSetCursorPos( pStatusWindow, 0, 1);
FTXWinPrintf( pStatusWindow, "Keys Retrieved : %u",
(unsigned)uiKeyCount);
FTXWinClearToEOL( pStatusWindow);
FTXWinSetCursorPos( pStatusWindow, 0, 2);
FTXWinClearToEOL( pStatusWindow);
// Test for the escape key
if( RC_OK( FTXWinTestKB( pStatusWindow)))
{
FLMUINT uiChar;
FTXWinInputChar( pStatusWindow, &uiChar);
if( uiChar == FKB_ESCAPE)
{
break;
}
}
if ((pFoundKeyV = f_new F_DataVector) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
// Look for the next key.
if (RC_BAD( rc = m_pDb->keyRetrieve(
uiIndex, pFromKeyV, uiSrchFlag, pFoundKeyV)))
{
if (rc == NE_XFLM_EOF_HIT)
{
break;
}
goto Exit;
}
uiSrchFlag = XFLM_EXCL | XFLM_MATCH_IDS;
// See if we have gone past the until key.
if (RC_BAD( rc = pFoundKeyV->outputKey(
m_pDb, uiIndex, 0, pucFoundKeyBuf, XFLM_MAX_KEY_SIZE, &uiFoundKeyLen)))
{
goto Exit;
}
if (RC_BAD( rc = ixKeyCompare( m_pDb, pIxd, NULL, NULL, NULL,
TRUE, TRUE, pucFoundKeyBuf, uiFoundKeyLen,
pucUntilKeyBuf, uiUntilKeyLen, &iCmp)))
{
goto Exit;
}
if (iCmp > 0)
{
break;
}
uiKeyCount++;
// Make a separator row to display the key number
if (RC_BAD( rc = pKeyEditor->addComment(
&pPrevRow, "Key [%,10u] Document [%,10I64u]",
uiKeyCount, pFoundKeyV->getDocumentID())))
{
goto Exit;
}
pPrevRow->uiFlags |= F_DOMEDIT_FLAG_LIST_ITEM;
// Display the key.
uiElementNumber = 0;
while (pFoundKeyV->getNameId( uiElementNumber))
{
if (RC_BAD( rc = setupIndexRow( pFoundKeyV, uiElementNumber, uiIndex, 0, &pTmpRow)))
{
goto Exit;
}
pTmpRow->uiFlags |= F_DOMEDIT_FLAG_LIST_ITEM;
uiElementNumber++;
if (RC_BAD( rc = pKeyEditor->insertRow( pTmpRow, pPrevRow)))
{
goto Exit;
}
pPrevRow = pTmpRow;
pTmpRow = NULL;
}
if (bFirst)
{
pFromKeyV->Release();
bFirst = FALSE;
}
pFromKeyV = pFoundKeyV;
pFoundKeyV = NULL;
f_yieldCPU();
#ifdef FLM_WIN
f_sleep( 0);
#endif
}
pFromKeyV = NULL; // s/b in a row
if ( pFoundKeyV)
{
pFoundKeyV->Release();
pFoundKeyV = NULL;
}
FTXWinFree( &pStatusWindow);
/*
Display the results
*/
pKeyEditor->setCurrentAtTop();
if( uiKeyCount)
{
pKeyEditor->setTitle( "Index List");
pKeyEditor->setKeyHook( f_ViewOnlyKeyHook, 0);
if( RC_BAD( rc = pKeyEditor->interactiveEdit( m_uiULX, m_uiULY, m_uiLRX, m_uiLRY)))
{
goto Exit;
}
}
else
{
displayMessage(
"No Keys Found Within Specified Range", rc,
NULL, FLM_RED, FLM_WHITE);
pKeyEditor->setCurrentAtTop();
goto ix_list_retry;
}
if (RC_BAD( rc = commitTransaction()))
{
goto Exit;
}
Exit:
f_free( &pucUntilKeyBuf);
if( pFromKeyV)
{
pFromKeyV->Release();
}
if( pFoundKeyV)
{
pFoundKeyV->Release();
}
if( pUntilKeyV)
{
pUntilKeyV->Release();
}
if( pStatusWindow)
{
FTXWinFree( &pStatusWindow);
}
if( pKeyEditor)
{
pKeyEditor->releaseAllRows();
pKeyEditor->Release();
}
if( RC_BAD( rc))
{
if( rc == NE_XFLM_EOF_HIT)
{
displayMessage( "The index is empty", rc,
NULL, FLM_RED, FLM_WHITE);
rc = NE_XFLM_OK;
}
}
if (m_pDb->getTransType() != XFLM_NO_TRANS)
{
(void)abortTransaction();
}
return( rc);
}
typedef struct QueryDataTag
{
FLMUINT uiCollection;
FLMUINT uiNodeArraySize;
FLMUINT64 * pui64Nodes;
FLMUINT * puiAttrNameIds;
FLMUINT uiNodeCount;
FLMUINT uiCurrNode;
FLMBOOL bShowingData;
char * pszQuery;
} QUERY_DATA;
/****************************************************************************
Desc:
*****************************************************************************/
FSTATIC RCODE f_QueryEditorKeyHook(
F_DomEditor * pDomEditor,
DME_ROW_INFO *, // pCurRow,
FLMUINT uiKeyIn,
FLMUINT * puiKeyOut,
void * pvKeyData
)
{
RCODE rc = NE_XFLM_OK;
char szTitle [100];
QUERY_DATA * pQueryData = (QUERY_DATA *)pvKeyData;
switch (uiKeyIn)
{
case 'P':
case 'p':
if (pQueryData->uiCurrNode)
{
pQueryData->uiCurrNode--;
}
Retrieve_Node:
*puiKeyOut = 0;
// Clear the current buffer.
pDomEditor->setScrFirstRow( NULL);
pDomEditor->setCurrentRow(NULL, 0);
if (RC_BAD( rc = pDomEditor->retrieveNodeFromDb( pQueryData->uiCollection,
pQueryData->pui64Nodes [pQueryData->uiCurrNode],
pQueryData->puiAttrNameIds [pQueryData->uiCurrNode])))
{
goto Exit;
}
f_sprintf( szTitle, "#%u of %u (N,SPACE=Next, P=Prev)",
(unsigned)(pQueryData->uiCurrNode + 1),
(unsigned)pQueryData->uiNodeCount);
pDomEditor->setTitle( szTitle);
// Show the query
if (!pQueryData->bShowingData)
{
FTX_WINDOW * pStatusWin = pDomEditor->getStatusWindow();
FTXWinSetCursorPos( pStatusWin, 0, 1);
FTXWinPrintf( pStatusWin, "%s", pQueryData->pszQuery);
pQueryData->bShowingData = TRUE;
}
break;
case 'n':
case 'N':
case ' ':
if (pQueryData->uiCurrNode < pQueryData->uiNodeCount - 1)
{
pQueryData->uiCurrNode++;
}
goto Retrieve_Node;
case 'F':
case 'f':
case FKB_ALT_F:
// Don't allow to start another query.
*puiKeyOut = 0;
break;
default:
*puiKeyOut = uiKeyIn;
if (!pQueryData->bShowingData)
{
goto Retrieve_Node;
}
break;
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Allows doing a query and having the user expand the results of
each returned node.
*****************************************************************************/
void F_DomEditor::doQuery(
char * pszQuery,
FLMUINT uiQueryBufSize)
{
RCODE rc = NE_XFLM_OK;
FLMUINT uiCollection;
FLMUINT uiTermChar;
IF_Query * pQuery = NULL;
F_XPath xpath;
IF_DOMNode * pNode = NULL;
FLMBOOL bStartedTrans = FALSE;
XFLM_OPT_INFO * pOptInfo;
FLMUINT uiOptInfoCnt;
EditQueryStatus queryStatus;
F_DomEditor * pQueryEditor = NULL;
QUERY_DATA QueryData;
FLMUINT uiQueryStrLen;
IF_DbSystem * pDbSystem = NULL;
f_memset( &QueryData, 0, sizeof( QueryData));
requestInput(
"XPATH Query", pszQuery, uiQueryBufSize, &uiTermChar);
if (uiTermChar == FKB_ESCAPE)
{
goto Exit;
}
if( RC_BAD( rc = FlmAllocDbSystem( &pDbSystem)))
{
goto Exit;
}
// Create a window for displaying query progress.
queryStatus.createQueryStatusWindow( m_pScreen,
FLM_GREEN, FLM_WHITE, pszQuery);
if (RC_BAD( rc = pDbSystem->createIFQuery( &pQuery)))
{
goto Exit;
}
if( RC_BAD( rc = beginTransaction( XFLM_READ_TRANS)))
{
goto Exit;
}
bStartedTrans = TRUE;
if (RC_BAD( rc = selectCollection( &uiCollection, &uiTermChar)))
{
goto Exit;
}
if (uiTermChar != FKB_ENTER)
{
goto Exit;
}
m_uiCollection = uiCollection;
if (RC_BAD( rc = pQuery->setCollection( uiCollection)))
{
goto Exit;
}
if (RC_BAD( rc = xpath.parseQuery( m_pDb, pszQuery, pQuery)))
{
goto Exit;
}
pQuery->setQueryStatusObject( &queryStatus);
for (;;)
{
if (RC_BAD( rc = pQuery->getNext( m_pDb, &pNode, 0, 0)))
{
if (rc == NE_XFLM_EOF_HIT || rc == NE_XFLM_USER_ABORT)
{
if (!queryStatus.keepResults())
{
QueryData.uiNodeCount = 0;
}
rc = NE_XFLM_OK;
break;
}
goto Exit;
}
// Save the node ID - don't collect any more than 30000
if (QueryData.uiNodeCount < 30000)
{
if (QueryData.uiNodeCount == QueryData.uiNodeArraySize)
{
FLMUINT uiNewSize = QueryData.uiNodeArraySize + 500;
if (RC_BAD( rc = f_realloc( sizeof( FLMUINT64) * uiNewSize,
&QueryData.pui64Nodes)))
{
goto Exit;
}
if (RC_BAD( rc = f_realloc( sizeof( FLMUINT) * uiNewSize,
&QueryData.puiAttrNameIds)))
{
goto Exit;
}
QueryData.uiNodeArraySize = uiNewSize;
}
if (pNode->getNodeType() == ATTRIBUTE_NODE)
{
if( RC_BAD( rc = pNode->getParentId( m_pDb,
&QueryData.pui64Nodes [QueryData.uiNodeCount])))
{
goto Exit;
}
if (RC_BAD( rc = pNode->getNameId( m_pDb,
&QueryData.puiAttrNameIds [QueryData.uiNodeCount])))
{
goto Exit;
}
}
else
{
if( RC_BAD( rc = pNode->getNodeId( m_pDb,
&QueryData.pui64Nodes [QueryData.uiNodeCount])))
{
goto Exit;
}
QueryData.puiAttrNameIds [QueryData.uiNodeCount] = 0;
}
QueryData.uiNodeCount++;
}
}
if (RC_BAD( rc = pQuery->getStatsAndOptInfo( &uiOptInfoCnt,
&pOptInfo)))
{
goto Exit;
}
if (uiOptInfoCnt)
{
FLMUINT uiOptToShow = 0;
FLMUINT uiChar;
for (;;)
{
queryStatus.refreshStatus( TRUE, uiOptToShow + 1,
uiOptInfoCnt, &pOptInfo [uiOptToShow]);
queryStatus.testEscape( uiOptInfoCnt, &uiChar);
if (uiChar == 'N' || uiChar == 'n')
{
if (uiOptToShow < uiOptInfoCnt - 1)
{
uiOptToShow++;
}
}
else if (uiChar == 'P' || uiChar == 'P')
{
if (uiOptToShow)
{
uiOptToShow--;
}
}
else if (uiChar == ' ')
{
if (uiOptToShow < uiOptInfoCnt - 1)
{
uiOptToShow++;
}
else
{
break;
}
}
else
{
break;
}
}
pDbSystem->freeMem( (void **)&pOptInfo);
}
if (!QueryData.uiNodeCount)
{
goto Exit;
}
// Initialize the query editor
if ((pQueryEditor = f_new F_DomEditor) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
if (RC_BAD( rc = pQueryEditor->Setup( m_pScreen)))
{
goto Exit;
}
// Configure the editor
QueryData.uiCollection = uiCollection;
pQueryEditor->setParent( this);
pQueryEditor->setShutdown( m_pbShutdown);
pQueryEditor->setSource( m_pDb, uiCollection);
uiQueryStrLen = f_strlen( pszQuery);
if (RC_BAD( rc = f_alloc( uiQueryStrLen + 1, &QueryData.pszQuery)))
{
goto Exit;
}
f_memcpy( QueryData.pszQuery, pszQuery, uiQueryStrLen + 1);
if (uiQueryStrLen > 75)
{
f_strcpy( &QueryData.pszQuery [72], "...");
}
pQueryEditor->setKeyHook( f_QueryEditorKeyHook, &QueryData);
if (RC_BAD( rc = pQueryEditor->interactiveEdit( m_uiULX, m_uiULY, m_uiLRX, m_uiLRY,
TRUE, 2, (FLMUINT)'P')))
{
goto Exit;
}
Exit:
if (RC_BAD( rc))
{
displayMessage( "Error", RC_SET( rc),
NULL, FLM_RED, FLM_WHITE);
}
if (pQuery)
{
pQuery->Release();
}
if (pNode)
{
pNode->Release();
}
if (bStartedTrans)
{
commitTransaction();
}
if (pQueryEditor)
{
pQueryEditor->releaseAllRows();
pQueryEditor->Release();
}
if (QueryData.pui64Nodes)
{
f_free( &QueryData.pui64Nodes);
}
if (QueryData.puiAttrNameIds)
{
f_free( &QueryData.puiAttrNameIds);
}
if (QueryData.pszQuery)
{
f_free( &QueryData.pszQuery);
}
if( pDbSystem)
{
pDbSystem->Release();
}
}
/****************************************************************************
Desc: Adds a comment line subordinate to the current node
*****************************************************************************/
RCODE F_DomEditor::addComment(
DME_ROW_INFO ** ppCurRow,
const char * pszFormat, ...
)
{
RCODE rc = NE_XFLM_OK;
char szBuffer[ 512];
FLMUNICODE * puzValue = NULL;
DME_ROW_INFO * pCommentRow = NULL;
f_va_list args;
flmAssert( m_bSetupCalled == TRUE);
f_va_start( args, pszFormat);
f_vsprintf( szBuffer, pszFormat, &args);
f_va_end( args);
if (RC_BAD( rc = f_calloc( (f_strlen(szBuffer) * 2) + 2, &puzValue)))
{
goto Exit;
}
asciiToUnicode( szBuffer, puzValue);
if (RC_BAD( rc = makeNewRow( &pCommentRow, puzValue, 0, TRUE)))
{
goto Exit;
}
pCommentRow->uiFlags = F_DOMEDIT_FLAG_COMMENT | F_DOMEDIT_FLAG_READ_ONLY |
F_DOMEDIT_FLAG_HIDE_LEVEL | F_DOMEDIT_FLAG_NO_DELETE | F_DOMEDIT_FLAG_HIDE_EXPAND |
F_DOMEDIT_FLAG_NOPARENT | F_DOMEDIT_FLAG_NOCHILD | F_DOMEDIT_FLAG_NODOM;
if (RC_BAD( rc = insertRow( pCommentRow, *ppCurRow)))
{
goto Exit;
}
// Return the new row.
*ppCurRow = pCommentRow;
Exit:
f_free( &puzValue);
return( rc);
}
/*=============================================================================
Desc:
=============================================================================*/
FSTATIC RCODE setupIndexRow(
F_DataVector * pKey,
FLMUINT uiElementNumber,
FLMUINT uiIndex,
FLMUINT uiFlag,
DME_ROW_INFO ** ppTmpRow
)
{
RCODE rc = NE_XFLM_OK;
DME_ROW_INFO * pTmpRow = NULL;
// Create the new row. Make sure we indicate that the display value comes
// from the local buffer.
if (RC_BAD( rc = makeNewRow(
&pTmpRow, NULL, 0, FALSE)))
{
goto Exit;
}
pTmpRow->pVector = pKey;
// uiIndex represents the current element number in the vector when there is
// a vector present.
pTmpRow->uiIndex = uiIndex;
pTmpRow->uiElementNumber = uiElementNumber;
pTmpRow->pDomNode = NULL;
pTmpRow->uiFlags = uiFlag | F_DOMEDIT_FLAG_HIDE_EXPAND | F_DOMEDIT_FLAG_NODOM;
*ppTmpRow = pTmpRow;
Exit:
return rc;
}
/*=============================================================================
Desc: Function to display the Index range selection page
=============================================================================*/
FSTATIC RCODE f_IndexRangeDispHook(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pRow,
FLMUINT * puiNumVals
)
{
RCODE rc = NE_XFLM_OK;
FLMUINT uiFlags = 0;
if( !pRow)
{
goto Exit;
}
pDomEditor->getControlFlags( pRow, &uiFlags);
// Are we just displaying a value, or should we use the Vector?
if (pRow->bUseValue && uiFlags & F_DOMEDIT_FLAG_COMMENT)
{
rc = formatRow( pDomEditor, pRow, puiNumVals, uiFlags);
}
else
{
flmAssert( pRow->pVector);
flmAssert( !pRow->pDomNode);
if (RC_BAD( rc = formatIndexKeyNode( pDomEditor, pRow, puiNumVals)))
{
goto Exit;
}
}
Exit:
// Don't hold on to the Dom node when finished.
if ( pRow->pDomNode)
{
pRow->pDomNode->Release();
pRow->pDomNode = NULL;
}
return( rc);
}
/*=============================================================================
Desc: Function to format the presentation of an index key row
=============================================================================*/
FSTATIC RCODE formatIndexKeyNode(
F_DomEditor * pDomEditor,
DME_ROW_INFO * pRow,
FLMUINT * puiNumVals
)
{
RCODE rc = NE_XFLM_OK;
FLMUINT uiCol = 4;
DME_DISP_COLUMN * pDispVals;
FLMUNICODE * puzBuffer = NULL;
FLMUINT uiBufSize;
F_DataVector * pVector = pRow->pVector;
FLMUINT uiElementNumber = pRow->uiElementNumber;
FLMUINT uiLen;
char * pszData = NULL;
FLMUINT64 ui64NodeId;
flmAssert( pVector);
if ((pDispVals = pDomEditor->getDispColumns()) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
f_memset( pDispVals, 0, sizeof(DME_DISP_COLUMN));
// Prepare the key component number
if (pVector->isDataComponent( uiElementNumber))
{
f_sprintf( pDispVals[ *puiNumVals].szString, "D)");
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = FLM_CYAN;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString) + 2;
(*puiNumVals)++;
}
else
{
f_sprintf( pDispVals[ *puiNumVals].szString, "K)");
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = FLM_CYAN;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString) + 2;
(*puiNumVals)++;
}
// Get the name for this element
if (RC_BAD( rc = pDomEditor->getNodeName( pRow->pDomNode, pRow, &puzBuffer, &uiBufSize)))
{
goto Exit;
}
if (RC_BAD( rc = unicodeToAscii(
puzBuffer, pDispVals[ *puiNumVals].szString, uiBufSize)))
{
goto Exit;
}
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = FLM_WHITE;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString) + 2;
(*puiNumVals)++;
// Get the current value in the buffer or display the one in the buffer.
switch( pVector->getDataType( uiElementNumber))
{
case XFLM_NODATA_TYPE:
{
f_sprintf( pDispVals[ *puiNumVals].szString, "no data");
break;
}
case XFLM_TEXT_TYPE:
{
if ((uiLen = pVector->getDataLength( uiElementNumber)) > 0)
{
if (RC_BAD( rc = f_calloc( uiLen, &pszData)))
{
goto Exit;
}
if (RC_BAD( rc = pVector->getUTF8( uiElementNumber,
(FLMBYTE *)pszData, &uiLen)))
{
goto Exit;
}
f_sprintf( pDispVals[ *puiNumVals].szString, "%*s", uiLen, pszData);
}
else
{
f_sprintf( pDispVals[ *puiNumVals].szString, "<empty str>");
}
break;
}
case XFLM_NUMBER_TYPE:
{
FLMUINT64 ui64Num;
if (RC_BAD( rc = pVector->getUINT64( uiElementNumber, &ui64Num)))
{
if (rc == NE_XFLM_NOT_FOUND)
{
f_sprintf( pDispVals[ *puiNumVals].szString, "<empty num>");
rc = NE_XFLM_OK;
}
else
{
goto Exit;
}
}
else
{
f_sprintf( pDispVals[ *puiNumVals].szString, "0x%I64x", ui64Num);
}
break;
}
case XFLM_BINARY_TYPE:
{
if ((uiLen = pVector->getDataLength( uiElementNumber)) > 0)
{
f_sprintf( pDispVals[ *puiNumVals].szString, "binary data type, len=%u",
(unsigned)uiLen);
}
else
{
f_sprintf( pDispVals[ *puiNumVals].szString, "<empty binary>");
}
break;
}
case XFLM_UNKNOWN_TYPE:
{
f_sprintf( pDispVals[ *puiNumVals].szString, "unknown data type");
break;
}
default:
{
f_sprintf( pDispVals[ *puiNumVals].szString, "invalid data type");
break;
}
}
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = FLM_YELLOW;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString) + 2;
(*puiNumVals)++;
// Display the node Id.
if ((ui64NodeId = pVector->getID( uiElementNumber)) != 0)
{
f_sprintf( pDispVals[ *puiNumVals].szString, "%I64u", ui64NodeId);
}
else
{
f_sprintf( pDispVals[ *puiNumVals].szString, "NULL");
}
pDispVals[ *puiNumVals].uiCol = uiCol;
pDispVals[ *puiNumVals].uiForeground = FLM_LIGHTRED;
pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? FLM_BLACK : FLM_BLUE;
uiCol += f_strlen( pDispVals[ *puiNumVals].szString) + 2;
(*puiNumVals)++;
// Check to make sure that the node value does not push the nodeId off the screen.
if (uiCol > pDomEditor->getCanvasCols())
{
FLMUINT uiValueIdx = *puiNumVals - 2;
FLMUINT uiStrOfs = f_strlen(pDispVals[ uiValueIdx].szString) -
(uiCol - pDomEditor->getCanvasCols());
f_sprintf(( char *)&pDispVals[ uiValueIdx].szString[ uiStrOfs], "... ");
}
Exit:
f_free( &puzBuffer);
f_free( &pszData);
return rc;
}
/*=============================================================================
Desc: Release all of the rows in the editor.
=============================================================================*/
void F_DomEditor::releaseAllRows()
{
if (m_pScrFirstRow)
{
// Make sure we release from the very beginning of the list of rows.
// If we do backup, we must increment the row count for each row
while (m_pScrFirstRow->pPrev != NULL)
{
m_pScrFirstRow = m_pScrFirstRow->pPrev;
}
while (m_pScrFirstRow)
{
releaseRow( &m_pScrFirstRow);
}
m_uiNumRows = 0;
m_pScrLastRow = m_pCurRow = m_pScrFirstRow;
}
}
/*=============================================================================
Desc: Deletes an entry from an index.
=============================================================================*/
RCODE F_DomEditor::viewOnlyDeleteIxKey( void )
{
RCODE rc = NE_XFLM_OK;
F_DataVector * pVector = NULL;
DME_ROW_INFO * pFirstDeleteRow = NULL;
FLMBYTE pucKeyBuf[ XFLM_MAX_KEY_SIZE];
FLMUINT uiKeyLen;
F_Btree * pBtree = NULL;
IXD * pIxd;
LFILE * pLFile = NULL;
F_Dict * pDict;
FLMBOOL bHaveCounts;
FLMBOOL bHaveData;
FLMBOOL bUpdateTranStarted = FALSE;
IXKeyCompare compareObject;
if (m_pCurRow->pVector)
{
// Return NE_XFLM_OK;
goto Exit;
}
if (!m_pCurRow->pNext)
{
// return NE_XFLM_OK;
goto Exit;
}
if (m_pCurRow->pVector)
{
// return NE_XFLM_OK;
goto Exit;
}
if ((m_pCurRow->uiFlags & F_DOMEDIT_FLAG_COMMENT) == 0)
{
// return NE_XFLM_OK;
goto Exit;
}
// Mark the first row to delete.
pFirstDeleteRow = m_pCurRow;
// Get the vector
pVector = m_pCurRow->pNext->pVector;
if (!pVector)
{
flmAssert( 0);
goto Exit;
}
// Start an update transaction.
if (RC_BAD( rc = beginTransaction( XFLM_UPDATE_TRANS)))
{
goto Exit;
}
bUpdateTranStarted = TRUE;
// Get the index, then open a btree to the index.
if (RC_BAD( rc = m_pDb->getDictionary( &pDict)))
{
goto Exit;
}
if (RC_BAD( rc = pVector->outputKey( m_pDb,
m_pCurRow->pNext->uiIndex,
0,
pucKeyBuf,
XFLM_MAX_KEY_SIZE,
&uiKeyLen)))
{
goto Exit;
}
if (RC_BAD( rc = pDict->getIndex( m_pCurRow->pNext->uiIndex,
&pLFile,
&pIxd)))
{
goto Exit;
}
compareObject.setIxInfo( m_pDb, pIxd);
compareObject.setCompareNodeIds( TRUE);
compareObject.setCompareDocId( TRUE);
compareObject.setSearchKey( NULL);
if ((pBtree = f_new F_Btree) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
bHaveCounts = (pIxd->uiFlags & IXD_ABS_POS) ? TRUE : FALSE;
bHaveData = (pIxd->pFirstData) ? TRUE : FALSE;
if (RC_BAD( rc = pBtree->btOpen( m_pDb,
pLFile,
bHaveCounts,
bHaveData, &compareObject)))
{
goto Exit;
}
// Delete the key.
if (RC_BAD( rc = pBtree->btRemoveEntry( pucKeyBuf, uiKeyLen)))
{
goto Exit;
}
// Now remove the rows from the display list. Release the comment row.
releaseRow( &m_pCurRow);
m_uiNumRows--;
while (m_pCurRow &&
(m_pCurRow->uiFlags & F_DOMEDIT_FLAG_COMMENT) == 0)
{
releaseRow( &m_pCurRow);
m_uiNumRows--;
}
Exit:
if (pBtree)
{
pBtree->btClose();
pBtree->Release();
}
if (bUpdateTranStarted)
{
if (RC_OK( rc))
{
if (RC_BAD( rc = commitTransaction()))
{
(void) abortTransaction();
}
}
else
{
(void) abortTransaction();
}
}
return rc;
}