1///////////////////////////////////////////////////////////////////////////// 2// Name: No names yet. 3// Purpose: Contrib. demo 4// Author: Aleksandras Gluchovas 5// Modified by: 6// Created: 27/12/98 7// RCS-ID: $Id: ifcontext.cpp 40162 2006-07-17 13:17:57Z MW $ 8// Copyright: (c) Aleskandars Gluchovas 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12// For compilers that support precompilation, includes "wx/wx.h". 13#include "wx/wxprec.h" 14 15#ifdef __BORLANDC__ 16#pragma hdrstop 17#endif 18 19#ifndef WX_PRECOMP 20#include "wx/wx.h" 21#endif 22 23#include <stdio.h> 24 25#include "ifcontext.h" 26 27/***** Implementation for class spInterFileContext *****/ 28 29size_t spInterFileContext::GetFileNo( const wxString& fname ) 30{ 31 for ( size_t i = 0; i != m_Files.size(); ++i ) 32 { 33 if ( fname == m_Files[i] ) 34 return i; 35 } 36 37 wxFAIL_MSG("File not found in array in function spInterFileContext::GetFileNo()"); 38 39 return 0; 40} 41 42size_t spInterFileContext::GetFileNoOfContext( spContext& ctx ) 43{ 44 spContext* pCtx = ctx.GetEnclosingContext( SP_CTX_FILE ); 45 46 // DBG:: outer-file context should be present 47 wxASSERT( pCtx && pCtx->GetType() == SP_CTX_FILE ); 48 49 return GetFileNo( ((spFile*)pCtx)->m_FileName ); 50} 51 52/*** public interface ***/ 53 54spInterFileContext::spInterFileContext() 55{} 56 57spInterFileContext::~spInterFileContext() 58{} 59 60void spInterFileContext::AddFile( const wxString& fname, const wxString& content ) 61{ 62 m_Files.push_back( fname ); 63 m_Contents.push_back( content ); 64} 65 66void spInterFileContext::RemoveContext( spContext& ctx ) 67{ 68 wxASSERT( ctx.PositionIsKnown() ); // DBG:: should be checked by-user code 69 70 size_t fNo = GetFileNoOfContext( ctx ); 71 72 mDeletionMarks.push_back( spBookmark( ctx.mSrcOffset, ctx.mContextLength, fNo ) ); 73} 74 75void spInterFileContext::InsertBookmarkSorted( BookmarkListT& lst, spBookmark& mark ) 76{ 77 for( size_t i = 0; i != lst.size(); ++i ) 78 79 if ( lst[i].mFrom > mark.mFrom ) 80 { 81 lst.insert( &lst[i], mark ); 82 return; 83 } 84 85 lst.push_back( mark ); 86} 87 88void spInterFileContext::DoAppendSourceFragment( wxString& source, 89 wxString& result, 90 size_t pos, size_t len ) 91{ 92 mFiltered.erase( mFiltered.begin(), mFiltered.end() ); 93 94 size_t i; 95 96 for( i = 0; i != mDeletionMarks.size(); ++i ) 97 { 98 spBookmark& mark = mDeletionMarks[i]; 99 100 if ( mark.mFileNo == mCurFileNo && 101 mark.mFrom >= pos && mark.mFrom < pos + len ) 102 103 InsertBookmarkSorted( mFiltered, mark ); 104 } 105 106 size_t cur = pos; 107 108 for( i = 0; i != mFiltered.size(); ++ i ) 109 { 110 spBookmark& mark = mFiltered[i]; 111 112 result.append( source, cur, ( (size_t)mark.mFrom - cur ) ); 113 114 cur = size_t( mark.mFrom + mark.mLen ); 115 116 if ( cur >= pos + len ) // check if we've overstepped the current source-fragment 117 { 118// wxASSERT(0); // DBG:: with current imp. this should not happen 119 wxFAIL_MSG("Overstepped the current source fragment in function\nspInterFileContext::DoAppendSourceFragment()"); 120 cur = pos + len; break; 121 } 122 } 123 124 result.append( source, cur, ( pos + len ) - cur ); 125} 126 127void spInterFileContext::GenerateContextBody( spContext& ctx, 128 wxString& source, 129 wxString& result, 130 size_t& lastSavedPos, 131 size_t& lastKnownPos ) 132{ 133 if ( ctx.PositionIsKnown() ) 134 lastKnownPos = ctx.mSrcOffset; 135 136 if ( ctx.IsVirtualContext() ) 137 { 138 // add fragment accumulated before this context 139 140 DoAppendSourceFragment( source, result, 141 size_t(lastSavedPos), 142 size_t(lastKnownPos - lastSavedPos) ); 143 144 // add context body 145 146 result += ctx.GetVirtualContextBody(); 147 148 lastSavedPos = lastKnownPos; 149 150 if ( ctx.PositionIsKnown() ) 151 { 152 if ( ctx.VitualContextHasChildren() ) 153 { 154 lastKnownPos = ctx.mSrcOffset + ctx.mHeaderLength; 155 156 lastSavedPos = lastKnownPos; 157 } 158 else 159 { 160 lastKnownPos = ctx.mSrcOffset + ctx.mContextLength; 161 162 lastSavedPos = lastKnownPos; 163 164 return; // have not children 165 } 166 } 167 } 168 169 MMemberListT& lst = ctx.GetMembers(); 170 171 for( size_t i = 0; i != lst.size(); ++i ) 172 { 173 GenerateContextBody( *lst[i], source, result, lastSavedPos, lastKnownPos ); 174 } 175 176 if ( ctx.IsVirtualContext() ) 177 { 178 if ( ctx.VitualContextHasChildren() && !ctx.GetFooterOfVirtualContextBody().empty() ) 179 { 180 // append the reminder space after children of the context 181 182 DoAppendSourceFragment( result, source, 183 size_t(lastSavedPos), 184 size_t(lastKnownPos - lastSavedPos) ); 185 186 // add footer 187 result += ctx.GetFooterOfVirtualContextBody(); 188 189 lastKnownPos = ctx.mSrcOffset + ctx.mContextLength; 190 191 lastSavedPos = lastKnownPos; 192 } 193 } 194 195 if ( ctx.PositionIsKnown() ) 196 197 lastKnownPos = ctx.mSrcOffset + ctx.mContextLength; 198} 199 200void spInterFileContext::GenrateContents() 201{ 202 MMemberListT& lst = GetMembers(); 203 204 for( size_t f = 0; f != lst.size(); ++f ) 205 { 206 wxString& fname = ((spFile*)lst[f])->m_FileName; 207 208 size_t fileNo = GetFileNo( fname ); 209 210 wxString& source = m_Contents[ fileNo ]; 211 212 wxString result; 213 214 size_t lastKnownPos = 0, // the begining of the file is always "known" 215 lastSavedPos = 0; 216 217 mCurFileNo = fileNo; 218 219 GenerateContextBody( *lst[f], source, result, lastSavedPos, lastKnownPos ); 220 221 // the end of file is always known 222 223 lastKnownPos = m_Contents[ fileNo ].length(); 224 225 // append the reminder 226 227 DoAppendSourceFragment( source, result, 228 size_t(lastSavedPos), 229 size_t(lastKnownPos - lastSavedPos) ); 230 231 // replace original contnet with newly generated one 232 233 m_Contents[ fileNo ] = result; 234 } 235} 236 237void spInterFileContext::ParseContents( SourceParserPlugin* pPlugin ) 238{ 239 mDeletionMarks.erase( mDeletionMarks.begin(), mDeletionMarks.end() ); 240 241 RemoveChildren(); // clean up top-level context 242 243 mParser.SetPlugin( pPlugin ); 244 245 for( size_t i = 0; i != m_Files.size(); ++i ) 246 { 247 wxChar* s = (char*)(m_Contents[i].c_str()); 248 249 spFile* pFCtx = mParser.Parse( s, s + m_Contents[i].length() ); 250 251 pFCtx->m_FileName = m_Files[i]; 252 253 AddMember( pFCtx ); 254 } 255} 256 257void spInterFileContext::WriteToFiles() 258{ 259 for( size_t i = 0; i != m_Files.size(); ++i ) 260 { 261 FILE* fp = fopen( m_Files[i].c_str(), "w+t" ); 262 263 if ( fp != NULL ) 264 { 265 fwrite( m_Contents[i].c_str(), sizeof(char), m_Contents[i].length(), fp ); 266 267 fclose( fp ); 268 } 269 } 270} 271 272wxString spInterFileContext::GetBody( spContext* pCtx ) 273{ 274 wxASSERT( pCtx->PositionIsKnown() ); // DBG:: should be checked by-user code 275 276 wxString& source = m_Contents[ GetFileNoOfContext( *pCtx ) ]; 277 278 return wxString( source.c_str() + pCtx->mSrcOffset, pCtx->mContextLength ); 279} 280 281wxString spInterFileContext::GetHeader( spContext* pCtx ) 282{ 283 wxASSERT( pCtx->PositionIsKnown() ); // DBG:: should be checked by-user code 284 285 wxASSERT( pCtx->mHeaderLength != -1 ); // DBG:: -/- 286 287 wxString& source = m_Contents[ GetFileNoOfContext( *pCtx ) ]; 288 289 return wxString( source.c_str() + pCtx->mSrcOffset, pCtx->mHeaderLength ); 290} 291