~ubuntu-branches/ubuntu/hardy/codeblocks/hardy-backports

« back to all changes in this revision

Viewing changes to src/plugins/contrib/wxSmith/wxsversionconverter.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michael Casadevall
  • Date: 2008-07-17 04:39:23 UTC
  • Revision ID: james.westby@ubuntu.com-20080717043923-gmsy5cwkdjswghkm
Tags: upstream-8.02
ImportĀ upstreamĀ versionĀ 8.02

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
* This file is part of wxSmith plugin for Code::Blocks Studio
 
3
* Copyright (C) 2006-2007  Bartlomiej Swiecki
 
4
*
 
5
* wxSmith is free software; you can redistribute it and/or modify
 
6
* it under the terms of the GNU General Public License as published by
 
7
* the Free Software Foundation; either version 3 of the License, or
 
8
* (at your option) any later version.
 
9
*
 
10
* wxSmith is distributed in the hope that it will be useful,
 
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
13
* GNU General Public License for more details.
 
14
*
 
15
* You should have received a copy of the GNU General Public License
 
16
* along with wxSmith. If not, see <http://www.gnu.org/licenses/>.
 
17
*
 
18
* $Revision: 4850 $
 
19
* $Id: wxsversionconverter.cpp 4850 2008-01-29 21:45:49Z byo $
 
20
* $HeadURL: svn://svn.berlios.de/codeblocks/tags/8.02/src/plugins/contrib/wxSmith/wxsversionconverter.cpp $
 
21
*/
 
22
 
 
23
#include "wxsversionconverter.h"
 
24
#include "wxsproject.h"
 
25
#include "wxscoder.h"
 
26
 
 
27
#include <globals.h>
 
28
#include <wx/string.h>
 
29
#include <tinyxml/tinywxuni.h>
 
30
 
 
31
// TODO: This is same as in wxsproject.h, make one set instead of two
 
32
namespace
 
33
{
 
34
    const int CurrentVersion = 1;
 
35
    const char* CurrentVersionStr = "1";
 
36
}
 
37
 
 
38
const wxsVersionConverter& wxsVersionConverter::Get()
 
39
{
 
40
    static wxsVersionConverter Singleton;
 
41
    return Singleton;
 
42
}
 
43
 
 
44
bool wxsVersionConverter::DetectOldConfig(TiXmlElement* Node,wxsProject* Project) const
 
45
{
 
46
    // New wxSmith style has resources put into <resources> node
 
47
    // and configuration to <gui> node
 
48
    if ( Node->FirstChildElement("dialog")        ) return true;
 
49
    if ( Node->FirstChildElement("frame")         ) return true;
 
50
    if ( Node->FirstChildElement("panel")         ) return true;
 
51
    if ( Node->FirstChildElement("configuration") ) return true;
 
52
 
 
53
    return false;
 
54
}
 
55
 
 
56
TiXmlElement* wxsVersionConverter::ConvertFromOldConfig(TiXmlElement* ConfigNode,TiXmlDocument* Doc,wxsProject* Project) const
 
57
{
 
58
    if ( cbMessageBox(_("This project uses old wxSmith configuration format\n"
 
59
                        "Would you like me to convert to new one?\n"),
 
60
                      _("wxSmith: Converting from old format"),
 
61
                      wxYES_NO) != wxID_YES ) return 0;
 
62
 
 
63
    TiXmlElement* NewConfig = Doc->InsertEndChild(TiXmlElement("wxSmith"))->ToElement();
 
64
    TiXmlElement* Resources = NewConfig->InsertEndChild(TiXmlElement("resources"))->ToElement();
 
65
    NewConfig->SetAttribute("version",CurrentVersionStr);
 
66
    for ( TiXmlElement* Node = ConfigNode->FirstChildElement(); Node; Node = Node->NextSiblingElement() )
 
67
    {
 
68
        wxString NodeName = cbC2U(Node->Value());
 
69
        if ( NodeName == _T("configuration") )
 
70
        {
 
71
            const char* AppSrc  = Node->Attribute("app_src_file");
 
72
            const char* Main    = Node->Attribute("main_resource");
 
73
            const char* InitAll = Node->Attribute("init_all_handlers");
 
74
 
 
75
            if ( AppSrc )
 
76
            {
 
77
                TiXmlElement* GUINode = NewConfig->InsertEndChild(TiXmlElement("gui"))->ToElement();
 
78
                GUINode->SetAttribute("name","wxWidgets");
 
79
                GUINode->SetAttribute("src",AppSrc);
 
80
                GUINode->SetAttribute("main",Main?Main:"");
 
81
                GUINode->SetAttribute("init_handlers",InitAll?InitAll:"necessary");
 
82
                GUINode->SetAttribute("language","CPP");
 
83
            }
 
84
        }
 
85
        else
 
86
        {
 
87
            if ( NodeName == _T("dialog") ||
 
88
                 NodeName == _T("frame") ||
 
89
                 NodeName == _T("panel") )
 
90
            {
 
91
                const char* Wxs   = Node->Attribute("wxs_file");
 
92
                const char* Class = Node->Attribute("class");
 
93
                const char* Src   = Node->Attribute("src_file");
 
94
                const char* Hdr   = Node->Attribute("header_file");
 
95
                const char* Xrc   = Node->Attribute("xrc_file");
 
96
                const char* Mode  = Node->Attribute("edit_mode");
 
97
 
 
98
                if ( Wxs && Class && Src && Hdr && Mode )
 
99
                {
 
100
                    if ( cbC2U(Mode) == _T("Source") ) Xrc = 0;
 
101
                    TiXmlElement* Res = Resources->InsertEndChild(TiXmlElement(
 
102
                        NodeName == _T("dialog") ? "wxDialog" :
 
103
                        NodeName == _T("frame")  ? "wxFrame" :
 
104
                                                   "wxPanel" ))->ToElement();
 
105
 
 
106
                    Res->SetAttribute("wxs",cbU2C(_T("wxsmith/")+cbC2U(Wxs)));
 
107
                    Res->SetAttribute("src",Src);
 
108
                    Res->SetAttribute("hdr",Hdr);
 
109
                    if ( Xrc ) Res->SetAttribute("xrc",Xrc);
 
110
                    Res->SetAttribute("name",Class);
 
111
                    Res->SetAttribute("language","CPP");
 
112
 
 
113
                    ConvertOldWxsFile(Project->GetProjectPath()+_T("wxsmith/")+cbC2U(Wxs),Xrc!=0);
 
114
                    AdoptOldSourceFile(Project->GetProjectPath()+cbC2U(Src),cbC2U(Class));
 
115
                }
 
116
            }
 
117
        }
 
118
    }
 
119
    return NewConfig;
 
120
}
 
121
 
 
122
void wxsVersionConverter::ConvertOldWxsFile(const wxString& FileName,bool UsingXrc) const
 
123
{
 
124
    TiXmlDocument Doc;
 
125
    if ( !TinyXML::LoadDocument(FileName,&Doc) ) return;
 
126
 
 
127
    TiXmlElement* Smith = Doc.FirstChildElement("resource");
 
128
    if ( Smith )
 
129
    {
 
130
        Smith->SetValue("wxsmith");
 
131
    }
 
132
 
 
133
    if ( UsingXrc && Smith )
 
134
    {
 
135
        // Need to extract extra data from any resource's item and put into <resource_extra> node
 
136
        TiXmlElement* Resource = Smith->FirstChildElement("object");
 
137
        TiXmlElement* Extra = Smith->InsertEndChild(TiXmlElement("resource_extra"))->ToElement();
 
138
        GatherExtraFromOldResourceReq(Resource,Extra,true);
 
139
    }
 
140
 
 
141
    TinyXML::SaveDocument(FileName,&Doc);
 
142
}
 
143
 
 
144
void wxsVersionConverter::GatherExtraFromOldResourceReq(TiXmlElement* Object,TiXmlElement* Extra,bool Root) const
 
145
{
 
146
    // The only extra information in old wxSmith was:
 
147
    //  * variable / member attributes of <object> node
 
148
    //  * event handlers enteries
 
149
    // These fields are extracted and put into wxs file
 
150
    if ( !strcmp(Object->Value(),"object") )
 
151
    {
 
152
        if ( Object->Attribute("class") && (Root || Object->Attribute("name")) )
 
153
        {
 
154
            TiXmlElement* ThisExtra = 0;
 
155
 
 
156
            // Checking if we got variable name
 
157
            if ( Object->Attribute("variable") && Object->Attribute("member") )
 
158
            {
 
159
                ThisExtra = Extra->InsertEndChild(TiXmlElement("object"))->ToElement();
 
160
                ThisExtra->SetAttribute("variable",Object->Attribute("variable"));
 
161
                ThisExtra->SetAttribute("member",Object->Attribute("member"));
 
162
            }
 
163
 
 
164
            // Checking for event handlers
 
165
 
 
166
            for ( TiXmlElement* Handler = Object->FirstChildElement("handler"); Handler; Handler = Handler->NextSiblingElement("handler") )
 
167
            {
 
168
                if ( !ThisExtra )
 
169
                {
 
170
                    ThisExtra = Extra->InsertEndChild(TiXmlElement("object"))->ToElement();
 
171
                }
 
172
                ThisExtra->InsertEndChild(*Handler);
 
173
            }
 
174
 
 
175
            if ( ThisExtra )
 
176
            {
 
177
                if ( Root )
 
178
                {
 
179
                    ThisExtra->SetAttribute("root","1");
 
180
                }
 
181
                else
 
182
                {
 
183
                    ThisExtra->SetAttribute("name",Object->Attribute("name"));
 
184
                    ThisExtra->SetAttribute("class",Object->Attribute("class"));
 
185
                }
 
186
            }
 
187
        }
 
188
    }
 
189
 
 
190
    for ( TiXmlElement* Child = Object->FirstChildElement(); Child; Child = Child->NextSiblingElement() )
 
191
    {
 
192
        GatherExtraFromOldResourceReq(Child,Extra,false);
 
193
    }
 
194
}
 
195
 
 
196
void wxsVersionConverter::AdoptOldSourceFile(const wxString& FileName,const wxString& Class) const
 
197
{
 
198
    // Need to add two new sections: //(*InternalHeaders and //(*IdInit
 
199
    // to do this //(*InternalHeaders will be added before any source code
 
200
    // but after all  #xxx directives
 
201
    // //(*IdInit will be added just before //(*EventTable nearrest line
 
202
    // before that section containing BEGIN_EVENT_TABLE
 
203
    //
 
204
    // This may not be tricky enough but I hope that not much people mess
 
205
    // with code generated by wxSmith from templates ;)
 
206
    //
 
207
    // BTW we do not use wxsCodeMarks::Beg and wxsCodeMarks::End because that could
 
208
    // cause some problems with future conversion of these marks
 
209
    // (upgrade of old-wxSmith project will be done in two steps then,
 
210
    // first - convertion to version 1 of new wxsmith and then upgrading to
 
211
    // higher version so if convention of code marks will change, it will
 
212
    // break the conversion chain)
 
213
 
 
214
    bool IsInternalHeaders = wxsCoder::Get()->GetCode(
 
215
        FileName,
 
216
        _T("//(*InternalHeaders(") + Class + _T(")\n"),
 
217
        _T("//*)"),
 
218
        true,true).Length() != 0;
 
219
 
 
220
    bool IsIdInit = wxsCoder::Get()->GetCode(
 
221
        FileName,
 
222
        _T("//(*IdInit(") + Class + _T(")\n"),
 
223
        _T("//*)"),
 
224
        true,true).Length() != 0;
 
225
 
 
226
    if ( !IsInternalHeaders || !IsIdInit )
 
227
    {
 
228
        wxFontEncoding Encoding;
 
229
        bool UseBOM;
 
230
        wxString Content = wxsCoder::Get()->GetFullCode(FileName,Encoding,UseBOM);
 
231
 
 
232
        int Pos = 0;
 
233
        if ( !IsInternalHeaders )
 
234
        {
 
235
            while ( Pos<(int)Content.Len() && LineContainDirectivesOnly(Content,Pos) );
 
236
 
 
237
            wxString AddInternalHeaders =
 
238
                _T("//(*InternalHeaders(") + Class + _T(")\n")
 
239
                _T("//*)\n")
 
240
                _T("\n");
 
241
 
 
242
            Content = Content.Mid(0,Pos) + AddInternalHeaders + Content.Mid(Pos);
 
243
        }
 
244
        else
 
245
        {
 
246
            Pos = Content.Find(_T("//(*InternalHeaders(") + Class + _T(")\n"));
 
247
            int Shift = Content.Mid(Pos).Find(_T("//*)"));
 
248
            if ( Shift != wxNOT_FOUND )
 
249
            {
 
250
                Pos += Shift;
 
251
            }
 
252
        }
 
253
 
 
254
        if ( !IsIdInit )
 
255
        {
 
256
            int NewPos = Content.Find(_T("BEGIN_EVENT_TABLE(")+Class);
 
257
            if ( NewPos!=wxNOT_FOUND )
 
258
            {
 
259
                Pos = NewPos;
 
260
            }
 
261
 
 
262
            // Switching to first character in this line
 
263
            wxString Indent;
 
264
            while ( Pos>0 &&
 
265
                    Content.GetChar(Pos-1)!=_T('\n') &&
 
266
                    Content.GetChar(Pos-1)!=_T('\r') )
 
267
            {
 
268
                wxChar Ch = Content.GetChar(Pos--);
 
269
                Indent.Append((Ch==_T('\t'))?_T('\t'):_T(' '));
 
270
            }
 
271
 
 
272
            wxString AddIdInit =
 
273
                Indent + _T("//(*IdInit(") + Class + _T(")\n") +
 
274
                Indent + _T("//*)\n") +
 
275
                Indent + _T("\n");
 
276
 
 
277
            Content = Content.Mid(0,Pos) + AddIdInit + Content.Mid(Pos);
 
278
        }
 
279
        wxsCoder::Get()->PutFullCode(FileName,Content,Encoding,UseBOM);
 
280
    }
 
281
}
 
282
 
 
283
bool wxsVersionConverter::LineContainDirectivesOnly(const wxString& Code,int& BeginPos) const
 
284
{
 
285
    int Pos = BeginPos;
 
286
 
 
287
    wxChar PreviousChar = _T('\0');
 
288
 
 
289
    // Processing characters in this line
 
290
    while ( Pos < (int)Code.Len() )
 
291
    {
 
292
        wxChar Ch = Code.GetChar(Pos);
 
293
        if ( Ch==_T('/') && PreviousChar==_T('/') )
 
294
        {
 
295
            // We got // comment, skipping till the end of line
 
296
            while ( ++Pos < (int)Code.Len() )
 
297
            {
 
298
                PreviousChar = Ch;
 
299
                wxChar Ch = Code.GetChar(Pos);
 
300
                if ( Ch==_T('\n') || Ch==_T('\r') )
 
301
                {
 
302
                    if ( PreviousChar == _T('\\') )
 
303
                    {
 
304
                        // Backslash removes EOL
 
305
                        if ( ++Pos < (int)Code.Len() )
 
306
                        {
 
307
                            PreviousChar = Ch;
 
308
                            Ch = Code.GetChar(Pos);
 
309
                            if ( (Ch!=_T('\n') && Ch==_T('\r')) || (Ch==PreviousChar) )
 
310
                            {
 
311
                                // One-char EOL
 
312
                                --Pos;
 
313
                            }
 
314
                        }
 
315
                    }
 
316
                    else
 
317
                    {
 
318
                        // End-Of-Line and End-Of-Comment
 
319
                        while ( Pos<(int)Code.Len() )
 
320
                        {
 
321
                            wxChar Ch = Code.GetChar(Pos);
 
322
                            if ( Ch!=_T('\n') && Ch!=_T('\r') ) break;
 
323
                            Pos++;
 
324
                        }
 
325
 
 
326
                        BeginPos = Pos;
 
327
                        return true;
 
328
                    }
 
329
                }
 
330
            }
 
331
            // End of file approached
 
332
            BeginPos = Pos;
 
333
            return false;
 
334
        }
 
335
        else if ( Ch==_T('*') && PreviousChar==_T('/') )
 
336
        {
 
337
            // Starting multiline comment, we skip everything till */ sequence
 
338
            while ( ++Pos < (int)Code.Len() )
 
339
            {
 
340
                PreviousChar = Ch;
 
341
                wxChar Ch = Code.GetChar(Pos);
 
342
 
 
343
                if ( Ch==_T('/') && PreviousChar==_T('*') )
 
344
                {
 
345
                    // End of comment, breaking
 
346
                    break;
 
347
                }
 
348
            }
 
349
 
 
350
            if ( Pos >= (int)Code.Len() )
 
351
            {
 
352
                // Jumping out to skip another Pos++
 
353
                break;
 
354
            }
 
355
        }
 
356
        else if ( PreviousChar==_T('/') )
 
357
        {
 
358
            // Previous char was not comment beginning
 
359
            // need to rewind to it and jump out
 
360
            Pos--;
 
361
            break;
 
362
        }
 
363
        else if ( Ch!=_T(' ') && Ch!=_T('\t') )
 
364
        {
 
365
            if ( Ch!=_T('/') )
 
366
            {
 
367
                // No white char, jumping out to find out what's this
 
368
                break;
 
369
            }
 
370
            // If it's '/', it may be a start
 
371
            // of comment, we give it a try
 
372
        }
 
373
        PreviousChar = Ch;
 
374
        Pos++;
 
375
    }
 
376
 
 
377
    if ( Pos<(int)Code.Len() )
 
378
    {
 
379
        wxChar Ch = Code.GetChar(Pos);
 
380
        if ( (Ch!=_T('\n')) && (Ch!=_T('\r')) )
 
381
        {
 
382
            // This is no directive, jumping out of function
 
383
            if ( Ch != _T('#') ) return false;
 
384
        }
 
385
    }
 
386
 
 
387
    // Searching for EOL
 
388
    bool BlockMultilineComment = false;
 
389
    while ( Pos<(int)Code.Len() )
 
390
    {
 
391
        wxChar Ch = Code.GetChar(Pos);
 
392
 
 
393
        if ( Ch==_T('\n') || Ch==_T('\r') )
 
394
        {
 
395
            if ( PreviousChar == _T('\\') )
 
396
            {
 
397
                // Backslash removes EOL
 
398
                if ( ++Pos >= (int)Code.Len() )
 
399
                {
 
400
                    // EOF reached
 
401
                    BeginPos = Pos;
 
402
                    return false;
 
403
                }
 
404
                PreviousChar = Ch;
 
405
                Ch = Code.GetChar(Pos);
 
406
                if ( (Ch!=_T('\n') && Ch!=_T('\r')) || (Ch==PreviousChar) )
 
407
                {
 
408
                    // One-character EOL
 
409
                    Pos--;
 
410
                }
 
411
            }
 
412
            else
 
413
            {
 
414
                break;
 
415
            }
 
416
        }
 
417
        else if ( Ch==_T('/') && PreviousChar==_T('/') )
 
418
        {
 
419
            // Have to block any multiline comment in this line
 
420
            BlockMultilineComment = true;
 
421
        }
 
422
        else if ( Ch==_T('*') && PreviousChar==_T('/') && !BlockMultilineComment )
 
423
        {
 
424
            // Searching for end of comment and return there
 
425
            bool WasAnyNL = false;
 
426
            while ( ++Pos<(int)Code.Len() )
 
427
            {
 
428
                PreviousChar = Ch;
 
429
                Ch = Code.GetChar(Pos);
 
430
                if ( Ch==_T('/') && PreviousChar==_T('*') )
 
431
                {
 
432
                    // Comment has been finished
 
433
                    if ( WasAnyNL )
 
434
                    {
 
435
                        // If there was any NL in comment, this mean that
 
436
                        // we can start scanning new line here so we return
 
437
                        // with true
 
438
                        BeginPos = ++Pos;
 
439
                        return true;
 
440
                    }
 
441
                    else
 
442
                    {
 
443
                        // There was no NL in comment, we're still inside directive
 
444
                        break;
 
445
                    }
 
446
                }
 
447
                else if ( Ch==_T('\n') || Ch==_T('\r') )
 
448
                {
 
449
                    WasAnyNL = true;
 
450
                }
 
451
            }
 
452
        }
 
453
        PreviousChar = Ch;
 
454
        Pos++;
 
455
    }
 
456
 
 
457
    // Skipping all NL chars left
 
458
    while ( Pos<(int)Code.Len() )
 
459
    {
 
460
        wxChar Ch = Code.GetChar(Pos);
 
461
        if ( Ch!=_T('\n') && Ch!=_T('\r') ) break;
 
462
        Pos++;
 
463
    }
 
464
 
 
465
    BeginPos = Pos;
 
466
    return true;
 
467
}
 
468
 
 
469
 
 
470
TiXmlElement* wxsVersionConverter::Convert(TiXmlElement* ConfigNode,TiXmlDocument* Doc,wxsProject* Project) const
 
471
{
 
472
    // Currently there's only one version of wxSmith, no need to convert
 
473
    return 0;
 
474
}