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