| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062 |
- /////////////////////////////////////////////////////////////////////////////
- // Name: wxrc.cpp
- // Purpose: XML resource compiler
- // Author: Vaclav Slavik, Eduardo Marques <edrdo@netcabo.pt>
- // Created: 2000/03/05
- // Copyright: (c) 2000 Vaclav Slavik
- // Licence: wxWindows licence
- /////////////////////////////////////////////////////////////////////////////
- // For compilers that support precompilation, includes "wx/wx.h".
- #include "wx/wxprec.h"
- #ifdef __BORLANDC__
- #pragma hdrstop
- #endif
- // for all others, include the necessary headers
- #ifndef WX_PRECOMP
- #include "wx/app.h"
- #include "wx/log.h"
- #include "wx/wxcrtvararg.h"
- #endif
- #include "wx/cmdline.h"
- #include "wx/xml/xml.h"
- #include "wx/ffile.h"
- #include "wx/filename.h"
- #include "wx/wfstream.h"
- #include "wx/utils.h"
- #include "wx/hashset.h"
- #include "wx/mimetype.h"
- #include "wx/vector.h"
- WX_DECLARE_HASH_SET(wxString, wxStringHash, wxStringEqual, StringSet);
- class XRCWidgetData
- {
- public:
- XRCWidgetData(const wxString& vname,const wxString& vclass)
- : m_class(vclass), m_name(vname) {}
- const wxString& GetName() const { return m_name; }
- const wxString& GetClass() const { return m_class; }
- private:
- wxString m_class;
- wxString m_name;
- };
- #include "wx/arrimpl.cpp"
- WX_DECLARE_OBJARRAY(XRCWidgetData,ArrayOfXRCWidgetData);
- WX_DEFINE_OBJARRAY(ArrayOfXRCWidgetData)
- class XRCWndClassData
- {
- private:
- wxString m_className;
- wxString m_parentClassName;
- StringSet m_ancestorClassNames;
- ArrayOfXRCWidgetData m_wdata;
- void BrowseXmlNode(wxXmlNode* node)
- {
- wxString classValue;
- wxString nameValue;
- wxXmlNode* children;
- while (node)
- {
- if (node->GetName() == wxT("object")
- && node->GetAttribute(wxT("class"),&classValue)
- && node->GetAttribute(wxT("name"),&nameValue))
- {
- m_wdata.Add(XRCWidgetData(nameValue,classValue));
- }
- children = node->GetChildren();
- if (children)
- BrowseXmlNode(children);
- node = node->GetNext();
- }
- }
- public:
- XRCWndClassData(const wxString& className,
- const wxString& parentClassName,
- const wxXmlNode* node) :
- m_className(className) , m_parentClassName(parentClassName)
- {
- if ( className == wxT("wxMenu") )
- {
- m_ancestorClassNames.insert(wxT("wxMenu"));
- m_ancestorClassNames.insert(wxT("wxMenuBar"));
- }
- else if ( className == wxT("wxMDIChildFrame") )
- {
- m_ancestorClassNames.insert(wxT("wxMDIParentFrame"));
- }
- else if( className == wxT("wxMenuBar") ||
- className == wxT("wxStatusBar") ||
- className == wxT("wxToolBar") )
- {
- m_ancestorClassNames.insert(wxT("wxFrame"));
- }
- else
- {
- m_ancestorClassNames.insert(wxT("wxWindow"));
- }
- BrowseXmlNode(node->GetChildren());
- }
- const ArrayOfXRCWidgetData& GetWidgetData()
- {
- return m_wdata;
- }
- bool CanBeUsedWithXRCCTRL(const wxString& name)
- {
- if (name == wxT("tool") ||
- name == wxT("data") ||
- name == wxT("unknown") ||
- name == wxT("notebookpage") ||
- name == wxT("separator") ||
- name == wxT("sizeritem") ||
- name == wxT("wxMenu") ||
- name == wxT("wxMenuBar") ||
- name == wxT("wxMenuItem") ||
- name.EndsWith(wxT("Sizer")) )
- {
- return false;
- }
- return true;
- }
- void GenerateHeaderCode(wxFFile& file)
- {
- file.Write(wxT("class ") + m_className + wxT(" : public ") + m_parentClassName
- + wxT(" {\nprotected:\n"));
- size_t i;
- for(i=0;i<m_wdata.GetCount();++i)
- {
- const XRCWidgetData& w = m_wdata.Item(i);
- if( !CanBeUsedWithXRCCTRL(w.GetClass()) ) continue;
- if( w.GetName().empty() ) continue;
- file.Write(
- wxT(" ") + w.GetClass() + wxT("* ") + w.GetName()
- + wxT(";\n"));
- }
- file.Write(wxT("\nprivate:\n void InitWidgetsFromXRC(wxWindow *parent){\n")
- wxT(" wxXmlResource::Get()->LoadObject(this,parent,wxT(\"")
- + m_className
- + wxT("\"), wxT(\"")
- + m_parentClassName
- + wxT("\"));\n"));
- for(i=0;i<m_wdata.GetCount();++i)
- {
- const XRCWidgetData& w = m_wdata.Item(i);
- if( !CanBeUsedWithXRCCTRL(w.GetClass()) ) continue;
- if( w.GetName().empty() ) continue;
- file.Write( wxT(" ")
- + w.GetName()
- + wxT(" = XRCCTRL(*this,\"")
- + w.GetName()
- + wxT("\",")
- + w.GetClass()
- + wxT(");\n"));
- }
- file.Write(wxT(" }\n"));
- file.Write( wxT("public:\n"));
- if ( m_ancestorClassNames.size() == 1 )
- {
- file.Write
- (
- m_className +
- wxT("(") +
- *m_ancestorClassNames.begin() +
- wxT(" *parent=NULL){\n") +
- wxT(" InitWidgetsFromXRC((wxWindow *)parent);\n")
- wxT(" }\n")
- wxT("};\n")
- );
- }
- else
- {
- file.Write(m_className + wxT("(){\n") +
- wxT(" InitWidgetsFromXRC(NULL);\n")
- wxT(" }\n")
- wxT("};\n"));
- for ( StringSet::const_iterator it = m_ancestorClassNames.begin();
- it != m_ancestorClassNames.end();
- ++it )
- {
- file.Write(m_className + wxT("(") + *it + wxT(" *parent){\n") +
- wxT(" InitWidgetsFromXRC((wxWindow *)parent);\n")
- wxT(" }\n")
- wxT("};\n"));
- }
- }
- }
- };
- WX_DECLARE_OBJARRAY(XRCWndClassData,ArrayOfXRCWndClassData);
- WX_DEFINE_OBJARRAY(ArrayOfXRCWndClassData)
- struct ExtractedString
- {
- ExtractedString() : lineNo(-1) {}
- ExtractedString(const wxString& str_,
- const wxString& filename_, int lineNo_)
- : str(str_), filename(filename_), lineNo(lineNo_)
- {}
- wxString str;
- wxString filename;
- int lineNo;
- };
- typedef wxVector<ExtractedString> ExtractedStrings;
- class XmlResApp : public wxAppConsole
- {
- public:
- // don't use builtin cmd line parsing:
- virtual bool OnInit() { return true; }
- virtual int OnRun();
- private:
- void ParseParams(const wxCmdLineParser& cmdline);
- void CompileRes();
- wxArrayString PrepareTempFiles();
- void FindFilesInXML(wxXmlNode *node, wxArrayString& flist, const wxString& inputPath);
- wxString GetInternalFileName(const wxString& name, const wxArrayString& flist);
- void DeleteTempFiles(const wxArrayString& flist);
- void MakePackageZIP(const wxArrayString& flist);
- void MakePackageCPP(const wxArrayString& flist);
- void MakePackagePython(const wxArrayString& flist);
- void OutputGettext();
- ExtractedStrings FindStrings();
- ExtractedStrings FindStrings(const wxString& filename, wxXmlNode *node);
- bool Validate();
- bool flagVerbose, flagCPP, flagPython, flagGettext, flagValidate, flagValidateOnly;
- wxString parOutput, parFuncname, parOutputPath, parSchemaFile;
- wxArrayString parFiles;
- int retCode;
- ArrayOfXRCWndClassData aXRCWndClassData;
- bool flagH;
- void GenCPPHeader();
- };
- IMPLEMENT_APP_CONSOLE(XmlResApp)
- int XmlResApp::OnRun()
- {
- static const wxCmdLineEntryDesc cmdLineDesc[] =
- {
- { wxCMD_LINE_SWITCH, "h", "help", "show help message", wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
- { wxCMD_LINE_SWITCH, "v", "verbose", "be verbose" },
- { wxCMD_LINE_SWITCH, "e", "extra-cpp-code", "output C++ header file with XRC derived classes" },
- { wxCMD_LINE_SWITCH, "c", "cpp-code", "output C++ source rather than .rsc file" },
- { wxCMD_LINE_SWITCH, "p", "python-code", "output wxPython source rather than .rsc file" },
- { wxCMD_LINE_SWITCH, "g", "gettext", "output list of translatable strings (to stdout or file if -o used)" },
- { wxCMD_LINE_OPTION, "n", "function", "C++/Python function name (with -c or -p) [InitXmlResource]" },
- { wxCMD_LINE_OPTION, "o", "output", "output file [resource.xrs/cpp]" },
- { wxCMD_LINE_SWITCH, "", "validate", "check XRC correctness (in addition to other processing)" },
- { wxCMD_LINE_SWITCH, "", "validate-only", "check XRC correctness and do nothing else" },
- { wxCMD_LINE_OPTION, "", "xrc-schema", "RELAX NG schema file to validate against (optional)" },
- #if 0 // not yet implemented
- { wxCMD_LINE_OPTION, "l", "list-of-handlers", "output list of necessary handlers to this file" },
- #endif
- { wxCMD_LINE_PARAM, NULL, NULL, "input file(s)",
- wxCMD_LINE_VAL_STRING,
- wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_OPTION_MANDATORY },
- wxCMD_LINE_DESC_END
- };
- wxCmdLineParser parser(cmdLineDesc, argc, argv);
- switch (parser.Parse())
- {
- case -1:
- return 0;
- case 0:
- retCode = 0;
- ParseParams(parser);
- if (flagValidate)
- {
- if ( !Validate() )
- return 2;
- if ( flagValidateOnly )
- return 0;
- }
- if (flagGettext)
- OutputGettext();
- else
- CompileRes();
- return retCode;
- }
- return 1;
- }
- void XmlResApp::ParseParams(const wxCmdLineParser& cmdline)
- {
- flagGettext = cmdline.Found("g");
- flagVerbose = cmdline.Found("v");
- flagCPP = cmdline.Found("c");
- flagPython = cmdline.Found("p");
- flagH = flagCPP && cmdline.Found("e");
- flagValidateOnly = cmdline.Found("validate-only");
- flagValidate = flagValidateOnly || cmdline.Found("validate");
- cmdline.Found("xrc-schema", &parSchemaFile);
- if (!cmdline.Found("o", &parOutput))
- {
- if (flagGettext)
- parOutput = wxEmptyString;
- else
- {
- if (flagCPP)
- parOutput = wxT("resource.cpp");
- else if (flagPython)
- parOutput = wxT("resource.py");
- else
- parOutput = wxT("resource.xrs");
- }
- }
- if (!parOutput.empty())
- {
- wxFileName fn(parOutput);
- fn.Normalize();
- parOutput = fn.GetFullPath();
- parOutputPath = wxPathOnly(parOutput);
- }
- if (!parOutputPath) parOutputPath = wxT(".");
- if (!cmdline.Found("n", &parFuncname))
- parFuncname = wxT("InitXmlResource");
- for (size_t i = 0; i < cmdline.GetParamCount(); i++)
- {
- #ifdef __WINDOWS__
- wxString fn=wxFindFirstFile(cmdline.GetParam(i), wxFILE);
- while (!fn.empty())
- {
- parFiles.Add(fn);
- fn=wxFindNextFile();
- }
- #else
- parFiles.Add(cmdline.GetParam(i));
- #endif
- }
- }
- void XmlResApp::CompileRes()
- {
- wxArrayString files = PrepareTempFiles();
- if ( wxFileExists(parOutput) )
- wxRemoveFile(parOutput);
- if (!retCode)
- {
- if (flagCPP){
- MakePackageCPP(files);
- if (flagH)
- GenCPPHeader();
- }
- else if (flagPython)
- MakePackagePython(files);
- else
- MakePackageZIP(files);
- }
- DeleteTempFiles(files);
- }
- wxString XmlResApp::GetInternalFileName(const wxString& name, const wxArrayString& flist)
- {
- wxString name2 = name;
- name2.Replace(wxT(":"), wxT("_"));
- name2.Replace(wxT("/"), wxT("_"));
- name2.Replace(wxT("\\"), wxT("_"));
- name2.Replace(wxT("*"), wxT("_"));
- name2.Replace(wxT("?"), wxT("_"));
- wxString s = wxFileNameFromPath(parOutput) + wxT("$") + name2;
- if (wxFileExists(s) && flist.Index(s) == wxNOT_FOUND)
- {
- for (int i = 0;; i++)
- {
- s.Printf(wxFileNameFromPath(parOutput) + wxT("$%03i-") + name2, i);
- if (!wxFileExists(s) || flist.Index(s) != wxNOT_FOUND)
- break;
- }
- }
- return s;
- }
- wxArrayString XmlResApp::PrepareTempFiles()
- {
- wxArrayString flist;
- for (size_t i = 0; i < parFiles.GetCount(); i++)
- {
- if (flagVerbose)
- wxPrintf(wxT("processing ") + parFiles[i] + wxT("...\n"));
- wxXmlDocument doc;
- if (!doc.Load(parFiles[i]))
- {
- wxLogError(wxT("Error parsing file ") + parFiles[i]);
- retCode = 1;
- continue;
- }
- wxString name, ext, path;
- wxFileName::SplitPath(parFiles[i], &path, &name, &ext);
- FindFilesInXML(doc.GetRoot(), flist, path);
- if (flagH)
- {
- wxXmlNode* node = (doc.GetRoot())->GetChildren();
- wxString classValue,nameValue;
- while(node){
- if(node->GetName() == wxT("object")
- && node->GetAttribute(wxT("class"),&classValue)
- && node->GetAttribute(wxT("name"),&nameValue)){
- aXRCWndClassData.Add(
- XRCWndClassData(nameValue,classValue,node)
- );
- }
- node = node -> GetNext();
- }
- }
- wxString internalName = GetInternalFileName(parFiles[i], flist);
- doc.Save(parOutputPath + wxFILE_SEP_PATH + internalName);
- flist.Add(internalName);
- }
- return flist;
- }
- // Does 'node' contain filename information at all?
- static bool NodeContainsFilename(wxXmlNode *node)
- {
- const wxString name = node->GetName();
- // Any bitmaps (bitmap2 is used for disabled toolbar buttons):
- if ( name == wxT("bitmap") || name == wxT("bitmap2") )
- return true;
- if ( name == wxT("icon") )
- return true;
- // wxBitmapButton:
- wxXmlNode *parent = node->GetParent();
- if (parent != NULL &&
- parent->GetAttribute(wxT("class"), wxT("")) == wxT("wxBitmapButton") &&
- (name == wxT("focus") ||
- name == wxT("disabled") ||
- name == wxT("hover") ||
- name == wxT("selected")))
- return true;
- // wxBitmap or wxIcon toplevel resources:
- if ( name == wxT("object") )
- {
- wxString klass = node->GetAttribute(wxT("class"), wxEmptyString);
- if (klass == wxT("wxBitmap") ||
- klass == wxT("wxIcon") ||
- klass == wxT("data") )
- return true;
- }
- // URLs in wxHtmlWindow:
- if ( name == wxT("url") &&
- parent != NULL &&
- parent->GetAttribute(wxT("class"), wxT("")) == wxT("wxHtmlWindow") )
- {
- // FIXME: this is wrong for e.g. http:// URLs
- return true;
- }
- return false;
- }
- // find all files mentioned in structure, e.g. <bitmap>filename</bitmap>
- void XmlResApp::FindFilesInXML(wxXmlNode *node, wxArrayString& flist, const wxString& inputPath)
- {
- // Is 'node' XML node element?
- if (node == NULL) return;
- if (node->GetType() != wxXML_ELEMENT_NODE) return;
- bool containsFilename = NodeContainsFilename(node);
- wxXmlNode *n = node->GetChildren();
- while (n)
- {
- if (containsFilename &&
- (n->GetType() == wxXML_TEXT_NODE ||
- n->GetType() == wxXML_CDATA_SECTION_NODE))
- {
- wxString fullname;
- if (wxIsAbsolutePath(n->GetContent()) || inputPath.empty())
- fullname = n->GetContent();
- else
- fullname = inputPath + wxFILE_SEP_PATH + n->GetContent();
- if (flagVerbose)
- wxPrintf(wxT("adding ") + fullname + wxT("...\n"));
- wxString filename = GetInternalFileName(n->GetContent(), flist);
- n->SetContent(filename);
- if (flist.Index(filename) == wxNOT_FOUND)
- flist.Add(filename);
- wxFileInputStream sin(fullname);
- wxFileOutputStream sout(parOutputPath + wxFILE_SEP_PATH + filename);
- sin.Read(sout); // copy the stream
- }
- // subnodes:
- if (n->GetType() == wxXML_ELEMENT_NODE)
- FindFilesInXML(n, flist, inputPath);
- n = n->GetNext();
- }
- }
- void XmlResApp::DeleteTempFiles(const wxArrayString& flist)
- {
- for (size_t i = 0; i < flist.GetCount(); i++)
- wxRemoveFile(parOutputPath + wxFILE_SEP_PATH + flist[i]);
- }
- void XmlResApp::MakePackageZIP(const wxArrayString& flist)
- {
- wxString files;
- for (size_t i = 0; i < flist.GetCount(); i++)
- files += flist[i] + wxT(" ");
- files.RemoveLast();
- if (flagVerbose)
- wxPrintf(wxT("compressing ") + parOutput + wxT("...\n"));
- wxString cwd = wxGetCwd();
- wxSetWorkingDirectory(parOutputPath);
- int execres = wxExecute(wxT("zip -9 -j ") +
- wxString(flagVerbose ? wxT("\"") : wxT("-q \"")) +
- parOutput + wxT("\" ") + files,
- wxEXEC_BLOCK);
- wxSetWorkingDirectory(cwd);
- if (execres == -1)
- {
- wxLogError(wxT("Unable to execute zip program. Make sure it is in the path."));
- wxLogError(wxT("You can download it at http://www.cdrom.com/pub/infozip/"));
- retCode = 1;
- return;
- }
- }
- static wxString FileToCppArray(wxString filename, int num)
- {
- wxString output;
- wxString tmp;
- wxString snum;
- wxFFile file(filename, wxT("rb"));
- wxFileOffset offset = file.Length();
- wxASSERT_MSG( offset >= 0 , wxT("Invalid file length") );
- const size_t lng = wx_truncate_cast(size_t, offset);
- wxASSERT_MSG( static_cast<wxFileOffset>(lng) == offset,
- wxT("Huge file not supported") );
- snum.Printf(wxT("%i"), num);
- output.Printf(wxT("static size_t xml_res_size_") + snum + wxT(" = %lu;\n"),
- static_cast<unsigned long>(lng));
- output += wxT("static unsigned char xml_res_file_") + snum + wxT("[] = {\n");
- // we cannot use string literals because MSVC is dumb wannabe compiler
- // with arbitrary limitation to 2048 strings :(
- unsigned char *buffer = new unsigned char[lng];
- file.Read(buffer, lng);
- for (size_t i = 0, linelng = 0; i < lng; i++)
- {
- tmp.Printf(wxT("%i"), buffer[i]);
- if (i != 0) output << wxT(',');
- if (linelng > 70)
- {
- linelng = 0;
- output << wxT("\n");
- }
- output << tmp;
- linelng += tmp.Length()+1;
- }
- delete[] buffer;
- output += wxT("};\n\n");
- return output;
- }
- void XmlResApp::MakePackageCPP(const wxArrayString& flist)
- {
- wxFFile file(parOutput, wxT("wt"));
- unsigned i;
- if (flagVerbose)
- wxPrintf(wxT("creating C++ source file ") + parOutput + wxT("...\n"));
- file.Write(""
- "//\n"
- "// This file was automatically generated by wxrc, do not edit by hand.\n"
- "//\n\n"
- "#include <wx/wxprec.h>\n"
- "\n"
- "#ifdef __BORLANDC__\n"
- " #pragma hdrstop\n"
- "#endif\n"
- "\n"
- ""
- "#include <wx/filesys.h>\n"
- "#include <wx/fs_mem.h>\n"
- "#include <wx/xrc/xmlres.h>\n"
- "#include <wx/xrc/xh_all.h>\n"
- "\n"
- "#if wxCHECK_VERSION(2,8,5) && wxABI_VERSION >= 20805\n"
- " #define XRC_ADD_FILE(name, data, size, mime) \\\n"
- " wxMemoryFSHandler::AddFileWithMimeType(name, data, size, mime)\n"
- "#else\n"
- " #define XRC_ADD_FILE(name, data, size, mime) \\\n"
- " wxMemoryFSHandler::AddFile(name, data, size)\n"
- "#endif\n"
- "\n");
- for (i = 0; i < flist.GetCount(); i++)
- file.Write(
- FileToCppArray(parOutputPath + wxFILE_SEP_PATH + flist[i], i));
- file.Write(""
- "void " + parFuncname + "()\n"
- "{\n"
- "\n"
- " // Check for memory FS. If not present, load the handler:\n"
- " {\n"
- " wxMemoryFSHandler::AddFile(wxT(\"XRC_resource/dummy_file\"), wxT(\"dummy one\"));\n"
- " wxFileSystem fsys;\n"
- " wxFSFile *f = fsys.OpenFile(wxT(\"memory:XRC_resource/dummy_file\"));\n"
- " wxMemoryFSHandler::RemoveFile(wxT(\"XRC_resource/dummy_file\"));\n"
- " if (f) delete f;\n"
- " else wxFileSystem::AddHandler(new wxMemoryFSHandler);\n"
- " }\n"
- "\n");
- for (i = 0; i < flist.GetCount(); i++)
- {
- wxString s;
- wxString mime;
- wxString ext = wxFileName(flist[i]).GetExt();
- if ( ext.Lower() == wxT("xrc") )
- mime = wxT("text/xml");
- #if wxUSE_MIMETYPE
- else
- {
- wxFileType *ft = wxTheMimeTypesManager->GetFileTypeFromExtension(ext);
- if ( ft )
- {
- ft->GetMimeType(&mime);
- delete ft;
- }
- }
- #endif // wxUSE_MIMETYPE
- s.Printf(" XRC_ADD_FILE(wxT(\"XRC_resource/" + flist[i] +
- "\"), xml_res_file_%u, xml_res_size_%u, wxT(\"%s\"));\n",
- i, i, mime.c_str());
- file.Write(s);
- }
- for (i = 0; i < parFiles.GetCount(); i++)
- {
- file.Write(" wxXmlResource::Get()->Load(wxT(\"memory:XRC_resource/" +
- GetInternalFileName(parFiles[i], flist) + "\"));\n");
- }
- file.Write("}\n");
- }
- void XmlResApp::GenCPPHeader()
- {
- // Generate the output header in the same directory as the source file.
- wxFileName headerName(parOutput);
- headerName.SetExt("h");
- wxFFile file(headerName.GetFullPath(), wxT("wt"));
- file.Write(
- "//\n"
- "// This file was automatically generated by wxrc, do not edit by hand.\n"
- "//\n\n"
- "#ifndef __" + headerName.GetName() + "_h__\n"
- "#define __" + headerName.GetName() + "_h__\n"
- );
- for(size_t i=0;i<aXRCWndClassData.GetCount();++i){
- aXRCWndClassData.Item(i).GenerateHeaderCode(file);
- }
- file.Write(
- "\nvoid \n"
- + parFuncname
- + "();\n#endif\n");
- }
- static wxString FileToPythonArray(wxString filename, int num)
- {
- wxString output;
- wxString tmp;
- wxString snum;
- wxFFile file(filename, wxT("rb"));
- wxFileOffset offset = file.Length();
- wxASSERT_MSG( offset >= 0 , wxT("Invalid file length") );
- const size_t lng = wx_truncate_cast(size_t, offset);
- wxASSERT_MSG( static_cast<wxFileOffset>(lng) == offset,
- wxT("Huge file not supported") );
- snum.Printf(wxT("%i"), num);
- output = " xml_res_file_" + snum + " = '''\\\n";
- unsigned char *buffer = new unsigned char[lng];
- file.Read(buffer, lng);
- for (size_t i = 0, linelng = 0; i < lng; i++)
- {
- unsigned char c = buffer[i];
- if (c == '\n')
- {
- tmp = (wxChar)c;
- linelng = 0;
- }
- else if (c < 32 || c > 127 || c == '\'')
- tmp.Printf(wxT("\\x%02x"), c);
- else if (c == '\\')
- tmp = wxT("\\\\");
- else
- tmp = (wxChar)c;
- if (linelng > 70)
- {
- linelng = 0;
- output << wxT("\\\n");
- }
- output << tmp;
- linelng += tmp.Length();
- }
- delete[] buffer;
- output += wxT("'''\n\n");
- return output;
- }
- void XmlResApp::MakePackagePython(const wxArrayString& flist)
- {
- wxFFile file(parOutput, wxT("wt"));
- unsigned i;
- if (flagVerbose)
- wxPrintf(wxT("creating Python source file ") + parOutput + wxT("...\n"));
- file.Write(
- "#\n"
- "# This file was automatically generated by wxrc, do not edit by hand.\n"
- "#\n\n"
- "import wx\n"
- "import wx.xrc\n\n"
- );
- file.Write("def " + parFuncname + "():\n");
- for (i = 0; i < flist.GetCount(); i++)
- file.Write(
- FileToPythonArray(parOutputPath + wxFILE_SEP_PATH + flist[i], i));
- file.Write(
- " # check if the memory filesystem handler has been loaded yet, and load it if not\n"
- " wx.MemoryFSHandler.AddFile('XRC_resource/dummy_file', 'dummy value')\n"
- " fsys = wx.FileSystem()\n"
- " f = fsys.OpenFile('memory:XRC_resource/dummy_file')\n"
- " wx.MemoryFSHandler.RemoveFile('XRC_resource/dummy_file')\n"
- " if f is not None:\n"
- " f.Destroy()\n"
- " else:\n"
- " wx.FileSystem.AddHandler(wx.MemoryFSHandler())\n"
- "\n"
- " # load all the strings as memory files and load into XmlRes\n"
- );
- for (i = 0; i < flist.GetCount(); i++)
- {
- wxString s;
- s.Printf(" wx.MemoryFSHandler.AddFile('XRC_resource/" + flist[i] +
- "', xml_res_file_%u)\n", i);
- file.Write(s);
- }
- for (i = 0; i < parFiles.GetCount(); i++)
- {
- file.Write(" wx.xrc.XmlResource.Get().Load('memory:XRC_resource/" +
- GetInternalFileName(parFiles[i], flist) + "')\n");
- }
- file.Write("\n");
- }
- void XmlResApp::OutputGettext()
- {
- ExtractedStrings str = FindStrings();
- wxFFile fout;
- if (parOutput.empty())
- fout.Attach(stdout);
- else
- fout.Open(parOutput, wxT("wt"));
- for (ExtractedStrings::const_iterator i = str.begin(); i != str.end(); ++i)
- {
- const wxFileName filename(i->filename);
- wxString s;
- s.Printf("#line %d \"%s\"\n",
- i->lineNo, filename.GetFullPath(wxPATH_UNIX));
- fout.Write(s);
- fout.Write("_(\"" + i->str + "\");\n");
- }
- if (!parOutput) fout.Detach();
- }
- ExtractedStrings XmlResApp::FindStrings()
- {
- ExtractedStrings arr, a2;
- for (size_t i = 0; i < parFiles.GetCount(); i++)
- {
- if (flagVerbose)
- wxPrintf(wxT("processing ") + parFiles[i] + wxT("...\n"));
- wxXmlDocument doc;
- if (!doc.Load(parFiles[i]))
- {
- wxLogError(wxT("Error parsing file ") + parFiles[i]);
- retCode = 1;
- continue;
- }
- a2 = FindStrings(parFiles[i], doc.GetRoot());
- WX_APPEND_ARRAY(arr, a2);
- }
- return arr;
- }
- static wxString ConvertText(const wxString& str)
- {
- wxString str2;
- const wxChar *dt;
- for (dt = str.c_str(); *dt; dt++)
- {
- if (*dt == wxT('_'))
- {
- if ( *(dt+1) == 0 )
- str2 << wxT('_');
- else if ( *(++dt) == wxT('_') )
- str2 << wxT('_');
- else
- str2 << wxT('&') << *dt;
- }
- else
- {
- switch (*dt)
- {
- case wxT('\n') : str2 << wxT("\\n"); break;
- case wxT('\t') : str2 << wxT("\\t"); break;
- case wxT('\r') : str2 << wxT("\\r"); break;
- case wxT('\\') : if ((*(dt+1) != 'n') &&
- (*(dt+1) != 't') &&
- (*(dt+1) != 'r'))
- str2 << wxT("\\\\");
- else
- str2 << wxT("\\");
- break;
- case wxT('"') : str2 << wxT("\\\""); break;
- default : str2 << *dt; break;
- }
- }
- }
- return str2;
- }
- ExtractedStrings
- XmlResApp::FindStrings(const wxString& filename, wxXmlNode *node)
- {
- ExtractedStrings arr;
- wxXmlNode *n = node;
- if (n == NULL) return arr;
- n = n->GetChildren();
- while (n)
- {
- if ((node->GetType() == wxXML_ELEMENT_NODE) &&
- // parent is an element, i.e. has subnodes...
- (n->GetType() == wxXML_TEXT_NODE ||
- n->GetType() == wxXML_CDATA_SECTION_NODE) &&
- // ...it is textnode...
- (
- node/*not n!*/->GetName() == wxT("label") ||
- (node/*not n!*/->GetName() == wxT("value") &&
- !n->GetContent().IsNumber()) ||
- node/*not n!*/->GetName() == wxT("help") ||
- node/*not n!*/->GetName() == wxT("longhelp") ||
- node/*not n!*/->GetName() == wxT("tooltip") ||
- node/*not n!*/->GetName() == wxT("htmlcode") ||
- node/*not n!*/->GetName() == wxT("title") ||
- node/*not n!*/->GetName() == wxT("item") ||
- node/*not n!*/->GetName() == wxT("message") ||
- node/*not n!*/->GetName() == wxT("note") ||
- node/*not n!*/->GetName() == wxT("defaultdirectory") ||
- node/*not n!*/->GetName() == wxT("defaultfilename") ||
- node/*not n!*/->GetName() == wxT("defaultfolder") ||
- node/*not n!*/->GetName() == wxT("filter") ||
- node/*not n!*/->GetName() == wxT("caption")
- ))
- // ...and known to contain translatable string
- {
- if (!flagGettext ||
- node->GetAttribute(wxT("translate"), wxT("1")) != wxT("0"))
- {
- arr.push_back
- (
- ExtractedString
- (
- ConvertText(n->GetContent()),
- filename,
- n->GetLineNumber()
- )
- );
- }
- }
- // subnodes:
- if (n->GetType() == wxXML_ELEMENT_NODE)
- {
- ExtractedStrings a2 = FindStrings(filename, n);
- WX_APPEND_ARRAY(arr, a2);
- }
- n = n->GetNext();
- }
- return arr;
- }
- bool XmlResApp::Validate()
- {
- if ( flagVerbose )
- wxPuts("validating XRC files...");
- wxString schemaURI;
- if ( !parSchemaFile.empty() )
- {
- schemaURI = parSchemaFile;
- }
- else
- {
- schemaURI = "http://www.wxwidgets.org/wxxrc";
- // Normally, we'd use an OASIS XML catalog to map the URI to a local copy,
- // but Jing's catalog support (-C catalogFile) requires additional
- // dependency, resolver.jar, that is not commonly installed alongside Jing
- // by systems that package Jing. So do the (trivial) mapping manually here:
- wxString wxWinRoot;
- if ( wxGetEnv("WXWIN", &wxWinRoot) )
- {
- wxString schemaFile(wxWinRoot + "/misc/schema/xrc_schema.rnc");
- if ( wxFileExists(schemaFile) )
- schemaURI = schemaFile;
- }
- }
- wxString cmdline = wxString::Format("jing -c \"%s\"", schemaURI);
- for ( size_t i = 0; i < parFiles.GetCount(); i++ )
- cmdline << wxString::Format(" \"%s\"", parFiles[i]);
- int res = wxExecute(cmdline, wxEXEC_BLOCK);
- if (res == -1)
- {
- wxLogError("Running RELAX NG validator failed.");
- wxLogError("Please install Jing (http://www.thaiopensource.com/relaxng/jing.html).");
- wxLogError("See http://svn.wxwidgets.org/svn/wx/wxWidgets/trunk/misc/schema/README for more information.");
- return false;
- }
- if ( flagVerbose )
- {
- if ( res == 0 )
- wxPuts("XRC validation passed without errors.");
- else
- wxPuts("XRC validation failed, there are errors.");
- }
- return res == 0;
- }
|