2
* This file is part of wxSmith plugin for Code::Blocks Studio
3
* Copyright (C) 2006-2007 Bartlomiej Swiecki
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.
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.
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/>.
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 $
23
#include "wxsversionconverter.h"
24
#include "wxsproject.h"
28
#include <wx/string.h>
29
#include <tinyxml/tinywxuni.h>
31
// TODO: This is same as in wxsproject.h, make one set instead of two
34
const int CurrentVersion = 1;
35
const char* CurrentVersionStr = "1";
38
const wxsVersionConverter& wxsVersionConverter::Get()
40
static wxsVersionConverter Singleton;
44
bool wxsVersionConverter::DetectOldConfig(TiXmlElement* Node,wxsProject* Project) const
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;
56
TiXmlElement* wxsVersionConverter::ConvertFromOldConfig(TiXmlElement* ConfigNode,TiXmlDocument* Doc,wxsProject* Project) const
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;
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() )
68
wxString NodeName = cbC2U(Node->Value());
69
if ( NodeName == _T("configuration") )
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");
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");
87
if ( NodeName == _T("dialog") ||
88
NodeName == _T("frame") ||
89
NodeName == _T("panel") )
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");
98
if ( Wxs && Class && Src && Hdr && Mode )
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();
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");
113
ConvertOldWxsFile(Project->GetProjectPath()+_T("wxsmith/")+cbC2U(Wxs),Xrc!=0);
114
AdoptOldSourceFile(Project->GetProjectPath()+cbC2U(Src),cbC2U(Class));
122
void wxsVersionConverter::ConvertOldWxsFile(const wxString& FileName,bool UsingXrc) const
125
if ( !TinyXML::LoadDocument(FileName,&Doc) ) return;
127
TiXmlElement* Smith = Doc.FirstChildElement("resource");
130
Smith->SetValue("wxsmith");
133
if ( UsingXrc && Smith )
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);
141
TinyXML::SaveDocument(FileName,&Doc);
144
void wxsVersionConverter::GatherExtraFromOldResourceReq(TiXmlElement* Object,TiXmlElement* Extra,bool Root) const
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") )
152
if ( Object->Attribute("class") && (Root || Object->Attribute("name")) )
154
TiXmlElement* ThisExtra = 0;
156
// Checking if we got variable name
157
if ( Object->Attribute("variable") && Object->Attribute("member") )
159
ThisExtra = Extra->InsertEndChild(TiXmlElement("object"))->ToElement();
160
ThisExtra->SetAttribute("variable",Object->Attribute("variable"));
161
ThisExtra->SetAttribute("member",Object->Attribute("member"));
164
// Checking for event handlers
166
for ( TiXmlElement* Handler = Object->FirstChildElement("handler"); Handler; Handler = Handler->NextSiblingElement("handler") )
170
ThisExtra = Extra->InsertEndChild(TiXmlElement("object"))->ToElement();
172
ThisExtra->InsertEndChild(*Handler);
179
ThisExtra->SetAttribute("root","1");
183
ThisExtra->SetAttribute("name",Object->Attribute("name"));
184
ThisExtra->SetAttribute("class",Object->Attribute("class"));
190
for ( TiXmlElement* Child = Object->FirstChildElement(); Child; Child = Child->NextSiblingElement() )
192
GatherExtraFromOldResourceReq(Child,Extra,false);
196
void wxsVersionConverter::AdoptOldSourceFile(const wxString& FileName,const wxString& Class) const
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
204
// This may not be tricky enough but I hope that not much people mess
205
// with code generated by wxSmith from templates ;)
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)
214
bool IsInternalHeaders = wxsCoder::Get()->GetCode(
216
_T("//(*InternalHeaders(") + Class + _T(")\n"),
218
true,true).Length() != 0;
220
bool IsIdInit = wxsCoder::Get()->GetCode(
222
_T("//(*IdInit(") + Class + _T(")\n"),
224
true,true).Length() != 0;
226
if ( !IsInternalHeaders || !IsIdInit )
228
wxFontEncoding Encoding;
230
wxString Content = wxsCoder::Get()->GetFullCode(FileName,Encoding,UseBOM);
233
if ( !IsInternalHeaders )
235
while ( Pos<(int)Content.Len() && LineContainDirectivesOnly(Content,Pos) );
237
wxString AddInternalHeaders =
238
_T("//(*InternalHeaders(") + Class + _T(")\n")
242
Content = Content.Mid(0,Pos) + AddInternalHeaders + Content.Mid(Pos);
246
Pos = Content.Find(_T("//(*InternalHeaders(") + Class + _T(")\n"));
247
int Shift = Content.Mid(Pos).Find(_T("//*)"));
248
if ( Shift != wxNOT_FOUND )
256
int NewPos = Content.Find(_T("BEGIN_EVENT_TABLE(")+Class);
257
if ( NewPos!=wxNOT_FOUND )
262
// Switching to first character in this line
265
Content.GetChar(Pos-1)!=_T('\n') &&
266
Content.GetChar(Pos-1)!=_T('\r') )
268
wxChar Ch = Content.GetChar(Pos--);
269
Indent.Append((Ch==_T('\t'))?_T('\t'):_T(' '));
273
Indent + _T("//(*IdInit(") + Class + _T(")\n") +
274
Indent + _T("//*)\n") +
277
Content = Content.Mid(0,Pos) + AddIdInit + Content.Mid(Pos);
279
wxsCoder::Get()->PutFullCode(FileName,Content,Encoding,UseBOM);
283
bool wxsVersionConverter::LineContainDirectivesOnly(const wxString& Code,int& BeginPos) const
287
wxChar PreviousChar = _T('\0');
289
// Processing characters in this line
290
while ( Pos < (int)Code.Len() )
292
wxChar Ch = Code.GetChar(Pos);
293
if ( Ch==_T('/') && PreviousChar==_T('/') )
295
// We got // comment, skipping till the end of line
296
while ( ++Pos < (int)Code.Len() )
299
wxChar Ch = Code.GetChar(Pos);
300
if ( Ch==_T('\n') || Ch==_T('\r') )
302
if ( PreviousChar == _T('\\') )
304
// Backslash removes EOL
305
if ( ++Pos < (int)Code.Len() )
308
Ch = Code.GetChar(Pos);
309
if ( (Ch!=_T('\n') && Ch==_T('\r')) || (Ch==PreviousChar) )
318
// End-Of-Line and End-Of-Comment
319
while ( Pos<(int)Code.Len() )
321
wxChar Ch = Code.GetChar(Pos);
322
if ( Ch!=_T('\n') && Ch!=_T('\r') ) break;
331
// End of file approached
335
else if ( Ch==_T('*') && PreviousChar==_T('/') )
337
// Starting multiline comment, we skip everything till */ sequence
338
while ( ++Pos < (int)Code.Len() )
341
wxChar Ch = Code.GetChar(Pos);
343
if ( Ch==_T('/') && PreviousChar==_T('*') )
345
// End of comment, breaking
350
if ( Pos >= (int)Code.Len() )
352
// Jumping out to skip another Pos++
356
else if ( PreviousChar==_T('/') )
358
// Previous char was not comment beginning
359
// need to rewind to it and jump out
363
else if ( Ch!=_T(' ') && Ch!=_T('\t') )
367
// No white char, jumping out to find out what's this
370
// If it's '/', it may be a start
371
// of comment, we give it a try
377
if ( Pos<(int)Code.Len() )
379
wxChar Ch = Code.GetChar(Pos);
380
if ( (Ch!=_T('\n')) && (Ch!=_T('\r')) )
382
// This is no directive, jumping out of function
383
if ( Ch != _T('#') ) return false;
388
bool BlockMultilineComment = false;
389
while ( Pos<(int)Code.Len() )
391
wxChar Ch = Code.GetChar(Pos);
393
if ( Ch==_T('\n') || Ch==_T('\r') )
395
if ( PreviousChar == _T('\\') )
397
// Backslash removes EOL
398
if ( ++Pos >= (int)Code.Len() )
405
Ch = Code.GetChar(Pos);
406
if ( (Ch!=_T('\n') && Ch!=_T('\r')) || (Ch==PreviousChar) )
417
else if ( Ch==_T('/') && PreviousChar==_T('/') )
419
// Have to block any multiline comment in this line
420
BlockMultilineComment = true;
422
else if ( Ch==_T('*') && PreviousChar==_T('/') && !BlockMultilineComment )
424
// Searching for end of comment and return there
425
bool WasAnyNL = false;
426
while ( ++Pos<(int)Code.Len() )
429
Ch = Code.GetChar(Pos);
430
if ( Ch==_T('/') && PreviousChar==_T('*') )
432
// Comment has been finished
435
// If there was any NL in comment, this mean that
436
// we can start scanning new line here so we return
443
// There was no NL in comment, we're still inside directive
447
else if ( Ch==_T('\n') || Ch==_T('\r') )
457
// Skipping all NL chars left
458
while ( Pos<(int)Code.Len() )
460
wxChar Ch = Code.GetChar(Pos);
461
if ( Ch!=_T('\n') && Ch!=_T('\r') ) break;
470
TiXmlElement* wxsVersionConverter::Convert(TiXmlElement* ConfigNode,TiXmlDocument* Doc,wxsProject* Project) const
472
// Currently there's only one version of wxSmith, no need to convert