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