1/////////////////////////////////////////////////////////////////////////////
2// Name:        No names yet.
3// Purpose:     Contrib. demo
4// Author:      Aleksandras Gluchovas
5// Modified by:
6// Created:     22/09/98
7// RCS-ID:      $Id: scriptbinder.h 34519 2005-06-02 09:44:45Z ABX $
8// Copyright:   (c) Aleskandars Gluchovas
9// Licence:     wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifndef __SCRIPTBINDER_G__
13#define __SCRIPTBINDER_G__
14
15#if defined( wxUSE_TEMPLATE_STL )
16
17    #include <vector>
18
19    #ifdef WIN32
20        #include <bstring.h>
21    #else
22        #include <strclass.h>
23        #include <string.h>
24    #endif
25
26#else
27
28    #include "wxstlvec.h"
29    #include "wx/string.h"
30
31#endif
32
33#ifndef ASSERT
34// assert yourself
35#define ASSERT(x) if (!(x) ) throw;
36#endif
37
38#include "markup.h"
39
40// just another portable stream class...
41
42class ScriptStream
43{
44protected:
45    char*  m_pBuf;
46    size_t m_Size;
47    size_t m_Capacity;
48public:
49    ScriptStream();
50    ~ScriptStream();
51
52    void WriteBytes( const void* srcBuf, size_t count );
53
54    ScriptStream& operator<<( const char* str );
55    ScriptStream& operator<<( const wxString& str );
56    ScriptStream& operator<<( char ch );
57
58    void endl();
59
60    inline char*  GetBuf() { return m_pBuf; }
61    inline size_t GetBufSize() { return m_Size; }
62
63    // clears current contents of the stream
64    void Reset() { m_Size = 0; }
65};
66
67
68class ScriptTemplate;
69
70// used internally by ScriptTemplate
71
72enum TEMPLATE_VARIABLE_TYPES
73{
74    TVAR_INTEGER,
75    TVAR_STRING,
76    TVAR_DOUBLE,
77    TVAR_REF_ARRAY
78};
79
80// helper structures used only by ScriptTemplate
81
82struct TVarInfo
83{
84public:
85    const char*     m_Name;
86    int             m_Type;
87    int             m_Ofs;
88
89    TVarInfo( const char* name, int ofs, int varType )
90        : m_Name(name),
91          m_Type( varType ),
92          m_Ofs( ofs )
93    {}
94};
95
96struct TArrayInfo : public TVarInfo
97{
98public:
99    int m_RefOfs;
100    int m_SizeIntOfs;
101    int m_ObjRefTemplOfs;
102
103    TArrayInfo( const char* name )
104        : TVarInfo( name, 0, TVAR_REF_ARRAY )
105    {}
106};
107
108// stores offset of the given member (of the given class)
109// to (*pOfs), though the use of template classes would have
110// solved this problem in much clearer fashion
111
112// FOR NOW:: obtaining physical offset of class member
113//           does not appeare to be protable across compilers?
114// FIXME::   +/- 1 problem
115
116#ifdef __UNIX__
117    #define WEIRD_OFFSET 1
118#else
119    #define WEIRD_OFFSET 0
120
121#endif
122
123#define GET_VAR_OFS( className, varName, pOfs )          \
124    {                                                    \
125        int* className::* varPtr;                        \
126        varPtr = (int* className::*)&className::varName; \
127                                                         \
128        (*pOfs) = int(*(int*)&varPtr)-WEIRD_OFFSET;      \
129    }
130
131class ScriptSection;
132
133#if defined( wxUSE_TEMPLATE_STL )
134
135    typedef vector<TVarInfo*> TVarListT;
136
137    // container class for sections
138    typedef vector<ScriptSection*> SectListT;
139
140#else
141
142    typedef TVarInfo*      TVarInfoPtrT;
143    typedef ScriptSection* ScriptSectionPtrT;
144
145    typedef WXSTL_VECTOR_SHALLOW_COPY(TVarInfoPtrT) TVarListT;
146
147    // container class for sections
148    typedef WXSTL_VECTOR_SHALLOW_COPY(ScriptSectionPtrT) SectListT;
149
150#endif
151
152// class performs preprocessing of arbitrary scripts,
153// replaces identifiers enclosed in $(..) tag, whith
154// values of the corresponding class member variables
155
156class ScriptTemplate
157{
158protected:
159    // do not use wxString object here - parsing of
160    // C string can be much faster (in debug v.)
161    char*     m_TText;
162
163    TVarListT m_Vars;
164
165    inline void PrintVar( TVarInfo*     pInfo,
166                          void*         dataObj,
167                          ScriptStream& stm );
168
169public:
170    ScriptTemplate( const wxString& templateText );
171    virtual ~ScriptTemplate();
172
173    bool HasVar( const char* name );
174
175    // Member variables registration methods.
176
177    // NOTE:: GET_VAR_OFS() macro should be used
178    // to get offset of the class member (see #define above)
179    void AddStringVar ( const char* name, int ofs );
180    void AddIntegerVar( const char* name, int ofs );
181    void AddDoubleVar ( const char* name, int ofs );
182
183    void AddObjectRefArray( const char*     name,
184                            int             ofsRefToFirstObj,
185                            int             ofsObjSizeInt,
186                            int             ofsObjRefTempl
187                          );
188
189    // reads the script, replaces $(..) tags with values
190    // of registered members of dataObj object, and outputs
191    // the result to given text stream
192
193    void PrintScript( void* dataObj, ScriptStream& stm );
194};
195
196class ScriptSection;
197
198// class manages section and aggregated sections of
199// inter-linked documents
200
201class ScriptSection
202{
203protected:
204
205    // NOTE:: "$(NAME)", $(ID), "$(BODY)" and "$(REFLIST)" are
206    //        reseved template variables of ScriptSection
207
208    // the below there members are registered to ScriptTemplate,
209    // GUID within the section tree (numeric)
210
211    ScriptSection*  m_pParent;
212    wxString        m_Id;   // $(ID)
213    wxString        m_Name;// $(NAME)
214    wxString        m_Body; // $(BODY)
215
216    // NULL, if this section is not aggregated anywhere
217
218    SectListT       m_Subsections; // aggregated sectons
219    SectListT       m_References;  // registered as $(REFLIST)
220
221    bool            m_AutoHide;  // see autoHide arg, in constructor
222    bool            m_SortOn;    // true, if sort subsectons by naem
223
224    // tempalte for this section
225    ScriptTemplate* m_pSectTempl;
226
227    // template used for links (or references) to this section
228    ScriptTemplate* m_pRefTempl;
229
230    // do not call destructor of this object,
231    // call RemoveRef() instead
232    int             m_RefCount;
233
234    static int      m_IdCounter;  // generator of GUIDs
235
236    // fields registered and used by ScriptTemplate object
237    void*           m_RefFirst;
238    int             m_ArrSize;
239
240protected:
241    virtual void AddRef();
242    virtual void RemoveRef();
243    void DoRemoveEmptySections(int& nRemoved, SectListT& removedLst);
244    void DoRemoveDeadLinks( SectListT& removedLst);
245
246public:
247
248    // NOTE:: pass NULL to certain template, if your sure
249    //        this kind of template will never be used,
250    //        e.g. if section is contained but never referrenced,
251    //        then pReferenceTemplate can be NULL
252
253    // if autoHide option is true, the section will be automatically
254    // collapsed (not shown) if it doesn't contain any references
255    // to other sections (e.g. could be usefull for autoamically
256    // hiding empty index-sections).
257
258    ScriptSection( const wxString& name = wxEmptyString,
259                   const wxString& body = wxEmptyString,
260                   ScriptTemplate* pSectionTemplate   = NULL,
261                   ScriptTemplate* pReferenceTemplate = NULL,
262                   bool            autoHide           = false,
263                   bool            sorted             = false
264                 );
265
266    // calls RemoveRef() to all aggreagated sections first,
267    // then to all referenced section - this way all
268    // sections (even not aggregated ones) become "garbage-collected"
269
270    // NOTE:: do not call destructor directlly, call RemoveRef()
271    //        instead
272    virtual ~ScriptSection();
273
274
275    // if addToReferencesToo is true, section is aggregated and
276    // also added to reference list of this section
277
278    void AddSection( ScriptSection* pSection, bool addToReferencesToo = false );
279
280    // add cross-reference to this given section
281    void AddReference( ScriptSection* pReferredSection );
282
283    // subsection may be given of variable depth level,
284    // e.g. "publications/reviews/software"
285
286    ScriptSection* GetSubsection( const char* name );
287
288    // returns list aggregated sections
289    SectListT& GetSubsections();
290
291    // binds reserved template names ( $(..) ) to member
292    // vairalbes in the ScriptSection class, should be called
293    // to initialize each user-code provided script template
294
295    static void RegisterTemplate( ScriptTemplate& sectionTempalte );
296
297    // prints out section tree to the stream, starting from
298    // this section as a root node
299    virtual void Print( ScriptStream& stm );
300
301    // searches empty sections which has autoHide == true,
302    // and colapses them (this method should be called )
303    // on the root-section of the sections tree
304
305    // NOTE:: does not work properly, yet!
306    void RemoveEmptySections();
307};
308
309// base class for documnetation generators
310// (allows user code set up target script type,
311//  independently of documentation type)
312
313class DocGeneratorBase
314{
315protected:
316    MarkupTagsT    m_Tags;
317
318    // override this method to do some post processing
319    // after generation of document, or even write some
320    // data into output stream, before the section tree
321    // is flushed into it.
322
323    // return false, if something has gone wrong and
324    // document cannot be saved now
325
326    virtual bool OnSaveDocument( ScriptStream& WXUNUSED(stm) )
327        { return 1; }
328
329    // override this method to provide reference to
330    // the top section of the document (used as default
331    // starting section when saving a document)
332
333    virtual ScriptSection* GetTopSection()
334        { return 0; }
335
336public:
337
338    DocGeneratorBase()
339        : m_Tags(0) // no defaul script
340    {}
341
342    // dectrouctors of polymorphic classes SHOULD be virtual
343    virtual ~DocGeneratorBase() {}
344
345    // returns tags, being used for specific target script
346    MarkupTagsT GetScriptMarkupTags() { return m_Tags; }
347
348    // sets tag array for specific script
349
350    // NOTE:: Why virtual? since approach with MarkupTagsT is
351    //        "flowless" only in theory. Overriding this method
352    //        allows document generators to check the type of the
353    //        target script, and perhaps make some modifications
354    //        to generator's tamplates, to match the specific script
355
356    virtual void SetScriptMarkupTags( MarkupTagsT tags )
357        { m_Tags = tags; }
358
359    // seves document to file starting from the root-node of
360    // the document (provided by GetTopSection() method),
361    // or from "pFromSection" if it's not NULL.
362
363    // fopenOptions arg. is string passed to fopen() method,
364    // returns true, if saving was successful
365
366    virtual bool SaveDocument( const char*    fname,
367                               const char*    fopenOptions = "w",
368                               ScriptSection* pFromSection = NULL
369                             );
370
371};
372
373#endif
374