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 
GetFileNo(const wxString & fname)29 size_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 
GetFileNoOfContext(spContext & ctx)42 size_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 
spInterFileContext()54 spInterFileContext::spInterFileContext()
55 {}
56 
~spInterFileContext()57 spInterFileContext::~spInterFileContext()
58 {}
59 
AddFile(const wxString & fname,const wxString & content)60 void spInterFileContext::AddFile( const wxString& fname, const wxString& content )
61 {
62     m_Files.push_back( fname );
63     m_Contents.push_back( content );
64 }
65 
RemoveContext(spContext & ctx)66 void 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 
InsertBookmarkSorted(BookmarkListT & lst,spBookmark & mark)75 void 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 
DoAppendSourceFragment(wxString & source,wxString & result,size_t pos,size_t len)88 void 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 
GenerateContextBody(spContext & ctx,wxString & source,wxString & result,size_t & lastSavedPos,size_t & lastKnownPos)127 void 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 
GenrateContents()200 void 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 
ParseContents(SourceParserPlugin * pPlugin)237 void 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 
WriteToFiles()257 void 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 
GetBody(spContext * pCtx)272 wxString 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 
GetHeader(spContext * pCtx)281 wxString 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