//------------------------------------------------------------------------------ // Desc: DOM editor class // // Tabs: 3 // // Copyright (c) 2003-2006 Novell, Inc. All Rights Reserved. // // This program is free software; you can redistribute it and/or // modify it under the terms of version 2 of the GNU General Public // License as published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, contact Novell, Inc. // // To contact Novell about this file by physical or electronic mail, // you may find current contact information at www.novell.com // // $Id: fdomedt.cpp 3133 2006-01-25 12:00:01 -0700 (Wed, 25 Jan 2006) dsanders $ //------------------------------------------------------------------------------ #include "flaimsys.h" #include "ftx.h" #include "flm_lutl.h" #include "domedit.h" #include "fdynbuf.h" #include "fxpath.h" #ifdef FLM_UNIX #include "ctype.h" #endif 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( char * pszToken, FLMUINT * puiNum); FSTATIC char * domeditSkipChars( char * pszStr, char * pszCharsToSkip); FSTATIC FLMBOOL domeditStrToDate( 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( char * pszAsciiString, FLMUNICODE * puzString); FSTATIC RCODE unicodeToAscii( FLMUNICODE * puzString, char * pszString, FLMUINT uiLength); FSTATIC RCODE formatText( FLMUNICODE * puzBuf, FLMBOOL bQuoted, char * pszPreText, 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, char * pszPreText, 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); /* DOMEdit prototypes */ RCODE _domEditBackgroundThread( F_Thread * pThread); RCODE domEditVerifyRun( void); // Imported global variable(s)... extern FLMBOOL gv_bShutdown; /* Local prototypes */ #define FLM_START_STATS #define FLM_STOP_STATS #define FLM_RESET_STATS /* Function / Method Implementations */ /**************************************************************************** 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( char * pszTitle) { RCODE rc = NE_XFLM_OK; FLMUINT uiBack; FLMUINT 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 = (FLMUINT)((m_bMonochrome) ? (FLMUINT)WPS_BLACK : (FLMUINT)WPS_BLUE); uiFore = (FLMUINT)WPS_WHITE; if( FTXWinSetTitle( m_pEditWindow, m_szTitle, uiBack, uiFore) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } } Exit: 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 XFLMAPI queryStatus( XFLM_OPT_INFO * pOptInfo); RCODE XFLMAPI newSource( XFLM_OPT_INFO * pOptInfo); RCODE XFLMAPI resultSetStatus( FLMUINT64 ui64TotalDocsRead, FLMUINT64 ui64TotalDocsPassed, FLMBOOL bCanRetrieveDocs); RCODE XFLMAPI resultSetComplete( FLMUINT64 ui64TotalDocsRead, FLMUINT64 ui64TotalDocsPassed); void createQueryStatusWindow( FTX_SCREEN * pScreen, FLMUINT uiBack, FLMUINT 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 FLMUINT getRefCount( void) { return( IF_QueryStatus::getRefCount()); } virtual FINLINE FLMUINT32 XFLMAPI AddRef( void) { return( IF_QueryStatus::AddRef()); } virtual FINLINE FLMUINT32 XFLMAPI Release( void) { return( IF_QueryStatus::Release()); } private: void outputLabel( FLMUINT uiRow, char * pszLabel); void outputStr( FLMUINT uiRow, 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, FLMUINT uiBack, FLMUINT uiFore, char * pszQuery) { FLMBOOL bOk = FALSE; FLMUINT uiNumCols; FLMUINT uiNumRows; FLMUINT uiQueryStrLen = f_strlen( pszQuery); if (FTXScreenGetSize( pScreen, &uiNumCols, &uiNumRows) != FTXRC_SUCCESS) { goto Exit; } m_uiNumCols = uiNumCols - 8; m_uiNumRows = uiNumRows - 4; if (FTXWinInit( pScreen, m_uiNumCols, m_uiNumRows, &m_pWindow) != FTXRC_SUCCESS) { goto Exit; } if (FTXWinSetScroll( m_pWindow, FALSE) != FTXRC_SUCCESS) { goto Exit; } FTXWinSetCursorType( m_pWindow, WPS_CURSOR_INVISIBLE); if (FTXWinSetBackFore( m_pWindow, uiBack, uiFore) != FTXRC_SUCCESS) { goto Exit; } if (FTXWinClear( m_pWindow) != FTXRC_SUCCESS) { goto Exit; } if (FTXWinDrawBorder( m_pWindow) != FTXRC_SUCCESS) { goto Exit; } if (FTXWinMove( m_pWindow, (FLMUINT)((uiNumCols - m_uiNumCols) / 2), (FLMUINT)((uiNumRows - m_uiNumRows) / 2)) != FTXRC_SUCCESS) { goto Exit; } if (FTXWinOpen( m_pWindow) != FTXRC_SUCCESS) { goto Exit; } 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( pScreen->pFtxInfo); bOk = TRUE; Exit: if (!bOk && m_pWindow) { FTXWinFree( &m_pWindow); } } /**************************************************************************** Desc: Output a label on the query status screen. *****************************************************************************/ void EditQueryStatus::outputLabel( FLMUINT uiRow, 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, 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( 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 (FTXWinTestKB( m_pWindow) == FTXRC_SUCCESS) { FLMUINT uiChar; FTXWinInputChar( m_pWindow, &uiChar); if (uiChar == WPK_ESCAPE) { FTXWinSetCursorPos( m_pWindow, LABEL_COLUMN, MESSAGE_LINE); FTXWinPrintf( m_pWindow, "Escape pressed, exit? (Y=Show results, ESC=quit): "); if (FTXWinInputChar( m_pWindow, &uiChar) == FTXRC_SHUTDOWN || uiChar == WPK_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 XFLMAPI 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 XFLMAPI 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; char szAction[ 2]; FLMUINT uiTermChar; FLMUINT uiHelpKey = uiStartChar; FLMBOOL bDoneEditing = FALSE; RCODE rc = NE_XFLM_OK; RCODE tmpRc = NE_XFLM_OK; FLMUINT uiFore; FLMUINT uiBack; F_Thread * pIxManagerThrd = NULL; F_Thread * pMemManagerThrd = NULL; char * pszQuery = NULL; FLMUINT uiSzQueryBufSize; F_DbSystem dbSystem; 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( !m_pNameTable) { if( RC_BAD( rc = refreshNameTable())) { goto Exit; } } if( !uiLRX && !uiLRY) { if( FTXScreenGetSize( m_pScreen, &uiNumCols, &uiNumRows) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } 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( FTXWinInit( m_pScreen, uiNumCols, uiNumRows, &m_pEditWindow) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( FTXWinMove( m_pEditWindow, uiStartCol, uiULY) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( FTXWinSetScroll( m_pEditWindow, FALSE) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( FTXWinSetLineWrap( m_pEditWindow, FALSE) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } FTXWinSetCursorType( m_pEditWindow, WPS_CURSOR_INVISIBLE); uiBack = (FLMUINT)((m_bMonochrome) ? (FLMUINT)WPS_BLACK : (FLMUINT)WPS_BLUE); uiFore = (FLMUINT)WPS_WHITE; if( FTXWinSetBackFore( m_pEditWindow, uiBack, uiFore) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( FTXWinClear( m_pEditWindow) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( bBorder) { if( FTXWinDrawBorder( m_pEditWindow) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } } if( FTXWinSetTitle( m_pEditWindow, m_szTitle, uiBack, uiFore) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( uiStatusLines) { if( FTXWinInit( m_pScreen, uiNumCols, uiStatusLines, &m_pEditStatusWin) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( FTXWinMove( m_pEditStatusWin, uiULX, uiULY + uiNumRows) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( FTXWinSetScroll( m_pEditStatusWin, FALSE) != FTXRC_SUCCESS) { goto Exit; } FTXWinSetCursorType( m_pEditStatusWin, WPS_CURSOR_INVISIBLE); if( FTXWinSetBackFore( m_pEditStatusWin, m_bMonochrome ? WPS_BLACK : WPS_GREEN, WPS_WHITE) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( FTXWinClear( m_pEditStatusWin) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( FTXWinOpen( m_pEditStatusWin) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } } if( FTXWinOpen( m_pEditWindow) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } 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( m_pScreen->pFtxInfo); while( !bDoneEditing && !isExiting()) { if( bRefreshEditWindow) { /* Refresh the edit window */ if( m_pParent) { m_bMonochrome = m_pParent->isMonochrome(); } if( FTXWinPaintBackground( m_pEditWindow, m_bMonochrome ? WPS_BLACK : WPS_BLUE) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } 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 */ if( FTXWinSetBackFore( m_pEditStatusWin, m_bMonochrome ? WPS_LIGHTGRAY : WPS_GREEN, m_bMonochrome ? WPS_BLACK : WPS_WHITE) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } 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( m_pScreen->pFtxInfo); bRefreshStatusWindow = FALSE; } if( uiHelpKey || FTXWinTestKB( m_pEditWindow) == FTXRC_SUCCESS) { 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 != WPK_TAB) { m_uiLastKey = uiChar; } } if( uiChar == WPK_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 WPK_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, WPS_RED, WPS_WHITE); } else if( RC_BAD( tmpRc = editRow( m_uiCurRow, m_pCurRow))) { displayMessage( "The field could not be edited", tmpRc, NULL, WPS_RED, WPS_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, WPS_RED, WPS_WHITE); } bRefreshEditWindow = TRUE; break; } // Expand the current row. case WPK_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, WPS_RED, WPS_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 WPK_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 WPK_LEFT: case WPK_MINUS: { if (m_pCurRow->bExpanded) { if (RC_BAD( tmpRc = collapseRow( &m_pCurRow))) { displayMessage( "Error collapsing current row", tmpRc, NULL, WPS_RED, WPS_WHITE); break; } bRefreshEditWindow = TRUE; } break; } // Move field cursor to the next row case WPK_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, WPS_RED, WPS_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 WPK_UP: { if (RC_BAD( tmpRc = getPrevRow( m_pCurRow, &pTmpRow, TRUE))) { displayMessage( "Failed to retrieve a previous row.", tmpRc, NULL, WPS_RED, WPS_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 WPK_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, WPS_RED, WPS_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 WPK_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, WPS_RED, WPS_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 WPK_HOME: { m_pCurRow = m_pScrFirstRow; m_uiCurRow = 0; bRefreshEditWindow = TRUE; checkDocument( &m_pCurDoc, m_pCurRow); break; } /* Jump to the end of the buffer */ case WPK_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 WPK_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, WPS_RED, WPS_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 WPK_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, WPS_RED, WPS_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 WPK_ALT_A: { if (RC_BAD( tmpRc = addSomething( &m_pCurRow))) { displayMessage( "Add/Insert operation failed", RC_SET( tmpRc), NULL, WPS_RED, WPS_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, WPS_RED, WPS_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, WPS_RED, WPS_WHITE); } break; } case 'X': case 'x': { if (RC_BAD( tmpRc = exportNode( m_pCurRow))) { displayMessage( "Node could not be exported", RC_SET( tmpRc), NULL, WPS_RED, WPS_WHITE); } break; } /* Index operations */ case 'I': case 'i': case WPK_ALT_I: { if( m_pDb == NULL) { break; } if( RC_BAD( tmpRc = indexList())) { displayMessage( "Index List Operation Failed", RC_SET(tmpRc), NULL, WPS_RED, WPS_WHITE); break; } bRefreshEditWindow = TRUE; break; } /* List all documents */ case 'L': case 'l': case WPK_ALT_L: { FLMUINT uiCollection = m_uiCollection; FLMUINT64 ui64NodeId; char szResponse[ 32]; FLMUINT uiTermChar; 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, WPS_RED, WPS_WHITE); break; } if( uiTermChar != WPK_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, WPS_RED, WPS_WHITE); break; } if( uiTermChar != WPK_ENTER) { break; } while ( pDocList && pDocList->ui64DocId != ui64NodeId) { pDocList = pDocList->pNext; } if (pDocList) { displayMessage( "Document already selected", NE_XFLM_FAILURE, NULL, WPS_RED, WPS_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, WPS_RED, WPS_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, WPS_RED, WPS_WHITE); break; } bRefreshEditWindow = TRUE; break; } /* Retrieve a node */ case 'R': case 'r': case WPK_ALT_R: { FLMUINT uiCollection; char szResponse[ 32]; FLMUINT uiTermChar; FLMUINT uiSrcLen; FLMUINT uiNodeId; FLMUINT64 ui64Tmp; szResponse [0] = 0; requestInput( "[READ] Node Number", szResponse, sizeof( szResponse), &uiTermChar); if( uiTermChar == WPK_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, WPS_RED, WPS_WHITE); break; } uiNodeId = (FLMUINT)ui64Tmp; } if (!m_pDocList) { if( RC_BAD( tmpRc = selectCollection( &uiCollection, &uiTermChar))) { displayMessage( "Error getting collection", RC_SET(tmpRc), NULL, WPS_RED, WPS_WHITE); break; } if( uiTermChar != WPK_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, WPS_RED, WPS_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 WPK_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 WPK_ALT_C: { char szResponse[ 2]; FLMUINT uiTermChar; szResponse [0] = 0; requestInput( "Clear buffer and discard modifications? (Y/N)", szResponse, 2, &uiTermChar); if( uiTermChar == WPK_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 == WPK_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, WPS_RED, WPS_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, WPS_RED, WPS_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, WPS_RED, WPS_WHITE); break; } } else { displayMessage( "Invalid Request", RC_SET( NE_XFLM_FAILURE), NULL, WPS_RED, WPS_WHITE); break; } bRefreshStatusWindow = TRUE; break; } case '?': { showHelp( &uiHelpKey); break; } case WPK_F10: { if( m_bMonochrome) { m_bMonochrome = FALSE; } else { m_bMonochrome = TRUE; } bRefreshEditWindow = TRUE; break; } case WPK_F8: /* Index Manager */ { char szDbPath [F_PATH_MAX_SIZE]; F_Db * pTmpDb = NULL; if( m_pDb == NULL) { break; } f_threadDestroy( &pIxManagerThrd); (void)m_pDb->getDbControlFileName( szDbPath, sizeof( szDbPath)); if (RC_OK( tmpRc = dbSystem.dbOpen( szDbPath, NULL, NULL, NULL, TRUE, (IF_Db **)&pTmpDb))) { f_threadCreate( &pIxManagerThrd, flstIndexManagerThread, "index_manager", FLM_DEFAULT_THREAD_GROUP, 0, (void *)pTmpDb); } else { displayMessage( "Failed to open database", RC_SET( tmpRc), NULL, WPS_RED, WPS_WHITE); } break; } case WPK_F9: /* Memory Manager */ { f_threadDestroy( &pMemManagerThrd); f_threadCreate( &pMemManagerThrd, flstMemoryManagerThread, "memory_manager"); break; } case WPK_DELETE: { if (RC_BAD( tmpRc = deleteRow( &m_pCurRow))) { displayMessage( "Delete operation failed", RC_SET( tmpRc), NULL, WPS_RED, WPS_WHITE); break; } bRefreshEditWindow = TRUE; break; } case WPK_ESCAPE: case 'Q': case 'q': case 'Z': case 'z': case WPK_ALT_Q: case WPK_ALT_Z: { bDoneEditing = TRUE; break; } default: { /* Unrecognized key ... ignore. */ break; } } } else { f_sleep( 1); } } Exit: f_free( &pszQuery); f_threadDestroy( &pIxManagerThrd); f_threadDestroy( &pMemManagerThrd); 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( m_pScreen->pFtxInfo, 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( m_pScreen->pFtxInfo, 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, ""))) { 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) { FLMUINT uiBackground = m_bMonochrome ? WPS_LIGHTGRAY : WPS_CYAN; FLMUINT uiForeground = m_bMonochrome ? WPS_BLACK : WPS_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( char * pszMessage, RCODE rcOfMessage, FLMUINT * puiTermChar, FLMUINT uiBackground, FLMUINT uiForeground) { RCODE rc = NE_XFLM_OK; flmAssert( m_bSetupCalled == TRUE); if( puiTermChar) { *puiTermChar = 0; } FTXDisplayMessage( m_pScreen, m_bMonochrome ? WPS_LIGHTGRAY : uiBackground, m_bMonochrome ? WPS_BLACK : uiForeground, pszMessage, F_DbSystem::_errorString( rcOfMessage), puiTermChar); return( rc); } /**************************************************************************** Name: openNewDb Desc: *****************************************************************************/ RCODE F_DomEditor::openNewDb( void) { RCODE rc = NE_XFLM_OK; char szResponse [100]; FLMUINT uiChar; F_DbSystem dbSystem; 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 == WPK_ESCAPE) { break; } if (RC_BAD( rc = dbSystem.dbOpen( szResponse, NULL, NULL, NULL, TRUE, (IF_Db **)&m_pDb))) { displayMessage( "Unable to open database", rc, NULL, WPS_RED, WPS_WHITE); m_pDb = NULL; continue; } m_bOpenedDb = TRUE; break; } Exit: return( rc); } /**************************************************************************** Name: requestInput Desc: *****************************************************************************/ RCODE F_DomEditor::requestInput( char * pszMessage, char * pszResponse, FLMUINT uiMaxRespLen, FLMUINT * puiTermChar) { FLMUINT uiNumCols; FLMUINT uiNumRows; FLMUINT uiNumWinRows = 3; FLMUINT uiNumWinCols; FTX_WINDOW * pWindow = NULL; IF_FileHdl * pFileHdl = NULL; RCODE rc = NE_XFLM_OK; flmAssert( m_bSetupCalled == TRUE); if( FTXScreenGetSize( m_pScreen, &uiNumCols, &uiNumRows) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } uiNumWinCols = uiNumCols - 8; if( FTXWinInit( m_pScreen, uiNumWinCols, uiNumWinRows, &pWindow) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( FTXWinSetScroll( pWindow, FALSE) != FTXRC_SUCCESS) { goto Exit; } FTXWinSetCursorType( pWindow, WPS_CURSOR_UNDERLINE); if( FTXWinSetBackFore( pWindow, m_bMonochrome ? WPS_BLACK : WPS_CYAN, WPS_WHITE) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( FTXWinClear( pWindow) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( FTXWinDrawBorder( pWindow) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( FTXWinMove( pWindow, (uiNumCols - uiNumWinCols) / 2, (uiNumRows - uiNumWinRows) / 2) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( FTXWinOpen( pWindow) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } for( ;;) { if( FTXWinClear( pWindow) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } FTXWinPrintf( pWindow, "%s: ", pszMessage); if( FTXLineEdit( pWindow, pszResponse, uiMaxRespLen, uiMaxRespLen, NULL, puiTermChar) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_FAILURE); goto Exit; } if( *puiTermChar == WPK_F1) { FLMUINT uiBytesRead; char * pszSrc; char * pszDest; if( RC_BAD( rc = gv_pFileSystem->Open( pszResponse, XFLM_IO_RDONLY, &pFileHdl))) { displayMessage( "Unable to open file", rc, NULL, WPS_RED, WPS_WHITE); continue; } if( RC_BAD( rc = pFileHdl->Read( 0, uiMaxRespLen, pszResponse, &uiBytesRead))) { if( rc == NE_XFLM_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( 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; 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, WPS_RED, WPS_WHITE); goto Exit; } if ( pRow->eType != ELEMENT_NODE) { displayMessage( "DOM Node is not an ELEMENT_NODE", NE_XFLM_FAILURE, NULL, WPS_RED, WPS_WHITE); goto Exit; } if (!pRow->bHasAttributes) { displayMessage( "DOM Node does not have attributes", NE_XFLM_FAILURE, NULL, WPS_RED, WPS_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 (FTXLineEdit( pWindow, pszOutputFileName, uiOutputFileNameBufSize - 1, uiOutputFileNameBufSize - 1, NULL, &uiChar) != FTXRC_SUCCESS) { *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", WPS_GREEN, WPS_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 ? WPS_LIGHTGRAY : WPS_RED, m_bMonochrome ? WPS_BLACK : WPS_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 WPK_ENTER: domGetOutputFileName( pWindow, szOutputFile, sizeof( szOutputFile)); domDisplayNodeInfo( pWindow, szOutputFile, m_pDb, m_uiCollection, pRow->ui64NodeId, FALSE, TRUE); break; case WPK_ESC: break; default: FTXDisplayMessage( m_pScreen, m_bMonochrome ? WPS_LIGHTGRAY : WPS_RED, m_bMonochrome ? WPS_BLACK : WPS_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; F_DbSystem dbSystem; if (RC_BAD( rc = createStatusWindow( "Export Node Subtree", WPS_GREEN, WPS_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 = FTXLineEdit( pWindow, szFileName, sizeof( szFileName) - 1, sizeof( szFileName) - 1, NULL, &uiChar)) != FTXRC_SUCCESS) { goto Exit; } if (!szFileName [0]) { goto Exit; } if (RC_BAD( rc = dbSystem.openFileOStream( szFileName, TRUE, &pFileOStream))) { displayMessage( "Error creating export file", rc, NULL, WPS_RED, WPS_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 WPK_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 WPK_ESC: goto Exit; default: FTXDisplayMessage( m_pScreen, m_bMonochrome ? WPS_LIGHTGRAY : WPS_RED, m_bMonochrome ? WPS_BLACK : WPS_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, WPS_RED, WPS_WHITE); goto Exit; } if( RC_BAD( rc = m_pDb->exportXML( pNode, pFileOStream, eFormat))) { displayMessage( "Error exporting data", rc, NULL, WPS_RED, WPS_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); } 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) { #ifdef FLM_LINUX 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], WPK_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], WPK_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], WPK_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], WPK_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], WPK_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], WPK_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], WPK_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], WPK_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], WPK_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], WPK_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], WPK_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], WPK_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], WPK_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], WPK_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], WPK_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() != WPK_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( char * pszTitle, FLMUINT uiBack, FLMUINT 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; /* Create a status window */ if( FTXScreenGetSize( m_pScreen, &uiNumCols, &uiNumRows) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( puiCols) { uiNumWinCols = *puiCols; } if( puiRows) { uiNumWinRows = *puiRows; } if( uiNumWinCols <= 2 || uiNumWinRows < 3) { uiNumWinCols = uiNumCols - 2; uiNumWinRows = uiNumRows - 2; } if( FTXWinInit( m_pScreen, uiNumWinCols, uiNumWinRows, &pWindow) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( puiCols) { *puiCols = uiNumWinCols; } if( puiRows) { *puiRows = uiNumWinRows; } if( FTXWinMove( pWindow, (FLMUINT)((uiNumCols - uiNumWinCols) / 2), (FLMUINT)((uiNumRows - uiNumWinRows) / 2)) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( FTXWinSetScroll( pWindow, TRUE) != FTXRC_SUCCESS) { goto Exit; } if( FTXWinSetLineWrap( pWindow, TRUE) != FTXRC_SUCCESS) { goto Exit; } FTXWinSetCursorType( pWindow, WPS_CURSOR_INVISIBLE); if( m_bMonochrome) { uiBack = WPS_LIGHTGRAY; uiFore = WPS_BLACK; if( FTXWinSetBackFore( pWindow, uiBack, uiFore) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } } else { if( FTXWinSetBackFore( pWindow, uiBack, uiFore) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } } if( FTXWinClear( pWindow) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( FTXWinDrawBorder( pWindow) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( pszTitle) { if( FTXWinSetTitle( pWindow, pszTitle, uiBack, uiFore) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } } *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 WPK_HOME: case WPK_END: case WPK_UP: case WPK_DOWN: case WPK_PGUP: case WPK_PGDN: case WPK_ESCAPE: { *puiKeyOut = uiKeyIn; break; } // Special case case WPK_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 WPK_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 WPK_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 WPK_ENTER: { if( !pDomEditor->canEditRow( pCurRow)) { pDomEditor->displayMessage( "The row cannot be edited", RC_SET( NE_XFLM_ILLEGAL_OP), NULL, WPS_RED, WPS_WHITE); } else if( RC_BAD( rc = pDomEditor->editIndexRow( pCurRow))) { pDomEditor->displayMessage( "The field could not be edited", rc, NULL, WPS_RED, WPS_WHITE); } *puiKeyOut = 0; break; } case WPK_ESCAPE: /* Quit key editor */ // case WPK_ALT_Q: /* Done editing keys */ case WPK_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, WPS_RED, WPS_WHITE); } else if( RC_BAD( rc = pDomEditor->editIndexNode( pCurRow))) { pDomEditor->displayMessage( "The field could not be edited", rc, NULL, WPS_RED, WPS_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 WPK_HOME: case WPK_END: case WPK_UP: case WPK_DOWN: case WPK_PGUP: case WPK_PGDN: case WPK_ESCAPE: case WPK_ENTER: case WPK_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; 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( 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( char * pszToken, // Token being checked FLMUINT * puiNum // Returned number - if token is a number ) { FLMBOOL bIsNum = FALSE; 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( char * pszStr, char * pszCharsToSkip ) { char * pszTmp; while (*pszStr) { pszTmp = pszCharsToSkip; while ((*pszTmp) && (*pszTmp != *pszStr)) { pszTmp++; } if (*pszTmp) { pszStr++; } else { break; } } return( pszStr); } /**************************************************************************** Desc: ****************************************************************************/ RCODE _domEditBackgroundThread( F_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( char * pszAsciiString, FLMUNICODE * puzString) { FLMUINT uiLoop = 0; // Convert to a unicode string. for( uiLoop=0; *pszAsciiString; pszAsciiString++) { if (*pszAsciiString == '&') { 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, char * pszPreText, char * pszPostText, char ** ppszString ) { RCODE rc = NE_XFLM_OK; FLMUNICODE * puzTmp = NULL; F_DynamicBuffer * pBuffer = NULL; FLMUNICODE uzNullChar; char * pszString; FLMUINT uiMaxStringLen = MAX_DISPLAY_SEGMENT; FLMUINT uiStringLen = 0; 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 ((pBuffer = f_new F_DynamicBuffer) == NULL) { goto Exit; } // If the first character is a carriage return, skip over it. if (*puzTmp == (FLMUNICODE)'\n') { puzTmp++; } if (pszPreText) { if (RC_BAD( rc = pBuffer->addString( pszPreText))) { goto Exit; } } if (bQuoted) { if (RC_BAD( rc = pBuffer->addChar( '"'))) { 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 (pBuffer->getBufferSize()) { f_sprintf( pszString, "%*.*s", 0, (uiStringLen <= uiMaxStringLen ? uiMaxStringLen - uiStringLen : 0), pBuffer->printBuffer()); pszString += pBuffer->getBufferSize(); uiStringLen += pBuffer->getBufferSize(); if ((uiStringLen + 1) < uiMaxStringLen) { f_sprintf( pszString, " "); pszString ++; uiStringLen ++; } else { break; } } // Output a newline to end this line pBuffer->reset(); // 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 = pBuffer->addChar( (char)*puzTmp))) { goto Exit; } } else { // Allow browser to render these - flush what we have in // our buffer up to this point, then output. if (pBuffer->getBufferSize()) { f_sprintf( pszString, "%*.*s", 0, (uiStringLen <= uiMaxStringLen ? uiMaxStringLen - uiStringLen : 0), pBuffer->printBuffer()); pszString += pBuffer->getBufferSize(); uiStringLen += pBuffer->getBufferSize(); pBuffer->reset(); } if (uiStringLen + 7 < uiMaxStringLen) { f_sprintf( pszString, "&#%04u;", (unsigned)(*puzTmp)); pszString += 7; uiStringLen += 7; } else { break; } } puzTmp++; } if (pBuffer->getBufferSize()) { f_sprintf( pszString, "%*.*s", 0, (uiStringLen <= uiMaxStringLen ? uiMaxStringLen - uiStringLen : 0), pBuffer->printBuffer()); pszString += pBuffer->getBufferSize(); uiStringLen += pBuffer->getBufferSize(); pBuffer->reset(); } if (bQuoted) { if (RC_BAD( rc = pBuffer->addChar( '"'))) { goto Exit; } } if (pszPostText) { if (RC_BAD( rc = pBuffer->addString( pszPostText))) { goto Exit; } } if (pBuffer->getBufferSize()) { f_sprintf( pszString, "%*.*s", 0, (uiStringLen <= uiMaxStringLen ? uiMaxStringLen - uiStringLen : 0), pBuffer->printBuffer()); pszString += pBuffer->getBufferSize(); pBuffer->reset(); } *ppszString = pszString; Exit: if (pBuffer) { pBuffer->Release(); } 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; FLMUINT uiForeground; if (pRow->pDomNode) { uiForeground = pRow->pDomNode->isQuarantined() ? WPS_LIGHTCYAN : WPS_YELLOW; } else { uiForeground = WPS_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 = WPS_WHITE; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_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 = WPS_WHITE; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_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 ? "" : !pRow->bHasChildren ? "" : ""); } else { f_sprintf( pDispVals[ *puiNumVals].szString, ""); } pDispVals[ *puiNumVals].uiCol = uiCol; pDispVals[ *puiNumVals].uiForeground = pDomEditor->isMonochrome() ? WPS_WHITE : uiForeground; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_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() ? WPS_WHITE : uiForeground; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_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; FLMUINT uiForeground; FLMBOOL bHasLocalData; if (RC_BAD( rc = pRow->pDomNode->isDataLocalToNode( pDomEditor->getDb(), &bHasLocalData))) { goto Exit; } if (pRow->pDomNode) { uiForeground = pRow->pDomNode->isQuarantined() ? WPS_LIGHTCYAN : WPS_WHITE; } else { uiForeground = WPS_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 = WPS_WHITE; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_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 = WPS_WHITE; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_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, "isMonochrome() ? WPS_BLACK : WPS_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 = WPS_LIGHTRED; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_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() ? WPS_BLACK : WPS_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 = WPS_WHITE; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_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 = WPS_WHITE; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_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, "isMonochrome() ? WPS_BLACK : WPS_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 = WPS_LIGHTRED; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_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 = WPS_WHITE; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_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, char * pszPreText, char * pszPostText ) { RCODE rc = NE_XFLM_OK; FLMUNICODE * puzValue = NULL; FLMBOOL bStringEmpty; char * pszString; FLMUINT uiCol; DME_DISP_COLUMN * pDispVals; FLMUINT uiForeground; if (pRow->pDomNode) { uiForeground = pRow->pDomNode->isQuarantined() ? WPS_LIGHTCYAN : WPS_WHITE; } else { uiForeground = WPS_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 = WPS_WHITE; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_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 = WPS_WHITE; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_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() ? WPS_BLACK : WPS_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 = WPS_WHITE; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_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 = WPS_WHITE; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_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, "isMonochrome() ? WPS_BLACK : WPS_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 = WPS_WHITE; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_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 = WPS_WHITE; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_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 = WPS_WHITE; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_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 = WPS_WHITE; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_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; F_FileHdl * pFileHdl = NULL; flmAssert( m_bSetupCalled == TRUE); if( FTXScreenGetSize( m_pScreen, &uiNumCols, &uiNumRows) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } uiNumWinCols = uiNumCols - 8; if( FTXWinInit( m_pScreen, uiNumWinCols, uiNumWinRows, &pWindow) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( FTXWinSetScroll( pWindow, FALSE) != FTXRC_SUCCESS) { goto Exit; } FTXWinSetCursorType( pWindow, WPS_CURSOR_UNDERLINE); if( FTXWinSetBackFore( pWindow, m_bMonochrome ? WPS_BLACK : WPS_CYAN, WPS_WHITE) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( FTXWinClear( pWindow) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( FTXWinDrawBorder( pWindow) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( FTXWinMove( pWindow, (uiNumCols - uiNumWinCols) / 2, (uiNumRows - uiNumWinRows) / 2) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( FTXWinOpen( pWindow) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( FTXWinClear( pWindow) != FTXRC_SUCCESS) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } // 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( FTXLineEdit( pWindow, pszBuffer, uiBufSize, uiBufSize, NULL, puiTermChar) != FTXRC_SUCCESS) { 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->pFtxInfo, 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 == WPK_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, WPS_RED, WPS_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->pFtxInfo, 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 == WPK_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 == WPK_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 == WPK_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, WPS_RED, WPS_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, WPS_RED, WPS_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 == WPK_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 != WPK_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 == WPK_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, WPS_RED, WPS_WHITE); } if( uiTermChar != WPK_ENTER) { goto Exit; } f_memset( szResponse, 0, sizeof(szResponse)); requestInput( "Element Title / Comment", szResponse, sizeof( szResponse), &uiTermChar); if( uiTermChar == WPK_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 == WPK_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 == WPK_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, WPS_RED, WPS_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, WPS_RED, WPS_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 == WPK_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 == WPK_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, WPS_RED, WPS_WHITE); goto Exit; } f_memset( szTextBuffer, 0, uiTextBufLen); requestInput( "Text", szTextBuffer, uiTextBufLen, &uiTermChar); if (uiTermChar == WPK_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 == WPK_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, WPS_RED, WPS_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 == WPK_ESCAPE) { goto Exit; } f_memset( szAttrValue, 0, sizeof( szAttrValue)); requestInput( "Attribute Value", szAttrValue, sizeof(szAttrValue), &uiTermChar); if (uiTermChar == WPK_ESCAPE) { goto Exit; } // Select the encryption algorithm (if any) if (RC_BAD( rc = selectEncDef( ELM_ENCDEF_TAG, &uiEncDefId, &uiTermChar))) { goto Exit; } if (uiTermChar == WPK_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, WPS_RED, WPS_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() == WPK_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 != WPK_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() == WPK_ESCAPE) { goto Exit; } if( RC_BAD( rc = createStatusWindow( " Key Retrieval Status (Press ESC to Interrupt) ", WPS_GREEN, WPS_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( MAX_KEY_SIZ * 2, &pucUntilKeyBuf))) { goto Exit; } pucFoundKeyBuf = &pucUntilKeyBuf [MAX_KEY_SIZ]; // Get the collated until key. if (RC_BAD( rc = pUntilKeyV->outputKey( m_pDb, uiIndex, 0, pucUntilKeyBuf, MAX_KEY_SIZ, &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( FTXWinTestKB( pStatusWindow) == FTXRC_SUCCESS) { FLMUINT uiChar; FTXWinInputChar( pStatusWindow, &uiChar); if( uiChar == WPK_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, MAX_KEY_SIZ, &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, WPS_RED, WPS_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, WPS_RED, WPS_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 WPK_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; F_DbSystem dbSystem; f_memset( &QueryData, 0, sizeof( QueryData)); requestInput( "XPATH Query", pszQuery, uiQueryBufSize, &uiTermChar); if (uiTermChar == WPK_ESCAPE) { goto Exit; } // Create a window for displaying query progress. queryStatus.createQueryStatusWindow( m_pScreen, WPS_GREEN, WPS_WHITE, pszQuery); if (RC_BAD( rc = dbSystem.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 != WPK_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; } } dbSystem.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, WPS_RED, WPS_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); } } /**************************************************************************** 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 = WPS_CYAN; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_BLUE; uiCol += f_strlen( pDispVals[ *puiNumVals].szString) + 2; (*puiNumVals)++; } else { f_sprintf( pDispVals[ *puiNumVals].szString, "K)"); pDispVals[ *puiNumVals].uiCol = uiCol; pDispVals[ *puiNumVals].uiForeground = WPS_CYAN; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_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 = WPS_WHITE; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_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, ""); } 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, ""); 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, ""); } 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 = WPS_YELLOW; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_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 = WPS_LIGHTRED; pDispVals[ *puiNumVals].uiBackground = pDomEditor->isMonochrome() ? WPS_BLACK : WPS_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[ MAX_KEY_SIZ]; 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, MAX_KEY_SIZ, &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, MAX_KEY_SIZ, 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; }