#include #include #include #include #include "xmlcopyeditor.h" #include "readfile.h" #include "xmldoc.h" #include "xmlctrl.h" #include "wraplibxml.h" #include "xmlschemalocator.h" #include "xsllocator.h" #include "xmlutf8reader.h" #include "xmlpromptgenerator.h" #include "xmlencodingspy.h" #include "styledialog.h" #include "mypropertysheet.h" #include "wraptempfilename.h" #include "globalreplacedialog.h" #include "replace.h" #include "associatedialog.h" #include "xmlassociatexsd.h" #include "xmlassociatexsl.h" #include "xmlassociatedtd.h" #include "aboutdialog.h" #include "pathresolver.h" #include "locationpanel.h" #include "insertpanel.h" #include "xmlwordcount.h" #include "mynotebook.h" #include "getlinuxappdir.h" #include "commandpanel.h" #include "binaryfile.h" #include #include #include #include #define ngettext wxGetTranslation #ifdef NEWFINDREPLACE #include "findreplacepanel.h" #endif #ifdef __WXMSW__ #include #else #include "wrapxerces.h" #include "xpm/appicon.xpm" #endif BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_ACTIVATE_APP(MyFrame::OnActivateApp) EVT_CLOSE(MyFrame::OnFrameClose) EVT_KEY_DOWN(MyFrame::OnKeyPressed) EVT_MENU(wxID_ABOUT, MyFrame::OnAbout) EVT_MENU(wxID_CLOSE, MyFrame::OnClose) EVT_MENU(wxID_CLOSE_ALL, MyFrame::OnCloseAll) EVT_MENU(wxID_CUT, MyFrame::OnCut) EVT_MENU(wxID_COPY, MyFrame::OnCopy) EVT_MENU(wxID_HELP, MyFrame::OnHelp) EVT_MENU(wxID_PASTE, MyFrame::OnPaste) EVT_MENU(ID_PASTE_NEW_DOCUMENT, MyFrame::OnPasteNewDocument) EVT_MENU(wxID_EXIT, MyFrame::OnQuit) EVT_MENU(wxID_NEW, MyFrame::OnNew) EVT_MENU(wxID_OPEN, MyFrame::OnOpen) EVT_MENU(wxID_SAVE, MyFrame::OnSave) EVT_MENU(wxID_SAVEAS, MyFrame::OnSaveAs) EVT_MENU(wxID_UNDO, MyFrame::OnUndo) EVT_MENU(wxID_REDO, MyFrame::OnRedo) EVT_MENU(wxID_REVERT, MyFrame::OnRevert) EVT_MENU(ID_INSERT_CHILD, MyFrame::OnInsertChild) EVT_MENU(ID_INSERT_SIBLING, MyFrame::OnInsertSibling) EVT_MENU(ID_INSERT_ENTITY, MyFrame::OnInsertEntity) EVT_MENU(ID_INSERT_TWIN, MyFrame::OnInsertTwin) EVT_MENU(ID_INSERT_SYMBOL, MyFrame::OnInsertSymbol) EVT_MENU(ID_TOGGLE_FOLD, MyFrame::OnToggleFold) EVT_MENU(ID_FOLD_ALL, MyFrame::OnFoldAll) EVT_MENU(ID_UNFOLD_ALL, MyFrame::OnUnfoldAll) EVT_MENU(ID_OPEN_LARGE_FILE, MyFrame::OnOpen) EVT_MENU(ID_PRINT_PREVIEW, MyFrame::OnPrintPreview) EVT_MENU(ID_PRINT_SETUP, MyFrame::OnPrintSetup) EVT_MENU(ID_PRINT, MyFrame::OnPrint) EVT_MENU(ID_WORD_COUNT, MyFrame::OnWordCount) EVT_MENU(ID_IMPORT_MSWORD, MyFrame::OnImportMSWord) EVT_MENU(ID_EXPORT_MSWORD, MyFrame::OnExportMSWord) EVT_MENU(ID_HIDE_PANE, MyFrame::OnClosePane) EVT_MENU(ID_COMMAND, MyFrame::OnCommand) EVT_MENU(ID_FIND, MyFrame::OnFind) EVT_MENU(ID_FIND_AGAIN, MyFrame::OnFindAgain) EVT_MENU(ID_GOTO, MyFrame::OnGoto) EVT_MENU(ID_FEEDBACK, MyFrame::OnFeedback) EVT_MENU(ID_PREVIOUS_DOCUMENT, MyFrame::OnPreviousDocument) EVT_MENU(ID_NEXT_DOCUMENT, MyFrame::OnNextDocument) EVT_MENU(ID_BROWSER, MyFrame::OnBrowser) EVT_MENU(ID_REPLACE, MyFrame::OnFindReplace) EVT_MENU(ID_GLOBAL_REPLACE, MyFrame::OnGlobalReplace) EVT_MENU(ID_CHECK_WELLFORMED, MyFrame::OnCheckWellformedness) EVT_MENU(ID_VALIDATE_DTD, MyFrame::OnValidateDTD) EVT_MENU(ID_VALIDATE_RELAX_NG, MyFrame::OnValidateRelaxNG) EVT_MENU(ID_VALIDATE_W3C_SCHEMA, MyFrame::OnValidateSchema) EVT_MENU(ID_XPATH, MyFrame::OnXPath) EVT_MENU_RANGE(ID_XSLT, ID_XSLT_WORDML_DOCBOOK, MyFrame::OnXslt) EVT_MENU(ID_PRETTYPRINT, MyFrame::OnPrettyPrint) EVT_MENU(ID_ENCODING, MyFrame::OnEncoding) EVT_MENU(ID_SPELL, MyFrame::OnSpelling) EVT_MENU(ID_FONT_SMALLER, MyFrame::OnFontSmaller) EVT_MENU(ID_FONT_NORMAL, MyFrame::OnFontMedium) EVT_MENU(ID_FONT_LARGER, MyFrame::OnFontLarger) EVT_MENU(ID_OPTIONS, MyFrame::OnOptions) EVT_MENU(ID_HOME, MyFrame::OnHome) EVT_MENU(ID_DOWNLOAD_SOURCE, MyFrame::OnDownloadSource) EVT_MENU(ID_TOOLBAR_VISIBLE, MyFrame::OnToolbarVisible) EVT_MENU(ID_LOCATION_PANE_VISIBLE, MyFrame::OnLocationPaneVisible) EVT_MENU(ID_PROTECT_TAGS, MyFrame::OnProtectTags) EVT_MENU(ID_WRAP_WORDS, MyFrame::OnWrapWords) EVT_MENU_RANGE(ID_SHOW_TAGS, ID_HIDE_TAGS, MyFrame::OnVisibilityState) EVT_MENU_RANGE(ID_ASSOCIATE_DTD_PUBLIC, ID_ASSOCIATE_XSL, MyFrame::OnAssociate) EVT_MENU_RANGE(wxID_FILE1, wxID_FILE9, MyFrame::OnHistoryFile) EVT_MENU_RANGE( ID_VALIDATE_PRESET1, ID_VALIDATE_PRESET9, MyFrame::OnValidatePreset) EVT_MENU_RANGE( ID_COLOR_SCHEME_DEFAULT, ID_COLOR_SCHEME_NONE, MyFrame::OnColorScheme) EVT_UPDATE_UI_RANGE(ID_REPLACE, ID_GLOBAL_REPLACE, MyFrame::OnUpdateReplaceRange) EVT_FIND(wxID_ANY, MyFrame::OnDialogFind) EVT_FIND_NEXT(wxID_ANY, MyFrame::OnDialogFind) EVT_FIND_REPLACE(wxID_ANY, MyFrame::OnDialogReplace) EVT_FIND_REPLACE_ALL(wxID_ANY, MyFrame::OnDialogReplaceAll) EVT_ICONIZE(MyFrame::OnIconize) EVT_UPDATE_UI(ID_LOCATION_PANE_VISIBLE, MyFrame::OnUpdateLocationPaneVisible) EVT_UPDATE_UI(wxID_CLOSE, MyFrame::OnUpdateDocRange) EVT_UPDATE_UI(wxID_SAVEAS, MyFrame::OnUpdateDocRange) EVT_UPDATE_UI(wxID_CLOSE_ALL, MyFrame::OnUpdateCloseAll) EVT_UPDATE_UI(wxID_REVERT, MyFrame::OnUpdateSaveUndo) EVT_UPDATE_UI(wxID_SAVE, MyFrame::OnUpdateDocRange) // always allow save if doc present EVT_UPDATE_UI(wxID_UNDO, MyFrame::OnUpdateSaveUndo) EVT_UPDATE_UI(wxID_REDO, MyFrame::OnUpdateRedo) EVT_UPDATE_UI(wxID_PASTE, MyFrame::OnUpdatePaste) EVT_UPDATE_UI(wxID_CUT, MyFrame::OnUpdateCutCopy) EVT_UPDATE_UI(wxID_COPY, MyFrame::OnUpdateCutCopy) EVT_UPDATE_UI(ID_FIND_AGAIN, MyFrame::OnUpdateFindAgain) EVT_UPDATE_UI_RANGE(ID_FIND, ID_EXPORT_MSWORD, MyFrame::OnUpdateDocRange) EVT_UPDATE_UI(ID_PREVIOUS_DOCUMENT, MyFrame::OnUpdatePreviousDocument) EVT_UPDATE_UI(ID_NEXT_DOCUMENT, MyFrame::OnUpdateNextDocument) EVT_UPDATE_UI(ID_HIDE_PANE, MyFrame::OnUpdateClosePane) EVT_IDLE(MyFrame::OnIdle) EVT_AUINOTEBOOK_PAGE_CLOSE(wxID_ANY, MyFrame::OnPageClosing) #ifdef __WXMSW__ EVT_DROP_FILES(MyFrame::OnDropFiles) #endif END_EVENT_TABLE() IMPLEMENT_APP(MyApp) MyApp::MyApp() : checker(NULL), server(NULL), connection(NULL), #ifdef __WXMSW__ config(new wxConfig(_T("SourceForge Project\\XML Copy Editor"))) #else config(new wxConfig(_T("xmlcopyeditor"))) #endif { lang = 0; #ifdef __WXGTK__ int fdnull = open("/dev/null", O_WRONLY, 0); dup2(fdnull, STDERR_FILENO); #endif myLocale.Init(); int systemLocale = myLocale.GetSystemLanguage(); switch (systemLocale) { case wxLANGUAGE_GERMAN: case wxLANGUAGE_GERMAN_AUSTRIAN: case wxLANGUAGE_GERMAN_BELGIUM: case wxLANGUAGE_GERMAN_LIECHTENSTEIN: case wxLANGUAGE_GERMAN_LUXEMBOURG: case wxLANGUAGE_GERMAN_SWISS: systemLocale = wxLANGUAGE_GERMAN; break; case wxLANGUAGE_CHINESE_SIMPLIFIED: systemLocale = wxLANGUAGE_CHINESE_SIMPLIFIED; break; case wxLANGUAGE_CHINESE_TRADITIONAL: systemLocale = wxLANGUAGE_CHINESE_TRADITIONAL; break; case wxLANGUAGE_SPANISH: case wxLANGUAGE_SPANISH_ARGENTINA: case wxLANGUAGE_SPANISH_BOLIVIA: case wxLANGUAGE_SPANISH_CHILE: case wxLANGUAGE_SPANISH_COLOMBIA: case wxLANGUAGE_SPANISH_COSTA_RICA: case wxLANGUAGE_SPANISH_DOMINICAN_REPUBLIC: case wxLANGUAGE_SPANISH_ECUADOR: case wxLANGUAGE_SPANISH_EL_SALVADOR: case wxLANGUAGE_SPANISH_GUATEMALA: case wxLANGUAGE_SPANISH_HONDURAS: case wxLANGUAGE_SPANISH_MEXICAN: case wxLANGUAGE_SPANISH_MODERN: case wxLANGUAGE_SPANISH_NICARAGUA: case wxLANGUAGE_SPANISH_PANAMA: case wxLANGUAGE_SPANISH_PARAGUAY: case wxLANGUAGE_SPANISH_PERU: case wxLANGUAGE_SPANISH_PUERTO_RICO: case wxLANGUAGE_SPANISH_URUGUAY: case wxLANGUAGE_SPANISH_US: case wxLANGUAGE_SPANISH_VENEZUELA: systemLocale = wxLANGUAGE_SPANISH; break; case wxLANGUAGE_SLOVAK: systemLocale = wxLANGUAGE_SLOVAK; break; case wxLANGUAGE_SWEDISH: systemLocale = wxLANGUAGE_SWEDISH; break; case wxLANGUAGE_FRENCH: systemLocale = wxLANGUAGE_FRENCH; break; case wxLANGUAGE_UKRAINIAN: systemLocale = wxLANGUAGE_UKRAINIAN; break; default: systemLocale = wxLANGUAGE_ENGLISH_US; break; } if (config.get()) { #ifdef __WXMSW__ singleInstanceCheck = config->Read(_T("singleInstanceCheck"), true); #else long longFalse = 0; singleInstanceCheck = config->Read(_T("singleInstanceCheck"), longFalse); #endif lang = config->Read(_T("lang"), systemLocale); } else { lang = systemLocale; #ifdef __WXMSW__ singleInstanceCheck = true; #else singleInstanceCheck = false; #endif } myLocale.Init(lang, wxLOCALE_LOAD_DEFAULT); wxLocale::AddCatalogLookupPathPrefix(wxT(".")); wxLocale::AddCatalogLookupPathPrefix(wxT("..")); #ifdef __LINUX__ wxLocale::AddCatalogLookupPathPrefix(GetLinuxAppDir::run()); #endif myLocale.AddCatalog(_T("messages")); #ifdef __LINUX__ { wxLogNull noLog; myLocale.AddCatalog(_T("fileutils")); } #endif } MyApp::~MyApp() { delete checker; delete server; delete connection; } bool MyApp::OnInit() { wxString name, service, hostName; name.Printf(_T("xmlcopyeditor-%s"), wxGetUserId().c_str()); service = IPC_SERVICE; hostName = _T("localhost"); if (singleInstanceCheck) { checker = new wxSingleInstanceChecker(name); while (checker->IsAnotherRunning()) { // attempt calling server client = new MyClient(); connection = (MyClientConnection *) client->MakeConnection(hostName, service, IPC_TOPIC); if (!connection || !connection->StartAdvise(IPC_ADVISE_NAME)) break; else { wxString argument; if (this->argc > 1) { for (int i = 1; i < this->argc; i++) { argument = (wxString)this->argv[i]; argument = PathResolver::run(argument); connection->Poke(argument, _T("Data")); } } else { argument = (wxString)IPC_NO_FILE; connection->Poke(argument, _T("Data")); } return false; } } } server = new MyServer; server->Create(service); MyFrame *frame; try { wxImage::AddHandler(new wxPNGHandler); wxSystemOptions::SetOption(_T("msw.remap"), 0); frame = new MyFrame( _("XML Copy Editor"), config.get(), myLocale, singleInstanceCheck, lang); frame->Show(true); if (frame->getHandleCommandLineFlag()) frame->handleCommandLine(); } catch (exception &e) { const char *what; what = e.what(); wxString wideWhat, errorString; wideWhat = wxString(what, wxConvLocal, strlen(what)); if (wideWhat.empty()) wideWhat = _("(unknown error)"); errorString = _("XML Copy Editor has encountered the following error and needs to close: "); errorString += wideWhat; errorString += _T("."); #ifdef __WXMSW__ ::MessageBox( NULL, errorString, _("Error"), MB_ICONERROR | MB_TASKMODAL); #else wxMessageBox(errorString, _("Error"), wxICON_ERROR); #endif exit(EXIT_FAILURE); } catch (...) { exit(EXIT_FAILURE); } return true; } void MyApp::OnUnhandledException() { #ifdef __WXMSW__ ::MessageBox( NULL, _("XML Copy Editor has encountered an error and needs to close."), _("Error"), MB_ICONERROR | MB_TASKMODAL); #else wxMessageBox( _("XML Copy Editor has encountered an error and needs to close."), _("Error"), wxICON_ERROR); #endif exit(EXIT_FAILURE); } bool MyApp::OnExceptionInMainLoop() { try { throw; } #ifdef __WXMSW__ catch (bad_alloc&) { ::MessageBox( NULL, _("The operating system has turned down a request for additional memory"), _("Out of memory"), MB_ICONERROR); return true; } #endif catch (exception &e) { const char *what; what = e.what(); wxString wideWhat, errorString; wideWhat = wxString(what, wxConvLocal, strlen(what)); if (wideWhat.empty()) _("(unknown error)"); errorString = _("The following error has occurred: "); errorString += wideWhat; errorString += _(".\n\nSelect \"Abort\" to exit, \"Retry\" to close this window and \"Ignore\" to continue."); #ifdef __WXMSW__ int ret = ::MessageBox( NULL, errorString, _("Error"), MB_ABORTRETRYIGNORE | MB_ICONERROR | MB_TASKMODAL); switch (ret) { case IDABORT: exit(EXIT_FAILURE); break; case IDRETRY: return false; case IDIGNORE: return true; default: throw; } #else // wxGTK does not reach this point; see HandleEvent below wxMessageBox( errorString, _("Error"), wxICON_ERROR); return false; #endif } catch (...) { wxString otherError(_("XML Copy Editor has encountered an error and needs to close.")); #ifdef __WXMSW__ ::MessageBox( NULL, otherError, _("Error"), MB_ICONERROR); return false; #else wxMessageBox( otherError, _("Error"), wxICON_ERROR); return false; #endif } return false; } #ifndef __WXMSW__ void MyApp::HandleEvent(wxEvtHandler *handler, wxEventFunction func, wxEvent& event) const { try { wxApp::HandleEvent(handler, func, event); } catch (std::bad_alloc&) { wxMessageBox( _("The operating system has turned down a request for additional memory"), _("Out of memory"), wxICON_ERROR); return; } catch (std::exception& e) { std::string s(e.what()); wxString ws = wxString(s.c_str(), wxConvUTF8, s.size()); wxMessageBox( ws, _("Error"), wxICON_ERROR); return; } catch (...) { throw; } } #endif MyFrame::MyFrame( const wxString& title, wxConfig *configParameter, wxLocale& locale, bool singleInstanceCheckParameter, int langParameter) : wxFrame(NULL, wxID_ANY, title), config(configParameter), myLocale(locale), singleInstanceCheck(singleInstanceCheckParameter), lang(langParameter), htmlPrinting(new wxHtmlEasyPrinting( wxEmptyString, this)), findDialog(0), #ifndef __WXMSW__ helpController(new wxHtmlHelpController()), #endif menuBar(0), toolBar(0), xmlMenu(0), mainBook(0), restoreFocusToNotebook(false) { manager.SetManagedWindow(this); lastPos = 0; htmlReport = NULL; lastDoc = NULL; wxString defaultFont = #ifdef __WXMSW__ _T("Arial"); #else _T("Bitstream Vera Sans"); #endif #ifdef __WXMSW__ coolBar = NULL; #endif bool findMatchCase; // fetch configuration if (config) // config found { history.Load(*config); properties.insertCloseTag = config->Read(_T("insertCloseTag"), true); properties.completion = config->Read(_T("completion"), true); properties.number = config->Read(_T("number"), true); properties.fold = config->Read(_T("fold"), true); properties.currentLine = config->Read(_T("currentLine"), true); properties.highlightSyntax = config->Read(_T("highlightSyntax"), true); properties.whitespaceVisible = config->Read(_T("whitespaceVisible"), true); properties.indentLines = config->Read(_T("indentLines"), true); properties.toggleLineBackground = config->Read(_T("toggleLineBackground"), true); properties.protectHiddenElements = config->Read(_T("protectHiddenElements"), true); properties.deleteWholeTag = config->Read(_T("deleteWholeTag"), true); properties.validateAsYouType = config->Read(_T("validateAsYouType"), true); properties.font = config->Read(_T("font"), defaultFont); findRegex = config->Read(_T("findRegex"), true); xpathExpression = config->Read(_T("xpathExpression"), wxEmptyString); lastXslStylesheet = config->Read(_T("lastXslStylesheet"), wxEmptyString); lastRelaxNGSchema = config->Read(_T("lastRelaxNGSchema"), wxEmptyString); lastXslStylesheet.Replace(_T(" "), _T("%20"), true); lastRelaxNGSchema.Replace(_T(" "), _T("%20"), true); applicationDir = config->Read(_T("applicationDir"), wxEmptyString); if (applicationDir.empty()) { #ifdef __WXMSW__ applicationDir = config->Read(_T("InstallPath"), wxGetCwd()); #else applicationDir = GetLinuxAppDir::run(); #endif } browserCommand = config->Read(_T("browserCommand"), wxEmptyString); // if default value != true, type as long int long valZoom, longFalse; longFalse = false; valZoom = 0; frameWidth = frameHeight = framePosX = framePosY = 0; properties.wrap = config->Read(_T("wrap"), longFalse); properties.zoom = config->Read(_T("zoom"), valZoom); properties.colorScheme = config->Read(_T("colorScheme"), COLOR_SCHEME_DEFAULT); globalReplaceAllDocuments = config->Read(_T("globalReplaceAllDocuments"), longFalse); showFullPathOnFrame = config->Read(_T("showFullPathOnFrame"), longFalse); findMatchCase = config->Read(_T("findMatchCase"), longFalse); commandSync = config->Read(_T("commandSync"), longFalse); commandOutput = config->Read(_T("commandOutput"), ID_COMMAND_OUTPUT_IGNORE); commandString = config->Read(_T("commandString"), wxEmptyString); ruleSetPreset = config->Read(_T("ruleSetPreset"), _("Default dictionary and style")); filterPreset = config->Read(_T("filterPreset"), _("(No filter)")); findData.SetFindString(config->Read(_T("findReplaceFind"), _T(""))); findData.SetReplaceString(config->Read(_T("findReplaceReplace"), _T(""))); toolbarVisible = config->Read(_T("toolbarVisible"), true); protectTags = config->Read(_T("protectTags"), longFalse); visibilityState = config->Read(_T("visibilityState"), ID_SHOW_TAGS); framePosX = config->Read(_T("framePosX"), framePosX); framePosY = config->Read(_T("framePosY"), framePosY); frameWidth = config->Read(_T("frameWidth"), frameWidth); frameHeight = config->Read(_T("frameHeight"), frameHeight); rememberOpenTabs = config->Read(_T("rememberOpenTabs"), true); libxmlNetAccess = config->Read(_T("libxmlNetAccess"), longFalse); openTabsOnClose = config->Read(_T("openTabsOnClose"), _T("")); notebookStyle = config->Read(_T("notebookStyle"), ID_NOTEBOOK_STYLE_VC8_COLOR); saveBom = config->Read(_T("saveBom"), true); unlimitedUndo = config->Read(_T("unlimitedUndo"), true); layout = config->Read(_T("layout"), wxEmptyString); restoreLayout = config->Read(_T("restoreLayout"), true); showLocationPane = config->Read(_T("showLocationPane"), true); showInsertChildPane = config->Read(_T("showInsertChildPane"), true); showInsertSiblingPane = config->Read(_T("showInsertSiblingPane"), true); showInsertEntityPane = config->Read(_T("showInsertEntityPane"), true); expandInternalEntities = config->Read(_T("expandInternalEntities"), true); #ifdef __WXMSW__ useCoolBar = config->Read(_T("useCoolBar"), true); #endif } else // config not found { properties.insertCloseTag = properties.completion = properties.currentLine = properties.indentLines = properties.protectHiddenElements = properties.toggleLineBackground = properties.deleteWholeTag = properties.highlightSyntax = true; properties.font = defaultFont; properties.wrap = properties.whitespaceVisible = false; properties.zoom = 0; properties.colorScheme = COLOR_SCHEME_DEFAULT; #ifdef __WXMSW__ applicationDir = wxGetCwd(); #else applicationDir = GetLinuxAppDir::run();//getLinuxApplicationDir(); #endif ruleSetPreset = _("Default dictionary and style"); filterPreset = _("No filter"); xpathExpression = lastXslStylesheet = lastRelaxNGSchema = wxEmptyString; findRegex = true; findMatchCase = globalReplaceAllDocuments = showFullPathOnFrame = false; toolbarVisible = true; protectTags = false; visibilityState = SHOW_TAGS; framePosX = framePosY = frameWidth = frameHeight = 0; rememberOpenTabs = true; libxmlNetAccess = false; openTabsOnClose = wxEmptyString; browserCommand = wxEmptyString; notebookStyle = ID_NOTEBOOK_STYLE_VC8_COLOR; saveBom = unlimitedUndo = true; layout = wxEmptyString; restoreLayout = true; showLocationPane = true; showInsertChildPane = true; showInsertSiblingPane = true; showInsertEntityPane = true; expandInternalEntities = true; properties.validateAsYouType = true; commandSync = false; commandOutput = ID_COMMAND_OUTPUT_IGNORE; commandString = wxEmptyString; #ifdef __WXMSW__ useCoolBar = true; #endif } largeFileProperties.completion = false; largeFileProperties.fold = false; largeFileProperties.whitespaceVisible = false; largeFileProperties.wrap = false; largeFileProperties.indentLines = false; largeFileProperties.protectHiddenElements = false; largeFileProperties.toggleLineBackground = false; largeFileProperties.toggleLineBackground = false; largeFileProperties.insertCloseTag = false; largeFileProperties.deleteWholeTag = false; largeFileProperties.highlightSyntax = false; largeFileProperties.validateAsYouType = false; largeFileProperties.number = properties.number; largeFileProperties.currentLine = properties.currentLine; largeFileProperties.font = properties.font; largeFileProperties.zoom = 0; largeFileProperties.colorScheme = COLOR_SCHEME_NONE; updatePaths(); loadBitmaps(); size_t findFlags = 0; findFlags |= wxFR_DOWN; if (findMatchCase) findFlags |= wxFR_MATCHCASE; findData.SetFlags(findFlags); if (browserCommand.empty()) { #ifdef __WXMSW__ browserCommand = binDir + _T("navigate.exe"); #else browserCommand = getLinuxBrowser(); #endif } // initialise document count for tab labels documentCount = 1; SetIcon(wxICON(appicon)); CreateStatusBar(); wxStatusBar *status = GetStatusBar(); int widths[] = { -24, -6, -6, -6, -8 }; status->SetFieldsCount(5); status->SetStatusWidths(5, widths); if (!frameWidth || !frameHeight || frameWidth < 0 || frameHeight < 0 || framePosX < 0 || framePosY < 0) { #ifdef __WXMSW__ Maximize(); #else SetSize(50, 50, 640, 480); #endif } else { SetSize(framePosX, framePosY, frameWidth, frameHeight); } stylePosition = aboutPosition = wxDefaultPosition; styleSize = wxSize(720, 540); #ifdef __WXMSW__ useCoolBarOnStart = useCoolBar; #endif showTopBars(toolbarVisible); long style = wxAUI_NB_TOP | wxAUI_NB_TAB_SPLIT | wxAUI_NB_TAB_MOVE | wxAUI_NB_WINDOWLIST_BUTTON | wxAUI_NB_CLOSE_ON_ALL_TABS | wxNO_BORDER; mainBook = new MyNotebook( this, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize, style); manager.AddPane(mainBook, wxAuiPaneInfo().CenterPane() .PaneBorder(false).Name(_T("documentPane"))); manager.GetPane(mainBook).dock_proportion = 10; // add insert child panes locationPanel = new LocationPanel(this, ID_LOCATION_PANEL); insertChildPanel = new InsertPanel(this, ID_INSERT_CHILD_PANEL, INSERT_PANEL_TYPE_CHILD); insertSiblingPanel = new InsertPanel(this, ID_INSERT_SIBLING_PANEL, INSERT_PANEL_TYPE_SIBLING); insertEntityPanel = new InsertPanel(this, ID_INSERT_ENTITY_PANEL, INSERT_PANEL_TYPE_ENTITY); #ifdef __WXMSW__ manager.AddPane((wxWindow *)locationPanel, wxRIGHT, _("Current Element")); manager.AddPane((wxWindow *)insertChildPanel, wxRIGHT, _("Insert Element")); manager.AddPane((wxWindow *)insertSiblingPanel, wxRIGHT, _("Insert Sibling")); manager.AddPane((wxWindow *)insertEntityPanel, wxRIGHT, _("Insert Entity")); #else manager.AddPane((wxWindow *)insertEntityPanel, wxRIGHT, _("Insert Entity")); manager.AddPane((wxWindow *)insertSiblingPanel, wxRIGHT, _("Insert Sibling")); manager.AddPane((wxWindow *)insertChildPanel, wxRIGHT, _("Insert Element")); manager.AddPane((wxWindow *)locationPanel, wxRIGHT, _("Current Element")); #endif manager.GetPane(locationPanel).Name(_T("locationPane")).Show( (restoreLayout) ? showLocationPane : true).DestroyOnClose(false).PinButton(true); manager.GetPane(locationPanel).dock_proportion = 1; manager.GetPane(insertChildPanel).Name(_T("insertChildPane")).Show( (restoreLayout) ? showInsertChildPane : true).DestroyOnClose(false).PinButton(true); manager.GetPane(insertChildPanel).dock_proportion = 1; manager.GetPane(insertSiblingPanel).Name(_T("insertSiblingPane")).Show( (restoreLayout) ? showInsertSiblingPane : true).DestroyOnClose(false).PinButton(true); manager.GetPane(insertSiblingPanel).dock_proportion = 1; manager.GetPane(insertEntityPanel).Name(_T("insertEntityPane")).Show( (restoreLayout) ? showInsertEntityPane : true).DestroyOnClose(false).PinButton(true); manager.GetPane(insertEntityPanel).dock_proportion = 1; // add (hidden) message pane htmlReport = new MyHtmlPane( this, ID_VALIDATION_PANE, wxDefaultPosition, wxSize(-1, 48)); #ifndef __WXMSW__ const int sizeArray[] = { 8, 9, 10, 11, 12, 13, 14 }; htmlReport->SetFonts(wxEmptyString, wxEmptyString, sizeArray); #endif htmlReport->SetBorders(0); manager.AddPane(htmlReport, wxAuiPaneInfo().Movable().Bottom() .Hide().Name(_T("messagePane")) .DestroyOnClose(false).Layer(1)); manager.GetPane(htmlReport).dock_proportion = 1; #ifdef NEWFINDREPLACE findReplacePanel = new FindReplacePanel( this, ID_FIND_REPLACE_PANEL, &findData, true, findRegex); manager.AddPane( (wxWindow *)findReplacePanel, wxAuiPaneInfo().Bottom().Hide().Caption(wxEmptyString). DestroyOnClose(false).Layer(2)); #endif commandPanel = new CommandPanel( this, wxID_ANY, commandString, // tbd commandSync, // tbd commandOutput // tbd ); manager.AddPane( (wxWindow *)commandPanel, wxAuiPaneInfo().Bottom().Hide().Caption(_T("Command")).DestroyOnClose(false).Layer(3)); if (!wxFileName::DirExists(applicationDir)) GetStatusBar()->SetStatusText(_("Cannot open application directory: see Tools, Options..., General")); // handle command line and, on Windows, MS Word integration handleCommandLineFlag = (wxTheApp->argc > 1) ? true : false; if (rememberOpenTabs && !openTabsOnClose.empty()) openRememberedTabs(); else { if (!handleCommandLineFlag) newDocument(wxEmptyString); } #ifdef __WXMSW__ DragAcceptFiles(true); // currently Windows only #endif XmlDoc *doc = getActiveDocument(); insertEntityPanel->update(doc); // NULL is ok manager.Update(); /* defaultLayout = manager.SavePerspective(); // restore layout if req'd if (restoreLayout && !layout.empty()) { if (!manager.LoadPerspective(layout, true)) manager.LoadPerspective(defaultLayout, true); } */ } MyFrame::~MyFrame() { std::vector::iterator it; for (it = tempFileVector.begin(); it != tempFileVector.end(); it++) wxRemoveFile(*it); layout = manager.SavePerspective(); if (!config) return; history.Save(*config); config->Write(_T("insertCloseTag"), properties.insertCloseTag); config->Write(_T("completion"), properties.completion); config->Write(_T("number"), properties.number); config->Write(_T("fold"), properties.fold); config->Write(_T("currentLine"), properties.currentLine); config->Write(_T("whitespaceVisible"), properties.whitespaceVisible); config->Write(_T("wrap"), properties.wrap); config->Write(_T("indentLines"), properties.indentLines); config->Write(_T("zoom"), properties.zoom); config->Write(_T("colorScheme"), properties.colorScheme); config->Write(_T("protectHiddenElements"), properties.protectHiddenElements); config->Write(_T("toggleLineBackground"), properties.toggleLineBackground); config->Write(_T("deleteWholeTag"), properties.deleteWholeTag); config->Write(_T("validateAsYouType"), properties.validateAsYouType); config->Write(_T("font"), properties.font); config->Write(_T("highlightSyntax"), properties.highlightSyntax); config->Write(_T("applicationDir"), applicationDir); config->Write(_T("ruleSetPreset"), ruleSetPreset); config->Write(_T("filterPreset"), filterPreset); config->Write(_T("xpathExpression"), xpathExpression); config->Write(_T("findReplaceFind"), findData.GetFindString()); config->Write(_T("findReplaceReplace"), findData.GetReplaceString()); config->Write(_T("globalReplaceAllDocuments"), globalReplaceAllDocuments); config->Write(_T("showFullPathOnFrame"), showFullPathOnFrame); config->Write(_T("toolbarVisible"), toolbarVisible); config->Write(_T("protectTags"), protectTags); config->Write(_T("visibilityState"), visibilityState); config->Write(_T("browserCommand"), browserCommand); config->Write(_T("layout"), layout); config->Write(_T("showLocationPane"), manager.GetPane(locationPanel).IsShown()); config->Write(_T("showInsertChildPane"), manager.GetPane(insertChildPanel).IsShown()); config->Write(_T("showInsertSiblingPane"), manager.GetPane(insertSiblingPanel).IsShown()); config->Write(_T("showInsertEntityPane"), manager.GetPane(insertEntityPanel).IsShown()); config->Write(_T("expandInternalEntities"), expandInternalEntities); config->Write(_T("findRegex"), findReplacePanel->getRegex()); config->Write(_T("findMatchCase"), (findData.GetFlags()) & wxFR_MATCHCASE); config->Write(_T("commandSync"), commandPanel->getSync()); config->Write(_T("commandOutput"), commandPanel->getOutput()); config->Write(_T("commandString"), commandPanel->getCommand()); #ifdef __WXMSW__ config->Write(_T("useCoolBar"), useCoolBar); #endif config->Write(_T("restoreLayout"), restoreLayout); config->Write(_T("lastXslStylesheet"), lastXslStylesheet); config->Write(_T("lastRelaxNGSchema"), lastRelaxNGSchema); GetPosition(&framePosX, &framePosY); config->Write(_T("framePosX"), framePosX); config->Write(_T("framePosY"), framePosY); GetSize(&frameWidth, &frameHeight); config->Write(_T("frameWidth"), frameWidth); config->Write(_T("frameHeight"), frameHeight); config->Write(_T("rememberOpenTabs"), rememberOpenTabs); config->Write(_T("openTabsOnClose"), openTabsOnClose); config->Write(_T("libxmlNetAccess"), libxmlNetAccess); config->Write(_T("singleInstanceCheck"), singleInstanceCheck); config->Write(_T("lang"), lang); config->Write(_T("notebookStyle"), notebookStyle); config->Write(_T("saveBom"), saveBom); config->Write(_T("unlimitedUndo"), unlimitedUndo); manager.UnInit(); } wxString MyFrame::getLinuxBrowser() { wxString s; const int stringArrayLen = 9; wxString stringArray[stringArrayLen]; stringArray[0] = _T("/usr/bin/firefox"); stringArray[1] = _T("/usr/bin/mozilla"); stringArray[2] = _T("/usr/bin/opera"); stringArray[3] = _T("/usr/bin/dillo"); stringArray[4] = _T("/opt/gnome/bin/epiphany"); stringArray[5] = _T("/opt/gnome/bin/galeon"); stringArray[6] = _T("/opt/kde/bin/konqueror"); stringArray[7] = _T("/opt/mozilla/bin/firefox"); stringArray[8] = wxEmptyString; // empty option is safe for (int i = 0; i < stringArrayLen; i++) { s = stringArray[i]; if (wxFileName::FileExists(s)) break; } return s; } void MyFrame::showTopBars(bool b) { #ifdef __WXMSW__ if (useCoolBarOnStart) { if (coolBar) { manager.DetachPane(coolBar); manager.Update(); coolBar->ShowBand(1, b); manager.AddPane(coolBar, wxAuiPaneInfo().Top().CaptionVisible(false).Name(_T("coolBar"))); } else { toolBar = getToolBar(); SetToolBar(NULL); if (toolBar && protectTags) toolBar->ToggleTool(ID_PROTECT_TAGS, protectTags); menuBar = getMenuBar(); coolBar = new wxCoolBar(this, -1); coolBar->AddBand(menuBar, false, wxEmptyString, true); coolBar->AddBand(toolBar, true, wxEmptyString, true); coolBar->ShowBand(1, b); manager.AddPane(coolBar, wxAuiPaneInfo().Top().CaptionVisible(false).Name(_T("coolBar"))); } return; } #endif if (!menuBar) { SetToolBar(NULL); menuBar = getMenuBar(); SetMenuBar(menuBar); } if (b) { if (!toolBar) toolBar = getToolBar(); SetToolBar(toolBar); } else { SetToolBar(NULL); delete toolBar; toolBar = NULL; } } void MyFrame::handleCommandLine() { bool wordFlag, styleFlag; wordFlag = styleFlag = false; wxChar c; int m_argc = wxTheApp->argc; wxChar **m_argv = wxTheApp->argv; while ((--m_argc > 0 && (*++m_argv)[0] == L'-') != 0) { while ((c = *++m_argv[0]) != 0) { switch (c) { case L'w': wordFlag = true; break; case L's': styleFlag = true; break; default: messagePane(_("Unknown command line switch (expecting 'w' or 's')"), CONST_STOP); return; } } } if (!(*m_argv)) { messagePane(_("Command line processing incomplete: no file specified"), CONST_STOP); return; } wxString fileName; // no flags specified or not Windows #ifdef __WXMSW__ if (!styleFlag && !wordFlag) #endif { for (; *m_argv; ++m_argv) { fileName = wxString(*m_argv, wxConvLocal, wcslen(*m_argv)); fileName = PathResolver::run(fileName); if (isOpen(fileName)) continue; else if (!openFile(fileName)) break; } return; } // options only available on Windows fileName = wxString(*m_argv, wxConvLocal, wcslen(*m_argv)); // fetch as many parameters as possible for (;;) { ++m_argv; if (!(*m_argv)) break; ruleSetPreset = wxString(*m_argv, wxConvLocal, wcslen(*m_argv)); ++m_argv; if (!(*m_argv)) break; filterPreset = wxString(*m_argv, wxConvLocal, wcslen(*m_argv)); ++m_argv; if (!(*m_argv)) break; applicationDir = wxString(*m_argv, wxConvLocal, wcslen(*m_argv)); updatePaths(); break; } if (wordFlag) importMSWord(fileName); else openFile(fileName); if (styleFlag && !ruleSetPreset.empty() && !filterPreset.empty()) { wxCommandEvent e; OnSpelling(e); } } bool MyFrame::isOpen(const wxString& fileName) { return (openFileSet.find(fileName) != openFileSet.end()); } void MyFrame::activateTab(const wxString& fileName) { int pageCount = mainBook->GetPageCount(); XmlDoc *currentDoc; for (int i = 0; i < pageCount; ++i) { currentDoc = (XmlDoc *)mainBook->GetPage(i); if (!currentDoc) break; if (currentDoc->getFullFileName() == fileName) { mainBook->SetSelection(i); break; } } } void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) { wxAboutDialogInfo info; info.SetName(_("XML Copy Editor")); info.SetWebSite(_T("http://xml-copy-editor.sourceforge.net")); info.SetVersion(ABOUT_VERSION); info.SetCopyright(ABOUT_COPYRIGHT); info.AddDeveloper(_("Gerald Schmidt (development) ")); info.AddDeveloper(_("Matt Smigielski (testing) ")); info.AddTranslator(_("Viliam Búr (Slovak) ")); info.AddTranslator(_("David Håsäther (Swedish) ")); info.AddTranslator(_("François Badier (French) ")); info.AddTranslator(_("Thomas Wenzel (German) ")); info.AddTranslator(_("SHiNE CsyFeK (Chinese Simplified) ")); info.AddTranslator(_("HSU PICHAN, YANG SHUFUN, CHENG PAULIAN, CHUANG KUO-PING, Marcus Bingenheimer (Chinese Traditional)")); info.AddTranslator(_("Serhij Dubyk ")); info.SetLicense(ABOUT_LICENSE); info.SetDescription(ABOUT_DESCRIPTION); wxAboutBox(info); XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; doc->SetFocus(); } void MyFrame::OnCheckWellformedness(wxCommandEvent& event) { statusProgress(wxEmptyString); XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; std::string utf8Buffer; getRawText(doc, utf8Buffer); if (utf8Buffer.empty()) return; // handle unusual encodings if (!XmlEncodingHandler::setUtf8(utf8Buffer)) { encodingMessage(); return; } doc->clearErrorIndicators(); statusProgress(_("Parse in progress...")); // check for well-formedness auto_ptr we(new WrapExpat()); if (!we->parse(utf8Buffer.c_str())) { std::string error = we->getLastError(); wxString werror = wxString(error.c_str(), wxConvUTF8, error.size()); statusProgress(wxEmptyString); messagePane(werror, CONST_WARNING); std::pair posPair = we->getErrorPosition(); --(posPair.first); int cursorPos = doc->PositionFromLine(posPair.first); doc->SetSelection(cursorPos, cursorPos); doc->setErrorIndicator(posPair.first, posPair.second); return; } statusProgress(wxEmptyString); documentOk(_("well-formed")); } void MyFrame::OnPageClosing(wxAuiNotebookEvent& event)//wxNotebookEvent& event)//wxFlatNotebookEvent& event) { deletePageVetoed = false; if (insertChildPanel && insertSiblingPanel && locationPanel) { insertChildPanel->update(NULL, wxEmptyString); insertSiblingPanel->update(NULL, wxEmptyString); locationPanel->update(); manager.Update(); } XmlDoc *doc; doc = (XmlDoc *)mainBook->GetPage(event.GetSelection()); if (!doc) return; statusProgress(wxEmptyString); closePane(); if (doc->GetModify())//CanUndo()) { int selection; wxString fileName; if ((selection = mainBook->GetSelection()) != -1) fileName = doc->getShortFileName(); int answer = wxMessageBox( _("Do you want to save the changes to ") + fileName + _T("?"), _("XML Copy Editor"), wxYES_NO | wxCANCEL | wxICON_QUESTION, this); if (answer == wxCANCEL) { event.Veto(); deletePageVetoed = true; return; } else if (answer == wxYES) { wxCommandEvent event; OnSave(event); } } statusProgress(wxEmptyString); openFileSet.erase(doc->getFullFileName()); event.Skip(); } void MyFrame::OnClose(wxCommandEvent& WXUNUSED(event)) { closeActiveDocument(); } void MyFrame::OnCloseAll(wxCommandEvent& WXUNUSED(event)) { if (!mainBook) return; openTabsOnClose = wxEmptyString; // retain tab order if (rememberOpenTabs && !openFileSet.empty()) { XmlDoc *doc; wxString fullPath; size_t maxTabs = mainBook->GetPageCount(); for (size_t i = 0; i < maxTabs; ++i) { doc = (XmlDoc *)mainBook->GetPage(i); if (doc) { fullPath = doc->getFullFileName(); if (!fullPath.empty()) { openTabsOnClose.Append(fullPath); openTabsOnClose.Append(_T("|")); } } } } while (closeActiveDocument()) ; } void MyFrame::OnClosePane(wxCommandEvent& WXUNUSED(event)) { closePane(); //closeFindReplacePane(); //closeCommandPane(); XmlDoc *doc = getActiveDocument(); if (doc) doc->SetFocus(); } void MyFrame::closePane() { if (!htmlReport) return; manager.GetPane(htmlReport).Hide(); manager.Update(); XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; doc->SetFocus(); } void MyFrame::closeFindReplacePane() { if (manager.GetPane(findReplacePanel).IsShown()) manager.GetPane(findReplacePanel).Hide(); manager.Update(); } void MyFrame::closeCommandPane() { if (manager.GetPane(commandPanel).IsShown()) manager.GetPane(commandPanel).Hide(); manager.Update(); } bool MyFrame::panelHasFocus() { XmlDoc *doc = getActiveDocument(); return (!doc || (FindFocus() != (wxWindow *)doc)); } void MyFrame::OnCut(wxCommandEvent& event) { if (panelHasFocus()) { event.Skip(); return; } XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; if (protectTags) doc->adjustSelection(); doc->Cut(); doc->setValidationRequired(true); } void MyFrame::OnCopy(wxCommandEvent& event) { if (panelHasFocus()) { event.Skip(); return; } XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; doc->Copy(); } void MyFrame::OnPaste(wxCommandEvent& event) { if (panelHasFocus()) { event.Skip(); return; } XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; // this has to be handled here to override Scintilla's default Ctrl+V support if (protectTags) { if (!wxTheClipboard->Open() || !wxTheClipboard->IsSupported(wxDF_TEXT)) return; wxTextDataObject data; wxTheClipboard->GetData(data); wxString buffer = data.GetText(); xmliseWideTextNode(buffer); doc->adjustCursor(); doc->AddText(buffer); } else doc->Paste(); /* XmlDoc *doc; doc = getActiveDocument(); if (doc && protectTags) doc->adjustCursor(); doc->setValidationRequired(true); event.Skip(); // new */ } void MyFrame::OnIdle(wxIdleEvent& event) { wxStatusBar *status = GetStatusBar(); if (!status) return; // update attributes hidden field even if no document loaded wxString currentHiddenStatus = status->GetStatusText(STATUS_HIDDEN); if (visibilityState == HIDE_ATTRIBUTES) { if (currentHiddenStatus != _("Attributes hidden")) status->SetStatusText( _("Attributes hidden"), STATUS_HIDDEN); } else if (visibilityState == HIDE_TAGS) { if (currentHiddenStatus != _("Tags hidden")) status->SetStatusText( _("Tags hidden"), STATUS_HIDDEN); } else { if (!currentHiddenStatus.empty()) status->SetStatusText(wxEmptyString, STATUS_HIDDEN); } // update protected field even if no document loaded wxString currentProtectedStatus = status->GetStatusText(STATUS_PROTECTED); if (protectTags) { if (currentProtectedStatus != _("Tags locked")) status->SetStatusText( _("Tags locked"), STATUS_PROTECTED); } else { if (!currentProtectedStatus.empty()) status->SetStatusText(wxEmptyString, STATUS_PROTECTED); } // check if document loaded wxString frameTitle = GetTitle(); XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) { if (lastDoc != NULL) { lastDoc = NULL; status->SetStatusText(wxEmptyString, STATUS_MODIFIED); status->SetStatusText(wxEmptyString, STATUS_POSITION); locationPanel->update(NULL, wxEmptyString); insertChildPanel->update(NULL, wxEmptyString); insertSiblingPanel->update(NULL, wxEmptyString); insertEntityPanel->update(NULL, wxEmptyString); wxString minimal = _("XML Copy Editor"); if (frameTitle != minimal) SetTitle(minimal); closeFindReplacePane(); event.Skip(); manager.Update(); } return; } if (restoreFocusToNotebook) { doc->SetFocus(); restoreFocusToNotebook = false; } wxString docTitle; if (doc->getFullFileName().empty() || !showFullPathOnFrame) docTitle = doc->getShortFileName(); else docTitle = doc->getFullFileName(); docTitle += _T(" - "); docTitle += _("XML Copy Editor"); if (frameTitle != docTitle) SetTitle(docTitle); // update modified field if (!mainBook) return; int index = mainBook->GetSelection(); wxString currentModifiedStatus = status->GetStatusText(STATUS_MODIFIED); wxString currentTabLabel = mainBook->GetPageText(index); if (doc->GetModify()) { if (currentModifiedStatus != _("Modified")) { status->SetStatusText(_("Modified"), STATUS_MODIFIED); if (!(currentTabLabel.Mid(0, 1) == _T("*"))) { currentTabLabel.Prepend(_T("*")); mainBook->SetPageText(index, currentTabLabel); } } } else { if (!currentModifiedStatus.empty()) { status->SetStatusText(_T(""), STATUS_MODIFIED); if (currentTabLabel.Mid(0, 1) == _T("*")) { currentTabLabel.Remove(0, 1); mainBook->SetPageText(index, currentTabLabel); } } } // update coordinates field std::pair myControlCoordinates; int current = doc->GetCurrentPos(); myControlCoordinates.first = doc->LineFromPosition(current) + 1; myControlCoordinates.second = doc->GetColumn(current) + 1; if (myControlCoordinates != controlCoordinates) { wxString coordinates; coordinates.Printf( _("Ln %i Col %i"), myControlCoordinates.first, myControlCoordinates.second); GetStatusBar()->SetStatusText(coordinates, STATUS_POSITION); controlCoordinates = myControlCoordinates; } // update parent element field wxString parent, grandparent; if (current == lastPos && doc == lastDoc) return; lastPos = current; lastDoc = doc; // don't try to find parent if pane is not shown if (!manager.GetPane(insertChildPanel).IsShown() && !properties.validateAsYouType) return; int parentCloseAngleBracket = -1; if (!doc->canInsertAt(current)) parent = grandparent = wxEmptyString; else { parentCloseAngleBracket = doc->getParentCloseAngleBracket(current); parent = doc->getLastElementName(parentCloseAngleBracket); } if (!parent.empty() && properties.validateAsYouType && doc->getValidationRequired()) { // tbd: limit to parent element doc->shallowValidate(doc->LineFromPosition(current), true); } if (parent == lastParent) return; lastParent = parent; bool mustUpdate = false; if (locationPanel && insertChildPanel && insertEntityPanel) { locationPanel->update(doc, parent); insertChildPanel->update(doc, parent); insertEntityPanel->update(doc); mustUpdate = true; } if (parent.empty()) { if (insertSiblingPanel) insertSiblingPanel->update(doc, wxEmptyString); if (mustUpdate) manager.Update(); return; } if (!manager.GetPane(insertSiblingPanel).IsShown()) { if (mustUpdate) manager.Update(); return; } // try to fetch grandparent if necessary/possible if (!parent.empty() && parentCloseAngleBracket != -1) { int grandParentCloseAngleBracket; grandParentCloseAngleBracket = doc->getParentCloseAngleBracket( doc->getTagStartPos(parentCloseAngleBracket)); grandparent = doc->getLastElementName(grandParentCloseAngleBracket); if (insertSiblingPanel) insertSiblingPanel->update(doc, parent, grandparent); if (grandparent != lastGrandparent) { mustUpdate = true; lastGrandparent = grandparent; } } if (mustUpdate) manager.Update(); } void MyFrame::OnInsertChild(wxCommandEvent& event) { if (!insertChildPanel) return; wxAuiPaneInfo info = manager.GetPane(insertChildPanel); if (!info.IsOk()) { return; } if (!info.IsShown()) { manager.GetPane(insertChildPanel).Show(true); manager.Update(); } insertChildPanel->setEditFocus(); } void MyFrame::OnInsertSibling(wxCommandEvent& event) { if (!insertSiblingPanel) return; wxAuiPaneInfo info = manager.GetPane(insertSiblingPanel); if (!info.IsOk()) { return; } if (!info.IsShown()) { manager.GetPane(insertSiblingPanel).Show(true); manager.Update(); } insertSiblingPanel->setEditFocus(); } void MyFrame::OnInsertEntity(wxCommandEvent& event) { if (!insertEntityPanel) return; wxAuiPaneInfo info = manager.GetPane(insertEntityPanel); if (!info.IsOk()) { return; } if (!info.IsShown()) { manager.GetPane(insertEntityPanel).Show(true); manager.Update(); } insertEntityPanel->setEditFocus(); } void MyFrame::OnInsertSymbol(wxCommandEvent& event) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; wxSymbolPickerDialog dlg(_T("*"), wxEmptyString, properties.font, this); if (dlg.ShowModal() == wxID_OK) { if (dlg.HasSelection()) { doc->AddText(dlg.GetSymbol()); } } } void MyFrame::OnInsertTwin(wxCommandEvent& event) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; wxString parent = doc->getParent(); if (!doc->insertSibling(parent, parent)) { wxString msg; msg.Printf(_T("Cannot insert twin '%s'"), parent.c_str()); messagePane(msg, CONST_STOP); } doc->setValidationRequired(true); doc->SetFocus(); } void MyFrame::OnPasteNewDocument(wxCommandEvent& event) { if (!wxTheClipboard->Open()) { messagePane(_("Cannot open clipboard"), CONST_STOP); return; } if (!wxTheClipboard->IsSupported(wxDF_TEXT)) { messagePane(_("Cannot paste as new document: no text on clipboard"), CONST_STOP); return; } wxTextDataObject data; wxTheClipboard->GetData(data); wxString buffer = data.GetText(); xmliseWideTextNode(buffer); buffer.Prepend(_T("\n")); buffer.Append(_T("\n")); newDocument(buffer); } void MyFrame::OnDialogFind(wxFindDialogEvent& event) { findAgain(event.GetFindString(), event.GetFlags()); } void MyFrame::OnDialogReplace(wxFindDialogEvent& event) { statusProgress(wxEmptyString); XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; int regexWidth = 0; if (findReplacePanel->getRegex()) { regexWidth = doc->ReplaceTargetRE(event.GetReplaceString()); //doc->SetTargetStart(newLocation + regexWidth); } else { doc->ReplaceTarget(event.GetReplaceString()); //doc->SetTargetStart(newLocation + event.GetReplaceString().size()); } /* if (doc->GetSelectionStart() != doc->GetSelectionEnd()) doc->ReplaceSelection(event.GetReplaceString()); */ OnDialogFind(event); } void MyFrame::OnDialogReplaceAll(wxFindDialogEvent& event) { statusProgress(wxEmptyString); XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; int flags = 0; if (event.GetFlags() & wxFR_WHOLEWORD) flags |= wxSTC_FIND_WHOLEWORD; if (event.GetFlags() & wxFR_MATCHCASE) flags |= wxSTC_FIND_MATCHCASE; if (findReplacePanel->getRegex()) flags |= wxSTC_FIND_REGEXP; doc->SetTargetStart(0); doc->SetTargetEnd(doc->GetLength()); doc->SetSearchFlags(flags); int newLocation, replacementCount, regexWidth; newLocation = replacementCount = regexWidth = 0; while ((newLocation = doc->SearchInTarget(event.GetFindString())) != -1) { if (findReplacePanel->getRegex()) { regexWidth = doc->ReplaceTargetRE(event.GetReplaceString()); doc->SetTargetStart(newLocation + regexWidth); } else { doc->ReplaceTarget(event.GetReplaceString()); doc->SetTargetStart(newLocation + event.GetReplaceString().size()); } doc->SetTargetEnd(doc->GetLength()); ++replacementCount; } wxString msg; msg.Printf( ngettext(L"%i replacement made", L"%i replacements made", replacementCount), replacementCount); statusProgress(msg); } void MyFrame::OnPrintSetup(wxCommandEvent &WXUNUSED(event)) { if (!htmlPrinting.get()) return; htmlPrinting->PageSetup(); } void MyFrame::OnPrintPreview(wxCommandEvent &WXUNUSED(event)) { XmlDoc *doc; if (!htmlPrinting.get() || (doc = getActiveDocument()) == NULL) return; wxString shortFileName, header; shortFileName = doc->getShortFileName(); if (!shortFileName.empty()) header = shortFileName + _T(" "); header += _T("(@PAGENUM@/@PAGESCNT@)
"); htmlPrinting->SetHeader( header, wxPAGE_ALL); statusProgress(_("Preparing Print Preview...")); wxString htmlBuffer = getHtmlBuffer(); statusProgress(wxEmptyString); if (!(htmlPrinting->PreviewText(htmlBuffer))) ; } void MyFrame::OnPrint(wxCommandEvent &WXUNUSED(event)) { XmlDoc *doc; if (!htmlPrinting.get() || (doc = getActiveDocument()) == NULL) return; wxString shortFileName, header; shortFileName = doc->getShortFileName(); if (!shortFileName.empty()) header = shortFileName + _T(" "); header += _T("(@PAGENUM@/@PAGESCNT@)
"); htmlPrinting->SetHeader( header, wxPAGE_ALL); statusProgress(_("Preparing to print...")); wxString htmlBuffer = getHtmlBuffer(); statusProgress(wxEmptyString); if (!(htmlPrinting->PrintText(htmlBuffer))) ; } wxString MyFrame::getHtmlBuffer() { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return _T(""); wxString buffer, htmlBuffer; buffer = doc->GetText(); size_t size = buffer.size(); htmlBuffer.reserve(size * 2); htmlBuffer = _T("

"); bool startOfLine = true; for (size_t i = 0; i < size; ++i) { wchar_t c = buffer[i]; switch (c) { case L' ': htmlBuffer += (startOfLine) ? _T(" ") : _T(" "); break; case L'\t': htmlBuffer += _T("  "); break; case L'<': htmlBuffer += _T("<"); startOfLine = false; break; case L'>': htmlBuffer += _T(">"); startOfLine = false; break; case L'\n': htmlBuffer += _T("
"); startOfLine = true; break; case L'&': htmlBuffer + _T("&"); startOfLine = false; break; default: htmlBuffer += c; startOfLine = false; break; } } htmlBuffer += _T("

"); return htmlBuffer; } void MyFrame::OnFind(wxCommandEvent& WXUNUSED(event)) { #ifdef NEWFINDREPLACE manager.GetPane(findReplacePanel).Caption(_("Find")); bool visible = manager.GetPane(findReplacePanel).IsShown(); if (!visible) { manager.GetPane(findReplacePanel).Show(); } manager.Update(); findReplacePanel->refresh(); findReplacePanel->setReplaceVisible(false); findReplacePanel->focusOnFind(); return; #endif if (findDialog.get()) { findDialog = std::auto_ptr(0); } findDialog = (std::auto_ptr(new wxFindReplaceDialog( this, &findData, _("Find")))); findDialog->Show(); } void MyFrame::OnImportMSWord(wxCommandEvent& event) { #ifndef __WXMSW__ messagePane(_("This functionality requires Microsoft Windows")); return; #endif std::auto_ptr fd(new wxFileDialog( this, _("Import Microsoft Word Document"), _T(""), _T(""), _T("Microsoft Word (*.doc)|*.doc"), wxOPEN | wxFILE_MUST_EXIST | wxCHANGE_DIR /* #ifdef __WXMSW__ | wxHIDE_READONLY #endif */ )); if (fd->ShowModal() == wxID_CANCEL) return; wxString path = fd->GetPath(); if (path == _T("")) return; importMSWord(path); } void MyFrame::importMSWord(const wxString& path) { #ifndef __WXMSW__ messagePane(_("This functionality requires Microsoft Windows")); return; #endif WrapTempFileName tempFileName(_T("")), swapFileName(_T("")); wxString completeSwapFileName = swapFileName.wideName() + _T(".doc"); if (!wxCopyFile(path, completeSwapFileName, true)) { wxString message; message.Printf(_("Cannot open %s for import"), path.c_str()); messagePane(message, CONST_STOP); return; } wxString cmd = binDir + _T("doc2xml.exe \"") + completeSwapFileName + _T("\" \"") + tempFileName.wideName() + _T("\""); statusProgress(_("Import in progress...")); int result = wxExecute(cmd, wxEXEC_SYNC); wxRemoveFile(completeSwapFileName); // necessary because .doc extension added statusProgress(wxEmptyString); wxString message; wxString versionMessage( _("(lossless conversion requires version 2003 or later)")); switch (result) { case 0: break; case 1: messagePane(_("Cannot start Microsoft Word"), CONST_STOP); return; case 2: messagePane( _("A more recent version of Microsoft Word is required"), CONST_STOP); return; case 3: message.Printf(_T("Microsoft Word cannot open %s"), path.c_str()); messagePane(message + path, CONST_STOP); return; case 4: message.Printf(_("Microsoft Word cannot save %s as XML"), path.c_str()); messagePane(message, CONST_STOP); return; case 5: messagePane( _("Microsoft Word cannot save this document as WordprocessingML ") + versionMessage, CONST_INFO); break; default: break; } statusProgress(_("Opening imported file...")); std::string buffer; wxString displayBuffer; if (result != 5) // Word 2003 or later { std::auto_ptr prettyPrinter(new WrapLibxml(libxmlNetAccess)); prettyPrinter->parse(tempFileName.name(), true); buffer = prettyPrinter->getOutput(); displayBuffer = wxString(buffer.c_str(), wxConvUTF8, buffer.size()); } else // earlier versions { if (!ReadFile::run(tempFileName.name(), buffer)) { statusProgress(wxEmptyString); messagePane(_("Cannot open imported file"), CONST_STOP); return; } displayBuffer = wxString(buffer.c_str(), wxConvUTF8, buffer.size()); displayBuffer.Remove(0, 1); // remove byte order mark xmliseWideTextNode(displayBuffer); displayBuffer.Prepend( _T("\n")); displayBuffer.Append(_T("\n")); } newDocument(displayBuffer, tempFileName.wideName()); statusProgress(wxEmptyString); } void MyFrame::OnExportMSWord(wxCommandEvent& event) { #ifndef __WXMSW__ messagePane(_("This functionality requires Microsoft Windows")); return; #endif statusProgress(wxEmptyString); // fetch document contents XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; WrapTempFileName wtfn(_T("")); wxString sourceFileName = doc->getFullFileName(); if (sourceFileName.empty()) { sourceFileName = wtfn.wideName(); std::fstream ofs(wtfn.name().c_str()); if (!ofs) return; std::string utf8Buffer; getRawText(doc, utf8Buffer); ofs << utf8Buffer; ofs.close(); } else if (doc->GetModify())//CanUndo()) { modifiedMessage(); return; } std::auto_ptr fd(new wxFileDialog( this, _("Export Microsoft Word Document"), _T(""), _T(""), _T("Microsoft Word (*.doc)|*.doc"), wxSAVE | wxOVERWRITE_PROMPT)); fd->ShowModal(); wxString path = fd->GetPath(); if (path == _T("")) return; wxString cmd = binDir + _T("xml2doc.exe -v \"") + sourceFileName + _T("\" \"") + path + _T("\""); statusProgress(_("Export in progress...")); int result = wxExecute(cmd, wxEXEC_SYNC); statusProgress(wxEmptyString); wxString message; switch (result) { case 1: messagePane(_("Cannot start Microsoft Word"), CONST_STOP); return; case 2: messagePane( _("A more recent version of Microsoft Word is required"), CONST_STOP); return; case 3: message.Printf(_("Microsoft Word cannot save %s"), path.c_str()); messagePane(message, CONST_STOP); return; case 0: break; default: break; } } void MyFrame::OnBrowser(wxCommandEvent& WXUNUSED(event)) { statusProgress(wxEmptyString); // fetch document contents XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; wxString sourceFileName = doc->getFullFileName(); WrapTempFileName wtfn(sourceFileName, _T(".html")); if (sourceFileName.empty() || doc->GetModify()) { sourceFileName = wtfn.wideName(); std::ofstream ofs((const char *)wtfn.name().c_str()); if (!ofs) { messagePane(_("Cannot save temporary file"), CONST_STOP); return; } std::string utf8Buffer; getRawText(doc, utf8Buffer); ofs << utf8Buffer; ofs.close(); // keep files until application closes tempFileVector.push_back(sourceFileName); tempFileVector.push_back(wtfn.originalWideName()); wtfn.setKeepFiles(true); } navigate(sourceFileName); } void MyFrame::OnHelp(wxCommandEvent& event) { #ifdef __WXMSW__ wxString cmd = _T("hh.exe \"") + helpDir + _T("xmlcopyeditor.chm\""); wxExecute(cmd); #else wxString helpFileName = helpDir + _T("xmlcopyeditor.hhp"); helpController->AddBook(wxFileName(helpFileName)); helpController->DisplayContents(); #endif } void MyFrame::OnColorScheme(wxCommandEvent& event) { int id = event.GetId(); switch (id) { case ID_COLOR_SCHEME_DEFAULT: properties.colorScheme = COLOR_SCHEME_DEFAULT; break; case ID_COLOR_SCHEME_DEFAULT_BACKGROUND: properties.colorScheme = COLOR_SCHEME_DEFAULT_BACKGROUND; break; case ID_COLOR_SCHEME_REDUCED_GLARE: properties.colorScheme = COLOR_SCHEME_REDUCED_GLARE; break; case ID_COLOR_SCHEME_NONE: properties.colorScheme = COLOR_SCHEME_NONE; break; default: return; } colorSchemeMenu->Check(id, true); XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; properties.zoom = doc->GetZoom(); // ensure temp changes to font size are kept applyEditorProperties(false); doc->SetFocus(); } void MyFrame::OnFontSmaller(wxCommandEvent& event) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; doc->ZoomOut(); properties.zoom = doc->GetZoom(); applyEditorProperties(true); doc->SetFocus(); } void MyFrame::OnFontMedium(wxCommandEvent& event) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; doc->SetZoom(0); properties.zoom = doc->GetZoom(); applyEditorProperties(true); doc->SetFocus(); } void MyFrame::OnFontLarger(wxCommandEvent& event) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; doc->ZoomIn(); properties.zoom = doc->GetZoom(); applyEditorProperties(true); doc->SetFocus(); } void MyFrame::OnOptions(wxCommandEvent& WXUNUSED(event)) { // ensure font size does not change after XmlDoc *doc = getActiveDocument(); if (doc) { properties.zoom = doc->GetZoom(); } wxString title(_("Options")); std::auto_ptr mpsd(new MyPropertySheet( this, properties, applicationDir, browserCommand, rememberOpenTabs, libxmlNetAccess, singleInstanceCheck, saveBom, unlimitedUndo, restoreLayout, expandInternalEntities, showFullPathOnFrame, lang, #ifdef __WXMSW__ useCoolBar, #endif wxID_ANY, title)); if (mpsd->ShowModal() == wxID_OK) { properties = mpsd->getProperties(); applyEditorProperties(); applicationDir = mpsd->getApplicationDir(); browserCommand = mpsd->getBrowserCommand(); rememberOpenTabs = mpsd->getRememberOpenTabs(); libxmlNetAccess = mpsd->getLibxmlNetAccess(); singleInstanceCheck = mpsd->getSingleInstanceCheck(); saveBom = mpsd->getSaveBom(); unlimitedUndo = mpsd->getUnlimitedUndo(); restoreLayout = mpsd->getRestoreLayout(); expandInternalEntities = mpsd->getExpandInternalEntities(); showFullPathOnFrame = mpsd->getShowFullPathOnFrame(); lang = mpsd->getLang(); #ifdef __WXMSW__ useCoolBar = mpsd->getUseCoolBar(); #endif updatePaths(); } if (doc) doc->SetFocus(); } void MyFrame::OnHistoryFile(wxCommandEvent& event) { wxString f(history.GetHistoryFile(event.GetId() - wxID_FILE1)); if (!f.empty()) openFile(f); } void MyFrame::OnGoto(wxCommandEvent& WXUNUSED(event)) { statusProgress(wxEmptyString); XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; wxTextEntryDialog *dlg = new wxTextEntryDialog( this, _("Enter line number:"), _("Go To")); int ret = dlg->ShowModal(); if (ret == wxID_CANCEL) return; wxString val = dlg->GetValue(); long line; if (!val.ToLong(&line) || line < 1) { wxString msg; msg.Printf(_("'%s' is not a valid line number"), val.c_str()); messagePane(msg, CONST_STOP); return; } --line; doc->GotoLine((int)line); doc->SetFocus(); } void MyFrame::OnFindAgain(wxCommandEvent& event) { //findAgain(findData.GetFindString(), findData.GetFlags()); findReplacePanel->OnFindNext(event); } void MyFrame::OnCommand(wxCommandEvent& WXUNUSED(event)) { bool visible = manager.GetPane(commandPanel).IsShown(); if (!visible) { manager.GetPane(commandPanel).Show(); } manager.Update(); commandPanel->focusOnCommand(); } void MyFrame::OnFindReplace(wxCommandEvent& WXUNUSED(event)) { #ifdef NEWFINDREPLACE manager.GetPane(findReplacePanel).Caption(_("Replace")); bool visible = manager.GetPane(findReplacePanel).IsShown(); if (!visible) { manager.GetPane(findReplacePanel).Show(); } manager.Update(); findReplacePanel->refresh(); findReplacePanel->setReplaceVisible(true); findReplacePanel->focusOnFind(); return; #endif if (findDialog.get()) { findDialog = std::auto_ptr(0); } findDialog = std::auto_ptr(new wxFindReplaceDialog( this, &findData, _("Find and Replace"), wxFR_REPLACEDIALOG)); findDialog->Show(); } void MyFrame::OnGlobalReplace(wxCommandEvent& event) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; size_t flags = findData.GetFlags(); std::auto_ptr grd(new GlobalReplaceDialog( this, findData.GetFindString(), findData.GetReplaceString(), flags & wxFR_MATCHCASE, globalReplaceAllDocuments, findRegex)); int res = grd->ShowModal(); flags = 0; flags |= wxFR_DOWN; if (grd->getMatchCase()) flags |= wxFR_MATCHCASE; findRegex = grd->getRegex(); globalReplaceAllDocuments = grd->getAllDocuments(); findData.SetFindString(grd->getFindString()); findData.SetReplaceString(grd->getReplaceString()); findData.SetFlags(flags); findReplacePanel->setRegex(findRegex); findReplacePanel->setMatchCase(flags & wxFR_MATCHCASE); findReplacePanel->refresh(); if (res != wxID_OK) { return; } int globalMatchCount, pageCount; globalMatchCount = 0; pageCount = mainBook->GetPageCount(); XmlDoc *currentDoc = getActiveDocument(); if (!currentDoc) return; for (int i = 0; i < pageCount; ++i) { std::string bufferUtf8; if (!globalReplaceAllDocuments) { getRawText(currentDoc, bufferUtf8); } else { currentDoc = (XmlDoc *)mainBook->GetPage(i); if (!currentDoc) return; getRawText(currentDoc, bufferUtf8); } size_t flags = findData.GetFlags(); if (!findRegex) { std::string findUtf8, replaceUtf8; findUtf8 =findData.GetFindString().mb_str(wxConvUTF8); replaceUtf8 = findData.GetReplaceString().mb_str(wxConvUTF8); globalMatchCount += Replace::run( bufferUtf8, findUtf8, replaceUtf8, flags & wxFR_MATCHCASE); currentDoc->SetTextRaw(bufferUtf8.c_str()); } else { try { std::auto_ptr wr(new WrapRegex( (const char *)findData.GetFindString().mb_str(wxConvUTF8), flags & wxFR_MATCHCASE, (const char *)findData.GetReplaceString().mb_str(wxConvUTF8))); int matchCount; std::string outputBuffer = wr->replaceGlobal(bufferUtf8, &matchCount); globalMatchCount += matchCount; currentDoc->SetTextRaw(outputBuffer.c_str()); } catch (std::exception& e) { wxString wideError = wxString(e.what(), wxConvUTF8, strlen(e.what())); messagePane(_("Cannot replace: ") + wideError, CONST_STOP); return; } } if (!globalReplaceAllDocuments) break; } wxString msg; msg.Printf( ngettext(L"%i replacement made", L"%i replacements made", globalMatchCount), globalMatchCount); statusProgress(msg); } void MyFrame::OnFrameClose(wxCloseEvent& event) { wxCommandEvent e; OnCloseAll(e); if (mainBook->GetPageCount()) { event.Veto(); return; } event.Skip(); } void MyFrame::OnNew(wxCommandEvent& WXUNUSED(event)) { wxString defaultSelection, typeSelection, templateFile; defaultSelection = _("XML document (*.xml)"); wxArrayString templateArray; if (wxFileName::DirExists(templateDir)) { wxString templateMask, name, extension, entry; templateMask = templateDir + wxFileName::GetPathSeparator() + _T("*.*"); templateFile = wxFindFirstFile(templateMask, wxFILE); wxFileName fn; if (!templateFile.empty()) { fn.Assign(templateFile); name = fn.GetName(); extension = fn.GetExt(); entry.Printf(_T("%s (*.%s)"), name.c_str(), extension.c_str()); templateArray.Add(entry); for (;;) { templateFile = wxFindNextFile(); if (templateFile.empty()) break; fn.Assign(templateFile); name = fn.GetName(); extension = fn.GetExt(); entry.Printf(_T("%s (*.%s)"), name.c_str(), extension.c_str()); templateArray.Add(entry); } } templateArray.Sort(); templateArray.Insert(defaultSelection, 0); const int arraySize = templateArray.GetCount(); wxString choiceArray[arraySize + 1]; for (int i = 0; i < arraySize; ++i) *(choiceArray + i) = templateArray.Item(i); wxSingleChoiceDialog scd( this, _("Choose a document type:"), _("New Document"), arraySize, choiceArray); if (scd.ShowModal() == wxID_CANCEL) { XmlDoc *doc = getActiveDocument(); if (doc) doc->SetFocus(); return; } typeSelection = scd.GetStringSelection(); } if (typeSelection == defaultSelection) { wxString emptyString(_T("")); newDocument(emptyString); return; } typeSelection.Replace(_T(" (*"), wxEmptyString); typeSelection.Replace(_T(")"), wxEmptyString); templateFile = templateDir + typeSelection; std::string templateFileLocal, buffer; templateFileLocal = templateFile.mb_str(wxConvLocal); ReadFile::run(templateFileLocal, buffer); wxString documentContents = wxString(buffer.c_str(), wxConvUTF8, buffer.size()); newDocument(documentContents, wxString(templateFileLocal.c_str(), wxConvUTF8, templateFileLocal.size())); } void MyFrame::newDocument(const wxString& s, const wxString& path, bool canSave) { std::string bufferUtf8 = (const char *)s.mb_str(wxConvUTF8); std::string pathUtf8 = (const char *)path.mb_str(wxConvUTF8); newDocument(bufferUtf8, pathUtf8, canSave); } void MyFrame::newDocument(const std::string& s, const std::string& path, bool canSave) { XmlDoc *doc; wxString documentLabel; documentLabel.Printf(_("Document%i"), documentCount++); std::string auxPath = getAuxPath(path); Freeze(); doc = (s.empty()) ? new XmlDoc( mainBook, properties, &protectTags, visibilityState, FILE_TYPE_XML, wxID_ANY, NULL, 0 // new: NULL pointer leads to default document ) : new XmlDoc( mainBook, properties, &protectTags, visibilityState, FILE_TYPE_XML, wxID_ANY, s.c_str(), // modified s.size(), // new catalogPath, path, auxPath); mainBook->AddPage((wxWindow *)doc, documentLabel, true); Thaw(); mainBook->Refresh(); if (properties.completion) doc->updatePromptMaps(); doc->setShortFileName(documentLabel); doc->SetFocus(); manager.Update(); locationPanel->update(doc, wxEmptyString); insertChildPanel->update(doc, wxEmptyString); insertSiblingPanel->update(doc, wxEmptyString); insertEntityPanel->update(doc); if (properties.validateAsYouType) doc->shallowValidate(); } void MyFrame::OnOpen(wxCommandEvent& event) { bool largeFile; largeFile = (event.GetId() == ID_OPEN_LARGE_FILE); wxString defaultFile, defaultDir; XmlDoc *doc; if ((doc = getActiveDocument()) != NULL) { defaultFile = doc->getFullFileName(); if (!defaultFile.empty()) { wxFileName fn(defaultFile); defaultDir = fn.GetPath(); } } wxFileDialog *fd = new wxFileDialog( this, (largeFile) ? _("Open Large Document") : _("Open"), defaultDir, wxEmptyString, FILE_FILTER, wxOPEN | wxMULTIPLE | wxFILE_MUST_EXIST | wxCHANGE_DIR ); if (fd->ShowModal() == wxID_CANCEL) return; wxArrayString paths; fd->GetPaths(paths); size_t count = paths.Count(); if (!count) return; for (size_t i = 0; i < count; ++i) if (!openFile(paths[i], largeFile)) break; } bool MyFrame::openFile(const wxString& fileName, bool largeFile) { if (!wxFileName::FileExists(fileName)) { wxString message; message.Printf(_("Cannot open %s"), fileName.c_str()); messagePane(message, CONST_STOP); return false; } if (openFileSet.count(fileName)) { wxString message; message.Printf(_("%s is already open"), fileName.c_str()); statusProgress(message); activateTab(fileName); return false; } wxString directory, name, extension; wxFileName::SplitPath(fileName, NULL, &directory, &name, &extension); if (!extension.empty()) { name += _T("."); name += extension; } wxString wideError; std::string buffer; pair posPair; XmlDoc *doc; int type = getFileType(fileName); std::string auxPath = getAuxPath((const char *)fileName.mb_str(wxConvLocal)); char *docBuffer = 0; size_t docBufferLen = 0; bool fileEmpty = false; statusProgress(_T("Opening file...")); //wxMemoryMappedFile *memorymap = NULL; BinaryFile *binaryfile = NULL; try { binaryfile = new BinaryFile((const char *)fileName.mb_str(wxConvLocal)); /* memorymap = new wxMemoryMappedFile( fileName, true, // readOnly true // fread ); */ } /* catch (wxMemoryMappedFileEmptyException&) { fileEmpty = true; } */ catch (...) { wxString message; message.Printf(_("Cannot open %s"), fileName.c_str()); messagePane(message, CONST_STOP); statusProgress(wxEmptyString); return false; } bool isUtf8 = false; if (!fileEmpty) { docBuffer = (char *)binaryfile->getData();//memorymap->GetStream(); docBufferLen = binaryfile->getDataLen();//memorymap->GetMapSize(); } else { docBuffer = NULL; docBufferLen = 0; isUtf8 = true; } statusProgress(wxEmptyString); char *iconvBuffer = 0; size_t iconvBufferLen = 0; char *finalBuffer; size_t finalBufferLen; // adjust for UTF-8 BOM if (docBuffer && (unsigned char)docBuffer[0] == 0xEF && (unsigned char)docBuffer[1] == 0xBB && (unsigned char)docBuffer[2] == 0xBF) { docBuffer += 3; docBufferLen -= 3; isUtf8 = true; } // no UTF-8 BOM found std::string encoding; if (!isUtf8 || !binaryfile->getDataLen()) { XmlEncodingSpy es; es.parse(docBuffer, docBufferLen); encoding = es.getEncoding(); if (encoding == "UTF-8" || encoding == "US-ASCII") // US-ASCII is a subset of UTF-8 isUtf8 = true; } // convert buffer if not UTF-8 if (isUtf8) { finalBuffer = docBuffer; finalBufferLen = docBufferLen; } else { // clear any other BOMs if (docBuffer && // UTF-32 BE (unsigned char)docBuffer[0] == 0x00 && (unsigned char)docBuffer[1] == 0x00 && (unsigned char)docBuffer[2] == 0xFE && (unsigned char)docBuffer[3] == 0xFF) { docBuffer += 4; docBufferLen -= 4; } if (docBuffer && // UTF-32 LE (unsigned char)docBuffer[0] == 0xFF && (unsigned char)docBuffer[1] == 0xFE && (unsigned char)docBuffer[2] == 0x00 && (unsigned char)docBuffer[3] == 0x00) { docBuffer += 4; docBufferLen -= 4; } if (docBuffer && //UTF-16 BE (unsigned char)docBuffer[0] == 0xFE && (unsigned char)docBuffer[1] == 0xFF) { docBuffer += 2; docBufferLen -= 2; } if (docBuffer && //UTF-16 LE (unsigned char)docBuffer[0] == 0xFF && (unsigned char)docBuffer[1] == 0xFE) { docBuffer += 2; docBufferLen -= 2; } if (!encoding.size()) // Expat couldn't parse file (e.g. UTF-32) { encoding = getApproximateEncoding(docBuffer, docBufferLen); } wxString wideEncoding = wxString( encoding.c_str(), wxConvLocal, encoding.size()); iconv_t cd = iconv_open("UTF-8", encoding.c_str()); if (cd == (iconv_t)-1) { wxString message; message.Printf(_("Cannot open %s: unknown encoding %s"), fileName.c_str(), wideEncoding.c_str()); messagePane(message, CONST_STOP); delete binaryfile;//memorymap; return false; }; int iconvLenMultiplier = 4; // worst case scenario if (encoding == "ISO-8859-1" || encoding == "UTF-16" || encoding == "UTF-16BE" || encoding == "UTF-16LE") { iconvLenMultiplier = 2; } else if (encoding == "UTF-32" || encoding == "UTF-32BE" || encoding == "UTF-32LE") { iconvLenMultiplier = 1; } size_t iconvBufferLeft, docBufferLeft; iconvBufferLen = iconvBufferLeft = docBufferLen * iconvLenMultiplier + 1; docBufferLeft = docBufferLen; iconvBuffer = new char[iconvBufferLen]; finalBuffer = iconvBuffer; // iconvBuffer will be incremented by iconv size_t nconv; nconv = iconv( cd, #ifdef __WXMSW__ (const char **) #endif &docBuffer, &docBufferLeft, &iconvBuffer, &iconvBufferLeft); *iconvBuffer = '\0'; iconv_close(cd); if (nconv == (size_t)-1) { wxString message; message.Printf(_("Cannot open %s: conversion from encoding %s failed"), fileName.c_str(), wideEncoding.c_str()); messagePane(message, CONST_STOP); delete[] finalBuffer; delete binaryfile; //delete memorymap; return false; } finalBufferLen = iconvBufferLen - iconvBufferLeft; } statusProgress(_("Creating document view...")); Freeze(); doc = new XmlDoc( mainBook, (largeFile) ? largeFileProperties: properties, &protectTags, visibilityState, (!binaryfile->getDataLen()) ? FILE_TYPE_XML : type, wxID_ANY, finalBuffer, finalBufferLen, catalogPath, (const char *)fileName.mb_str(wxConvLocal), auxPath); #ifdef __WXMSW__ doc->SetUndoCollection(false); doc->SetUndoCollection(true); #endif doc->setFullFileName(fileName); doc->setShortFileName(name); doc->setDirectory(directory); openFileSet.insert(fileName); history.AddFileToHistory(fileName); updateFileMenu(); wxFileName ofn(fileName); doc->setLastModified(ofn.GetModificationTime()); mainBook->AddPage((wxWindow *)doc, name, _T("")); Thaw(); statusProgress(wxEmptyString); mainBook->Refresh(); wxFileName fn(fileName); doc->setLastModified(fn.GetModificationTime()); doc->SetFocus(); if (type != FILE_TYPE_XML || !binaryfile->getDataLen()) { delete binaryfile;//memorymap; return true; } // NOW parse the document, but don't create a UTF-8 copy statusProgress(_T("Parsing document...")); std::auto_ptr we(new WrapExpat()); bool optimisedParseSuccess = false; // omit XML declaration if (!isUtf8 && finalBufferLen && finalBuffer[0] == '<' && finalBuffer[1] == '?' && finalBuffer[2] == 'x' && finalBuffer[3] == 'm' && finalBuffer[4] == 'l') { for (; *finalBuffer && finalBufferLen; finalBuffer++ && finalBufferLen--) { if (*finalBuffer == '>') { finalBuffer++; finalBufferLen--; break; } } } if (finalBuffer) { optimisedParseSuccess = we->parse(finalBuffer, finalBufferLen); statusProgress(wxEmptyString); } // NOW update prompt maps if necessary if (!largeFile && (properties.completion || properties.validateAsYouType)) { statusProgress(_T("Compiling autocompletion lists...")); doc->updatePromptMaps(finalBuffer, finalBufferLen); statusProgress(wxEmptyString); } if (!largeFile && (properties.validateAsYouType && doc->getDtdFound())) { statusProgress(_T("Validating document...")); doc->shallowValidate(finalBuffer, finalBufferLen); statusProgress(wxEmptyString); } if (!optimisedParseSuccess) { std::string error = we->getLastError(); wideError = wxString(error.c_str(), wxConvUTF8, error.size()); posPair = we->getErrorPosition(); --(posPair.first); messagePane(wideError, CONST_WARNING); int newPosition = doc->PositionFromLine(posPair.first); doc->SetSelection(newPosition, newPosition); doc->SetFocus(); } else { closePane(); } delete binaryfile; //delete memorymap; return true; } std::string MyFrame::getApproximateEncoding(char *docBuffer, size_t docBufferLen) { std::string line, encoding; char *it; size_t i; // grab first line for ( i = 0, it = docBuffer; i < docBufferLen && *it != '\n' && i < BUFSIZ; i++, it++) { if (*it) line += *it; } std::pair limits = XmlEncodingHandler::getEncodingValueLimits(line); if (limits.first == -1 || limits.second == -1) return ""; return line.substr(limits.first, limits.second); } void MyFrame::OnToggleFold(wxCommandEvent& WXUNUSED(event)) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; doc->toggleFold(); } void MyFrame::OnFoldAll(wxCommandEvent& WXUNUSED(event)) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; doc->foldAll(); doc->SetFocus(); } void MyFrame::OnUnfoldAll(wxCommandEvent& WXUNUSED(event)) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; doc->unfoldAll(); doc->SetFocus(); } void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) { Close(true); } void MyFrame::OnUndo(wxCommandEvent& WXUNUSED(event)) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; doc->Undo(); doc->setValidationRequired(true); doc->SetFocus(); } void MyFrame::OnRedo(wxCommandEvent& WXUNUSED(event)) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; doc->Redo(); doc->setValidationRequired(true); doc->SetFocus(); } void MyFrame::OnRevert(wxCommandEvent& WXUNUSED(event)) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; while (doc->GetModify()) { if (!doc->CanUndo()) return; doc->Undo(); doc->setValidationRequired(true); } doc->SetFocus(); } void MyFrame::OnSpelling(wxCommandEvent& WXUNUSED(event)) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; statusProgress(wxEmptyString); closePane(); #ifdef __WXMSW__ doc->SetUndoCollection(false); doc->SetUndoCollection(true); #endif std::string rawBufferUtf8; getRawText(doc, rawBufferUtf8); // handle unusual encodings if (!XmlEncodingHandler::setUtf8(rawBufferUtf8)) { encodingMessage(); return; } WrapTempFileName tempFileName(doc->getFullFileName()); ofstream rawBufferStream(tempFileName.name().c_str()); if (!rawBufferStream) return; rawBufferStream << rawBufferUtf8; rawBufferStream.close(); auto_ptr wl(new WrapLibxml(libxmlNetAccess, catalogPath)); bool success = wl->parse(tempFileName.name(), true); std::string bufferParameterUtf8; if (!success) { statusProgress(wxEmptyString); std::string error = wl->getLastError(); wxString wideError = wxString(error.c_str(), wxConvUTF8, error.size()); wideError.Prepend(_("Opening spelling and style check in read-only mode: ")); messagePane(wideError, CONST_WARNING); if (!ReadFile::run(tempFileName.name(), bufferParameterUtf8)) return; std::auto_ptr we(new WrapExpat()); bufferParameterUtf8 = we->xmliseTextNode(bufferParameterUtf8); bufferParameterUtf8.insert(0, ""); bufferParameterUtf8 += ""; } else { bufferParameterUtf8 = wl->getOutput(); } auto_ptr sd(new StyleDialog( this, wxICON(appicon), bufferParameterUtf8, doc->getShortFileName(), ruleSetDir, filterDir, browserCommand, ruleSetPreset, filterPreset, (success) ? false : true, stylePosition, styleSize)); if (sd->ShowModal() == wxID_OK) { std::string bufferUtf8 = sd->getEditedString(); if (bufferUtf8.empty()) messagePane(_("Edited document empty"), CONST_STOP); else doc->SetTextRaw(bufferUtf8.c_str()); } // update presets if report has been created (even if followed by cancel) ruleSetPreset = sd->getRuleSetPreset(); filterPreset = sd->getFilterPreset(); #ifdef __WXMSW__ stylePosition = sd->getPosition(); styleSize = sd->getSize(); #endif } void MyFrame::OnPreviousDocument(wxCommandEvent& WXUNUSED(event)) { if (!getActiveDocument()) return; statusProgress(wxEmptyString); closePane(); int currentSelection = mainBook->GetSelection(); if (currentSelection < 1) return; mainBook->SetSelection(--currentSelection); XmlDoc *doc = getActiveDocument(); if (doc) doc->SetFocus(); } void MyFrame::OnNextDocument(wxCommandEvent& WXUNUSED(event)) { if (!getActiveDocument()) return; statusProgress(wxEmptyString); closePane(); int currentSelection = mainBook->GetSelection(); int maxSelection = mainBook->GetPageCount(); if (currentSelection >= (maxSelection - 1)) return; mainBook->SetSelection(++currentSelection); XmlDoc *doc = getActiveDocument(); if (doc) doc->SetFocus(); } void MyFrame::OnSave(wxCommandEvent& event) { save(); } void MyFrame::save() { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; /* if (!doc->GetModify()) return; */ wxString fileName; if ((fileName = doc->getFullFileName()) == _T("")) { wxCommandEvent event; OnSaveAs(event); return; } if (!saveFile(doc, fileName, true)) ; // handle messages in saveFile } void MyFrame::OnSaveAs(wxCommandEvent& event) { saveAs(); } void MyFrame::saveAs() { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; wxString defaultFile, defaultDir; defaultFile = doc->getFullFileName(); if (!defaultFile.empty()) { wxFileName fn(defaultFile); defaultDir = fn.GetPath(); } auto_ptr fd(new wxFileDialog( this, _("Save As"), defaultDir, defaultFile, FILE_FILTER, wxSAVE | wxOVERWRITE_PROMPT)); if (fd->ShowModal() == wxID_CANCEL) return; wxString path = fd->GetPath(); if ( openFileSet.count(path) && path != doc->getFullFileName()) { wxString message; message.Printf(_("%s is already open"), path.c_str()); messagePane(message, CONST_STOP); return; } wxString name = fd->GetFilename(); wxString directory; wxFileName::SplitPath(path, &directory, NULL, NULL); if (path == _T("")) return; if (!saveFile(doc, path, false)) return; // if already named, remove from set of open files openFileSet.erase(doc->getFullFileName()); doc->setFullFileName(path); doc->setShortFileName(name); doc->setDirectory(directory); history.AddFileToHistory(path); // update history updateFileMenu(); int selection; if ((selection = mainBook->GetSelection()) == -1) return; mainBook->SetPageText(selection, name); } void MyFrame::OnUpdateCloseAll(wxUpdateUIEvent& event) { event.Enable(mainBook->GetPageCount() > 1); } void MyFrame::OnUpdateCutCopy(wxUpdateUIEvent& event) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) { event.Enable(false); return; } event.Enable(true); } void MyFrame::OnUpdateLocationPaneVisible(wxUpdateUIEvent& event) { if (!viewMenu) return; wxAuiPaneInfo info = manager.GetPane(locationPanel); event.Check(info.IsShown()); } void MyFrame::OnUpdateSavedOnly(wxUpdateUIEvent& event) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) { event.Enable(false); return; } event.Enable( (doc->getFullFileName().empty()) ? false : true); } void MyFrame::OnUpdateDocRange(wxUpdateUIEvent& event) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) { event.Enable(false); return; } event.Enable(true); } void MyFrame::OnUpdateReplaceRange(wxUpdateUIEvent& event) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) // || protectTags) { event.Enable(false); return; } event.Enable(true); } void MyFrame::OnUpdateFindAgain(wxUpdateUIEvent& event) { if (!getActiveDocument() || findData.GetFindString().empty()) { event.Enable(false); return; } event.Enable(true); } void MyFrame::OnUpdateSaveUndo(wxUpdateUIEvent& event) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) { event.Enable(false); return; } //event.Enable((doc->CanUndo()) ? true : false); event.Enable((doc->GetModify()) ? true : false); } void MyFrame::OnUpdateRedo(wxUpdateUIEvent& event) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) { event.Enable(false); return; } event.Enable(doc->CanRedo()); } void MyFrame::OnUpdatePaste(wxUpdateUIEvent& event) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) { event.Enable(false); return; } event.Enable(true); } void MyFrame::OnUpdatePreviousDocument(wxUpdateUIEvent& event) { if (!getActiveDocument()) { event.Enable(false); return; } int currentDocument = mainBook->GetSelection(); event.Enable((currentDocument < 1) ? false : true); } void MyFrame::OnUpdateNextDocument(wxUpdateUIEvent& event) { if (!getActiveDocument()) { event.Enable(false); return; } int currentDocument = mainBook->GetSelection(); int maxDocument = mainBook->GetPageCount(); event.Enable((currentDocument >= (maxDocument - 1)) ? false : true); } void MyFrame::OnUpdateClosePane(wxUpdateUIEvent& event) { wxAuiPaneInfo i1, i2, i3; i1 = manager.GetPane(htmlReport); i2 = manager.GetPane(findReplacePanel); i3 = manager.GetPane(commandPanel); event.Enable(i1.IsShown() || i2.IsShown() || i3.IsShown()); } void MyFrame::OnValidateDTD(wxCommandEvent& event) { statusProgress(wxEmptyString); // fetch document contents XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; updatePaths(); // needed to ensure catalog is available wxString fname = doc->getFullFileName(); WrapTempFileName wtfn(fname); if (fname.empty() || doc->GetModify()) { wxString wideBuffer = doc->GetText(); std::string buffer = (const char *)wideBuffer.mb_str(wxConvUTF8); if (!saveRawUtf8( wtfn.name(), buffer)) { messagePane( _("Cannot save temporary copy for validation; please save or discard changes"), CONST_STOP); return; } fname = wtfn.wideName(); } std::string fnameLocal = (const char *)fname.mb_str(wxConvLocal); doc->clearErrorIndicators(); statusProgress(_("DTD validation in progress...")); auto_ptr wl(new WrapLibxml(libxmlNetAccess, catalogPath)); if (!wl->validate(fnameLocal)) { std::string error = wl->getLastError(); wxString wideError = wxString(error.c_str(), wxConvUTF8, error.size()); statusProgress(wxEmptyString); messagePane(wideError, CONST_WARNING); std::pair posPair = wl->getErrorPosition(); --(posPair.first); int cursorPos = doc->PositionFromLine(posPair.first); doc->SetSelection(cursorPos, cursorPos); // shallow validate all doc->shallowValidate(); // has to come first as it deletes all indicators doc->setErrorIndicator(posPair.first, posPair.second); return; } statusProgress(wxEmptyString); documentOk(_("valid")); } void MyFrame::OnValidateRelaxNG(wxCommandEvent& event) { statusProgress(wxEmptyString); XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; wxString fileName = doc->getFullFileName(); wxString defaultFile, defaultDir; defaultFile = doc->getFullFileName(); if (!defaultFile.empty()) { wxFileName fn(defaultFile); defaultDir = fn.GetPath(); } AssociateDialog ad( this, _("Select RELAX NG grammar"), _("Choose a file:"), _("RELAX NG grammar"), _T("*.*"), lastRelaxNGSchema); if (ad.ShowModal() != wxID_OK) return; wxString path = lastRelaxNGSchema = ad.getUrl(); if (path.empty()) { statusProgress(wxEmptyString); return; } validateRelaxNG(doc, path, fileName); } void MyFrame::validateRelaxNG( XmlDoc *doc, const wxString& schemaName, wxString& fileName) // not const: may change if empty/document modified { statusProgress(wxEmptyString); if (!doc) return; WrapTempFileName wtfn(fileName); if (fileName.empty() || doc->GetModify()) { wxString wideBuffer = doc->GetText(); std::string buffer = (const char *)wideBuffer.mb_str(wxConvUTF8); if (!saveRawUtf8( wtfn.name(), buffer)) { messagePane( _("Cannot save temporary copy for validation; please save or discard changes"), CONST_STOP); return; } fileName = wtfn.wideName(); } doc->clearErrorIndicators(); statusProgress(_("RELAX NG validation in progress...")); auto_ptr wl(new WrapLibxml(libxmlNetAccess, catalogPath)); std::string schemaFileNameLocal = (const char *)schemaName.mb_str(wxConvLocal); std::string fileNameLocal = (const char *)fileName.mb_str(wxConvLocal); if (!wl->validateRelaxNG(schemaFileNameLocal, fileNameLocal)) { std::string error = wl->getLastError(); wxString wideError = wxString(error.c_str(), wxConvUTF8, error.size()); statusProgress(wxEmptyString); std::pair posPair = wl->getErrorPosition(); --(posPair.first); int cursorPos = doc->PositionFromLine(posPair.first); doc->SetSelection(cursorPos, cursorPos); doc->setErrorIndicator(posPair.first, posPair.second); messagePane(wideError, CONST_WARNING); doc->SetFocus(); return; } statusProgress(wxEmptyString); documentOk(_("valid")); doc->SetFocus(); } void MyFrame::OnValidatePreset(wxCommandEvent& event) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; wxString fileName = doc->getFullFileName(); int id = event.GetId(); wxString schemaFileName = validationPresetMap[id]; if (schemaFileName.empty()) return; validateRelaxNG(doc, schemaFileName, fileName); } void MyFrame::OnValidateSchema(wxCommandEvent& event) { statusProgress(wxEmptyString); XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; /* // schema location required std::auto_ptr xsl(new XmlSchemaLocator()); std::string utf8Buffer; getRawText(doc, utf8Buffer); XmlEncodingHandler::setUtf8(utf8Buffer, true); xsl->parse(utf8Buffer); std::string utf8Location = xsl->getSchemaLocation(); if (utf8Location.empty()) { messagePane(_("No XML Schema found"), CONST_STOP); return; } */ wxString fileName; std::string tempFileNameLocal; fileName = doc->getFullFileName(); WrapTempFileName wtfn(fileName); if (fileName.empty() || doc->GetModify()) { wxString wideBuffer = doc->GetText(); std::string buffer = (const char *)wideBuffer.mb_str(wxConvUTF8); if (!saveRawUtf8( wtfn.name(), buffer)) { messagePane( _("Cannot save temporary copy for validation; please save or discard changes"), CONST_STOP); return; } fileName = wtfn.wideName(); } doc->clearErrorIndicators(); std::string error; wxString wideError; #ifdef __WXMSW__ // separate WrapTempFileName for output log WrapTempFileName tempFileName(_T("")); wxString cmd = binDir + _T("validate.exe \"") + fileName + _T("\" \"") + tempFileName.wideName() + _T("\""); statusProgress(_("Validation in progress...")); int result = wxExecute(cmd, wxEXEC_SYNC); statusProgress(wxEmptyString); switch (result) { case 0: documentOk(_("valid")); break; case 1: messagePane(_("MSXML validation failed (version 4.0 or later required)"), CONST_STOP); break; case 2: if (ReadFile::run(tempFileName.name(), error)) { wideError = wxString(error.c_str(), wxConvLocal, error.size()); messagePane(wideError, CONST_WARNING); // tbd: extract line & column numbers; use error indicators } else messagePane(_("Validation error"), CONST_WARNING); break; default: break; } doc->SetFocus(); return; #else std::auto_ptr validator(new WrapXerces()); std::string fileNameLocal = (const char *)fileName.mb_str(wxConvLocal); if (!validator->validate(fileNameLocal)) { error = validator->getLastError(); wideError = wxString(error.c_str(), wxConvUTF8, error.size()); messagePane(wideError, CONST_WARNING); std::pair posPair = validator->getErrorPosition(); int cursorPos = doc->PositionFromLine(posPair.first - 1); doc->SetSelection(cursorPos, cursorPos); doc->setErrorIndicator(posPair.first - 1, posPair.second); } else documentOk(_("valid")); /* // handle relative locations schemaPath = PathResolver::run(schemaPath, fileName); statusProgress(_("XML Schema validation in progress...")); auto_ptr wl(new WrapLibxml(libxmlNetAccess, catalogPath)); std::string schemaFileNameLocal = (const char *)schemaPath.mb_str(wxConvLocal); std::string fileNameLocal = (const char *)fileName.mb_str(wxConvLocal); if (!wl->validateW3CSchema(schemaFileNameLocal, fileNameLocal)) { std::string error = wl->getLastError(); wxString wideError = wxString(error.c_str(), wxConvUTF8, error.size()); statusProgress(wxEmptyString); std::pair posPair = wl->getErrorPosition(); --(posPair.first); int cursorPos = doc->PositionFromLine(posPair.first - 1); doc->SetSelection(cursorPos, cursorPos); doc->setErrorIndicator(posPair.first - 1, posPair.second); messagePane(wideError, CONST_WARNING); return; } statusProgress(wxEmptyString); documentOk(_("valid")); */ #endif } void MyFrame::OnXPath(wxCommandEvent& event) { statusProgress(wxEmptyString); closePane(); XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; auto_ptr dlg(new wxTextEntryDialog( this, _("Enter XPath:"), _("Evaluate XPath"), xpathExpression)); int ret = dlg->ShowModal(); if (ret == wxID_CANCEL) return; xpathExpression = dlg->GetValue(); std::string valUtf8 = (const char *)xpathExpression.mb_str(wxConvUTF8); // fetch document contents std::string rawBufferUtf8; getRawText(doc, rawBufferUtf8); if (!XmlEncodingHandler::setUtf8(rawBufferUtf8)) { encodingMessage(); return; } WrapTempFileName tempFileName(doc->getFullFileName()); ofstream rawBufferStream(tempFileName.name().c_str()); if (!rawBufferStream) return; rawBufferStream << rawBufferUtf8; rawBufferStream.close(); auto_ptr wl(new WrapLibxml(libxmlNetAccess, catalogPath)); bool success = wl->xpath(valUtf8, tempFileName.name()); if (!success) { std::string error = wl->getLastError(); wxString wideError = wxString(error.c_str(), wxConvUTF8, error.size()); if (!wideError.empty()) wideError.Prepend(_T(": ")); wideError.Prepend(_("Cannot evaluate XPath")); messagePane(wideError, CONST_WARNING); return; } statusProgress(wxEmptyString); std::string buffer = wl->getOutput(); if (buffer.empty()) { messagePane(_("No matching nodes found"), CONST_WARNING); return; } newDocument(buffer); statusProgress(wxEmptyString); } void MyFrame::OnXslt(wxCommandEvent& event) { statusProgress(wxEmptyString); closePane(); // fetch document contents XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; std::string rawBufferUtf8; getRawText(doc, rawBufferUtf8); if (!XmlEncodingHandler::setUtf8(rawBufferUtf8)) { encodingMessage(); return; } WrapTempFileName tempFileName(doc->getFullFileName()); ofstream rawBufferStream(tempFileName.name().c_str()); if (!rawBufferStream) return; rawBufferStream << rawBufferUtf8; rawBufferStream.close(); wxString path; int id = event.GetId(); if (id == ID_XSLT) { XslLocator xl; xl.parse(rawBufferUtf8); std::string location = xl.getXslLocation(); path = wxString(location.c_str(), wxConvUTF8, location.size()); path.Replace(_T("%20"), _T(" "), true); path = PathResolver::run(path, doc->getFullFileName()); if (!wxFileName::FileExists(path)) { if (!path.empty()) { wxString message; message.Printf(_("Cannot open stylesheet %s"), path.c_str()); messagePane(message, CONST_WARNING); } wxString defaultFile, defaultDir; defaultFile = doc->getFullFileName(); if (!defaultFile.empty()) { wxFileName fn(defaultFile); defaultDir = fn.GetPath(); } AssociateDialog ad( this, _("Select stylesheet"), _("Choose a file:"), _("XSLT stylesheet"), _T("*.xsl;*.xslt"), lastXslStylesheet); if (ad.ShowModal() != wxID_OK) return; path = lastXslStylesheet = ad.getUrl(); if (path.empty()) // Cancel selected { statusProgress(wxEmptyString); return; } } } else { wxString sep; sep.Append(wxFileName::GetPathSeparator()); switch (id) { case ID_XSLT_TEI_FO: path = applicationDir + sep + _T("tei") + sep + _T("fo") + sep + _T("tei.xsl"); break; case ID_XSLT_TEI_HTML: path = applicationDir + sep + _T("tei") + sep + _T("html") + sep + _T("tei.xsl"); break; case ID_XSLT_TEI_XHTML: path = applicationDir + sep + _T("tei") + sep + _T("xhtml") + sep + _T("tei.xsl"); break; case ID_XSLT_TEI_LATEX: path = applicationDir + sep + _T("tei") + sep + _T("latex") + sep + _T("tei.xsl"); break; case ID_XSLT_DOCBOOK_FO: path = applicationDir + sep + _T("docbook") + sep + _T("fo") + sep + _T("docbook.xsl"); break; case ID_XSLT_DOCBOOK_HTML: path = applicationDir + sep + _T("docbook") + sep + _T("html") + sep + _T("docbook.xsl"); break; case ID_XSLT_DOCBOOK_XHTML: path = applicationDir + sep + _T("docbook") + sep + _T("xhtml") + sep + _T("docbook.xsl"); break; default: break; } } statusProgress(_("XSL transformation in progress...")); std::string stylefnameLocal = (const char *)path.mb_str(wxConvLocal); auto_ptr wl(new WrapLibxml(libxmlNetAccess, catalogPath)); if (!wl->xslt(stylefnameLocal, tempFileName.name())) { std::string error = wl->getLastError(); wxString wideError = wxString(error.c_str(), wxConvUTF8, error.size()); wideError.Prepend(_("Cannot transform: ")); statusProgress(wxEmptyString); messagePane(wideError, CONST_WARNING); return; } std::string buffer = wl->getOutput(); if (buffer.empty()) { messagePane(_("Output document empty"), CONST_WARNING); return; } statusProgress(wxEmptyString); newDocument(buffer); } void MyFrame::OnPrettyPrint(wxCommandEvent& event) { statusProgress(wxEmptyString); closePane(); // fetch document contents XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; int line = doc->LineFromPosition(doc->GetCurrentPos()); std::string rawBufferUtf8; getRawText(doc, rawBufferUtf8); std::string encoding = XmlEncodingHandler::get(rawBufferUtf8); if (!XmlEncodingHandler::setUtf8(rawBufferUtf8, true)) { encodingMessage(); return; } statusProgress(_("Pretty-printing in progress...")); for (int i = 0; i < 2; i++) // perform two iterations { WrapTempFileName tempFileName(doc->getFullFileName()); ofstream rawBufferStream(tempFileName.name().c_str()); if (!rawBufferStream) return; rawBufferStream << rawBufferUtf8; rawBufferStream.close(); auto_ptr wl(new WrapLibxml(libxmlNetAccess, catalogPath)); bool success = wl->parse(tempFileName.name(), true); if (!success) { std::string error = wl->getLastError(); wxString wideError = wxString(error.c_str(), wxConvUTF8, error.size()); wideError.Prepend(_("Cannot pretty-print: ")); statusProgress(wxEmptyString); messagePane(wideError, CONST_WARNING); return; } rawBufferUtf8 = wl->getOutput(); } statusProgress(wxEmptyString); if (rawBufferUtf8.empty()) messagePane( _("Pretty-print unsuccessful: output document empty"), CONST_STOP); else { /* if (encoding != "UTF-8") { std::string output = getEncodedBuffer(rawBufferUtf8, encoding); if (!output.empty()) rawBufferUtf8 = output; } */ if (encoding != "UTF-8" && !encoding.empty()) { XmlEncodingHandler::set(rawBufferUtf8, encoding); } doc->SetTextRaw(rawBufferUtf8.c_str()); statusProgress(wxEmptyString); } doc->GotoLine(line); doc->SetFocus(); } void MyFrame::OnEncoding(wxCommandEvent& event) { statusProgress(wxEmptyString); closePane(); // fetch document contents XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; std::vector encodingVector; encodingVector.push_back(_T("UTF-8")); encodingVector.push_back(_T("UTF-16")); encodingVector.push_back(_T("UTF-16LE")); encodingVector.push_back(_T("UTF-16BE")); encodingVector.push_back(_T("ISO-8859-1")); encodingVector.push_back(_T("US-ASCII")); const int vectorSize = encodingVector.size(); wxString choiceArray[vectorSize + 1]; for (int i = 0; i < vectorSize; ++i) *(choiceArray + i) = encodingVector.at(i); wxSingleChoiceDialog scd( this, _("Choose an encoding:"), _("Encoding"), vectorSize, choiceArray); if (scd.ShowModal() == wxID_CANCEL) return; wxString selection; std::string selectionUtf8, bufferUtf8; selection = scd.GetStringSelection(); selectionUtf8 = selection.mb_str(wxConvUTF8); getRawText(doc, bufferUtf8); XmlEncodingHandler::setUtf8(bufferUtf8, true); WrapTempFileName tempFileName(_T("")); std::auto_ptr wl(new WrapLibxml(libxmlNetAccess)); int res; WrapTempFileName sourceFileName(doc->getFullFileName()); saveRawUtf8(sourceFileName.name(), bufferUtf8); res = wl->saveEncodingFromFile(sourceFileName.name(), tempFileName.name(), selectionUtf8); if (res == -1) { std::string error = wl->getLastError(); wxString wideError = wxString(error.c_str(), wxConvUTF8, error.size()); wideError.Prepend(_("Cannot set encoding: ")); messagePane(wideError, CONST_STOP); return; } std::string newBuffer; bool success = ReadFile::run(tempFileName.name(), newBuffer); if (!success) { messagePane(_("Cannot set encoding (cannot open temporary file)"), CONST_STOP); return; } std::auto_ptr xur(new XmlUtf8Reader( false, expandInternalEntities, newBuffer.size())); if (!xur->parse(newBuffer)) { messagePane(_("Cannot set encoding (cannot parse temporary file)"), CONST_STOP); return; } /* if (wl->getLastError().empty()) { doc->SetTextRaw(xur->getBuffer().c_str()); } else { std::string err = wl->getLastError(); wxString wideErr; wideErr = _("Cannot set encoding: "); wideErr += wxString(err.c_str(), wxConvUTF8, err.size()); messagePane(wideErr, CONST_STOP); } */ doc->SetTextRaw(xur->getBuffer().c_str()); doc->SetFocus(); } /* std::string MyFrame::getEncodedBuffer( const std::string& bufferUtf8, const std::string& encodingUtf8) { WrapTempFileName tempFileName(_T("")); std::auto_ptr wl(new WrapLibxml(libxmlNetAccess)); int res; // change to saveEncodingFromFile? res = wl->saveEncoding(bufferUtf8, tempFileName.name(), encodingUtf8); if (res == -1) { std::string error = wl->getLastError(); wxString wideError = wxString(error.c_str(), wxConvUTF8, error.size()); wideError.Prepend(_("Cannot set encoding: ")); messagePane(wideError, CONST_STOP); return ""; } std::string newBuffer; bool success = ReadFile::run(tempFileName.name(), newBuffer); if (!success) { messagePane(_("Cannot set encoding (cannot open temporary file)"), CONST_STOP); return ""; } std::auto_ptr xur(new XmlUtf8Reader( false, expandInternalEntities, newBuffer.size())); if (!xur->parse(newBuffer)) { messagePane(_("Cannot set encoding (cannot parse temporary file)"), CONST_STOP); return ""; } return xur->getBuffer().c_str(); } */ void MyFrame::OnHome(wxCommandEvent& event) { navigate(_T("http://xml-copy-editor.sourceforge.net")); } void MyFrame::OnDownloadSource(wxCommandEvent& event) { navigate(_T("https://sourceforge.net/project/showfiles.php?group_id=141776")); } void MyFrame::OnToolbarVisible(wxCommandEvent& event) { if (!viewMenu) return; #ifdef __WXMSW__ if (useCoolBarOnStart) toolbarVisible = (viewMenu->IsChecked(ID_TOOLBAR_VISIBLE)) ? false : true; else toolbarVisible = (toolbarVisible) ? false : true; #else toolbarVisible = (toolbarVisible) ? false : true; #endif viewMenu->Check(ID_TOOLBAR_VISIBLE, toolbarVisible); showTopBars(toolbarVisible); manager.Update(); } void MyFrame::OnWrapWords(wxCommandEvent& event) { if (!viewMenu) return; bool wrapWords; #ifdef __WXMSW__ wrapWords = (viewMenu->IsChecked(ID_WRAP_WORDS)) ? false : true; #else wrapWords = (properties.wrap) ? false : true; #endif viewMenu->Check(ID_WRAP_WORDS, wrapWords); properties.wrap = wrapWords; // update all documents int pageCount = mainBook->GetPageCount(); XmlDoc *currentDoc; for (int i = 0; i < pageCount; ++i) { currentDoc = (XmlDoc *)mainBook->GetPage(i); if (!currentDoc) break; currentDoc->SetWrapMode(wrapWords); } } void MyFrame::OnLocationPaneVisible(wxCommandEvent& event) { wxAuiPaneInfo info = manager.GetPane(locationPanel); bool visible = (info.IsShown()) ? false : true; manager.GetPane(locationPanel).Show(visible); manager.Update(); XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; doc->SetFocus(); } void MyFrame::OnProtectTags(wxCommandEvent& event) { if (!xmlMenu) return; #ifdef __WXMSW__ if (useCoolBarOnStart) protectTags = (xmlMenu->IsChecked(ID_PROTECT_TAGS)) ? false : true; else protectTags = (protectTags) ? false : true; #else protectTags = (protectTags) ? false : true; #endif if (xmlMenu) xmlMenu->Check(ID_PROTECT_TAGS, protectTags); if (toolBar) toolBar->ToggleTool(ID_PROTECT_TAGS, protectTags); XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; if (protectTags) doc->adjustCursor(); // apply to all open docs? doc->SetFocus(); } void MyFrame::OnVisibilityState(wxCommandEvent& event) { int id; id = event.GetId(); switch (id) { case ID_SHOW_TAGS: visibilityState = SHOW_TAGS; //GetStatusBar()->SetStatusText(wxEmptyString, STATUS_PARENT); break; case ID_HIDE_ATTRIBUTES: visibilityState = HIDE_ATTRIBUTES; //GetStatusBar()->SetStatusText(wxEmptyString, STATUS_PARENT); break; case ID_HIDE_TAGS: visibilityState = HIDE_TAGS; break; default: visibilityState = SHOW_TAGS; break; } if (viewMenu) viewMenu->Check(id, true); // iterate over all open documents int pageCount = mainBook->GetPageCount(); XmlDoc *currentDoc; for (int i = 0; i < pageCount; ++i) { currentDoc = (XmlDoc *)mainBook->GetPage(i); if (!currentDoc) break; currentDoc->applyVisibilityState(visibilityState); } if (visibilityState == HIDE_ATTRIBUTES || visibilityState == HIDE_TAGS) { if (properties.protectHiddenElements && !protectTags) { wxCommandEvent e; OnProtectTags(e); } } // fetch current document XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; // set focus for current document doc->SetFocus(); } void MyFrame::OnFeedback(wxCommandEvent& event) { wxString forumUrl = _T("https://sourceforge.net/forum/forum.php?forum_id=475215"); navigate(forumUrl); } void MyFrame::navigate(const wxString& url) { wxString testString = browserCommand; testString.Replace(_T(" -remote"), wxEmptyString, true); if (browserCommand.empty()) { messagePane( _("Cannot open in browser: no browser defined (see Tools, Options..., General)"), CONST_STOP); return; } else if (!wxFileName::FileExists(testString)) { wxString message; message.Printf( _("Cannot open in browser: %s not found (see Tools, Options..., General)"), testString.c_str()); messagePane(message, CONST_STOP); return; } wxString cmd; cmd = browserCommand + _T(" \"") + url + _T("\""); wxExecute(cmd, wxEXEC_ASYNC); // make ASYNC an option? } void MyFrame::findAgain(wxString s, int flags) { findReplacePanel->flagNotFound(false); if (s.empty()) return; statusProgress(wxEmptyString); XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; // update regex parameter to keep global replace in sync findRegex = findReplacePanel->getRegex(); int newLocation; int myFlags = 0; if (flags & wxFR_WHOLEWORD) myFlags |= wxSTC_FIND_WHOLEWORD; if (flags & wxFR_MATCHCASE) myFlags |= wxSTC_FIND_MATCHCASE; if (findReplacePanel->getRegex()) myFlags |= wxSTC_FIND_REGEXP; bool incrementalFind = (findReplacePanel->getIncrementalFind()) ? true : false; //doc->SetYCaretPolicy(wxSTC_CARET_SLOP | wxSTC_CARET_STRICT, 10); if (flags & wxFR_DOWN) // find next { doc->SetTargetStart((incrementalFind) ? doc->GetSelectionStart() : doc->GetSelectionEnd()); doc->SetTargetEnd(doc->GetLength()); doc->SetSearchFlags(myFlags); newLocation = doc->SearchInTarget(s); // try once more from top if (newLocation == -1) { doc->SetTargetStart(0); doc->SetTargetEnd(doc->GetLength()); newLocation = doc->SearchInTarget(s); } } else // find previous { doc->SetCurrentPos( (doc->GetSelectionStart()) ? doc->GetSelectionStart() - 1 : 0); doc->SearchAnchor(); newLocation = doc->SearchPrev(myFlags, s); } //doc->SetYCaretPolicy(wxSTC_CARET_SLOP, 0); if (newLocation == -1) { findReplacePanel->flagNotFound(true); wxString err; err.Printf(_("Cannot find '%s'"), s.c_str()); doc->SetSelectionEnd(doc->GetSelectionStart()); statusProgress(err); // must clear target to prevent replace affecting whole document doc->SetTargetStart(0); doc->SetTargetEnd(0); return; } doc->SetSelection(doc->GetTargetStart(), doc->GetTargetEnd()); doc->EnsureCaretVisible(); } bool MyFrame::closeActiveDocument() { statusProgress(wxEmptyString); closePane(); int selection = mainBook->GetSelection(); if (selection == -1 || !mainBook->GetPageCount()) // GetPageCount needed for wxAuiNotebook return false; locationPanel->update(NULL, wxEmptyString); insertChildPanel->update(NULL, wxEmptyString); insertSiblingPanel->update(NULL, wxEmptyString); // workaround -- wxAuiNotebook: send virtual close event? DeletePage doesn't generate one wxAuiNotebookEvent e; e.SetSelection(selection); OnPageClosing(e); if (deletePageVetoed) return false; mainBook->DeletePage(selection); return true; // was: // mainBook->DeletePage(selection); // return (!deletePageVetoed); } bool MyFrame::saveFile(XmlDoc *doc, wxString& fileName, bool checkLastModified) { if (!doc) return false; statusProgress(wxEmptyString); if (checkLastModified) { wxFileName fn(fileName); if (fn.IsOk()) { wxDateTime myLastModified = fn.GetModificationTime(); if (!myLastModified.IsEqualTo(doc->getLastModified())) { int choice = wxMessageBox( _("File has been modified by another application.\nDo you want to proceed?"), _("Confirmation"), wxICON_QUESTION | wxYES_NO | wxCANCEL); if (choice != wxYES) return false; } } } int bytes = 0; std::string utf8Buffer, encoding, fileNameLocal; bool isXml = true; try { getRawText(doc, utf8Buffer); XmlEncodingSpy es; es.parse(utf8Buffer); encoding = es.getEncoding(); fileNameLocal = fileName.mb_str(wxConvLocal); closePane(); bool success; success = true; if (getFileType(fileName) != FILE_TYPE_XML) { isXml = false; } // raw file conditions if (doc->getType() == FILE_TYPE_BINARY) { success = saveRawUtf8(fileNameLocal, utf8Buffer, true); if (success) bytes = utf8Buffer.size(); } else if (!isXml && encoding.empty()) { success = saveRawUtf8(fileNameLocal, utf8Buffer, false); if (success) bytes = utf8Buffer.size(); } else if (encoding == "UTF-8") { auto_ptr we(new WrapExpat()); if (!we->parse(utf8Buffer)) { std::string error = we->getLastError(); wxString werror = wxString(error.c_str(), wxConvUTF8, error.size()); if (we->isEncodingError()) ; messagePane(werror, CONST_WARNING); } success = saveRawUtf8(fileNameLocal, utf8Buffer); if (success) bytes = utf8Buffer.size(); } else { wxString wideEncoding = wxString(encoding.c_str(), wxConvLocal, encoding.size()); // IF Unicode, use iconv to convert buffer if (encoding == "UTF-16" || encoding == "UTF-16LE" || encoding == "UTF-16BE" || encoding == "UTF-32" || encoding == "UTF-32LE" || encoding == "UTF-32BE") { iconv_t cd = iconv_open(encoding.c_str(), "UTF-8"); if (cd == (iconv_t)-1) { success = saveRawUtf8(fileNameLocal, utf8Buffer); if (success) { bytes = utf8Buffer.size(); wxString message; message.Printf( _("%s saved in default encoding UTF-8: unknown encoding %s"), fileName.c_str(), wideEncoding.c_str()); messagePane(message, CONST_WARNING); } else return false; } else { size_t utf8BufferLen = utf8Buffer.size(); size_t iconvBufferLen, iconvBufferLeft, utf8BufferLeft; int iconvLenMultiplier = 4; // worst case scenario if (encoding == "UTF-16" || encoding == "UTF-16BE" || encoding == "UTF-16LE") { iconvLenMultiplier = 2; } else if (encoding == "UTF-32" || encoding == "UTF-32BE" || encoding == "UTF-32LE") { iconvLenMultiplier = 4; } iconvBufferLen = iconvBufferLeft = utf8BufferLen * iconvLenMultiplier + 4; // worst case scenario char *finalBuffer; char *iconvBuffer = new char[iconvBufferLen]; utf8BufferLeft = utf8BufferLen; iconvBuffer = new char[iconvBufferLen]; finalBuffer = iconvBuffer; // iconvBuffer will be incremented by iconv size_t nconv; #ifdef __WXMSW_ const char * #else char * #endif utf8BufferPtr = (char *) utf8Buffer.c_str(); nconv = iconv( cd, #ifdef __WXMSW__ (const char **) #endif &utf8BufferPtr, &utf8BufferLeft, &iconvBuffer, &iconvBufferLeft); iconv_close(cd); if (nconv == (size_t)-1) // conversion failed { delete[] finalBuffer; success = saveRawUtf8(fileNameLocal, utf8Buffer); if (success) { bytes = utf8Buffer.size(); wxString message; message.Printf( _("%s saved in default encoding UTF-8: conversion to %s failed"), fileName.c_str(), wideEncoding.c_str()); messagePane(message, CONST_WARNING); } else { return false; } } else { size_t finalBufferLen = iconvBufferLen - iconvBufferLeft; std::ofstream ofs(fileNameLocal.c_str(), std::ios::out | std::ios::binary); if (!ofs) { delete[] finalBuffer; return false; } // iconv adds boms for UTF-16 & UTF-32 automatically ofs.write(finalBuffer, finalBufferLen); ofs.close(); delete[] finalBuffer; bytes = finalBufferLen; } } } else // all other encodings handled by Libxml { XmlEncodingHandler::setUtf8(utf8Buffer); auto_ptr wl(new WrapLibxml(libxmlNetAccess)); WrapTempFileName sourceFileName(fileName); saveRawUtf8(sourceFileName.name(), utf8Buffer); int result = wl->saveEncodingFromFile(sourceFileName.name(), fileNameLocal, encoding); if (result == -1) { success = saveRawUtf8(fileNameLocal, utf8Buffer); if (success) { std::string libxmlError = wl->getLastError(); bytes = utf8Buffer.size(); wxString msg, wideEncoding, wideError; wideEncoding = wxString(encoding.c_str(), wxConvUTF8, encoding.size()); wideError = wxString(libxmlError.c_str(), wxConvUTF8, libxmlError.size()); if (wideError.empty()) wideError = _("unknown error"); msg.Printf(_("Cannot save document in %s: %s (saved in default encoding UTF-8)"), wideEncoding.c_str(), wideError.c_str()); messagePane(msg, CONST_INFO); } } else bytes = result; } } } // try catch (std::bad_alloc&) { if (encoding != "UTF-8") { int answer = wxMessageBox( _("Out of memory: attempt to save in default encoding UTF-8?"), _("Out of memory"), wxYES_NO | wxCANCEL | wxICON_QUESTION, this); if (answer == wxCANCEL || answer == wxNO) return false; bool success = saveRawUtf8(fileNameLocal, utf8Buffer); if (success) { bytes = utf8Buffer.size(); wxString message; message.Printf( _("%s saved in default encoding UTF-8"), fileName.c_str()); messagePane(message, CONST_INFO); } else { wxString message; message.Printf(_("Cannot save %s"), fileName.c_str()); messagePane(message, CONST_STOP); return false; } } } doc->SetFocus(); doc->SetSavePoint(); if (properties.validateAsYouType && isXml) doc->shallowValidate(utf8Buffer.c_str(), utf8Buffer.size()); if (!unlimitedUndo) doc->EmptyUndoBuffer(); wxFileName fn(fileName); if (fn.IsOk()) doc->setLastModified(fn.GetModificationTime()); openFileSet.insert(fileName); displaySavedStatus(bytes); return true; } bool MyFrame::saveRawUtf8( const std::string& fileNameLocal, std::string& bufferUtf8, bool ignoreEncoding, bool isXml) { ofstream ofs(fileNameLocal.c_str(), std::ios::out | std::ios::binary); if (!ofs) return false; if (!ignoreEncoding && isXml) XmlEncodingHandler::setUtf8(bufferUtf8, true); if (saveBom && isXml) { char bom[4]; bom[0] = 0xEF; bom[1] = 0xBB; bom[2] = 0xBF; bom[3] = 0; ofs.write(bom, 3); } ofs.write(bufferUtf8.c_str(), bufferUtf8.size()); ofs.close(); return true; } void MyFrame::displaySavedStatus(int bytes) { wxString unit; float result = 0; if (bytes > 1000000) { result = bytes / 1000000; unit = _("MB"); } else if (bytes > 1000) { result = bytes / 1000; unit = _("kB"); } else if (bytes >= 0) { result = bytes; unit = ngettext(L"byte", L"bytes", bytes); } else return; wxString msg; msg.Printf( _("%g %s saved"), result, unit.c_str()); statusProgress(msg); } bool MyFrame::xpThemeActive() { #ifndef __WXMSW__ return false; #else return (wxUxThemeEngine::Get() && wxUxThemeEngine::Get()->IsThemeActive()); #endif } bool MyFrame::getHandleCommandLineFlag() { return handleCommandLineFlag; } MyMenuBar *MyFrame::getMenuBar() { fileMenu = new wxMenu; // use class-wide data member updateFileMenu(false); // edit menu wxMenu *editMenu = new wxMenu; wxMenuItem *undoItem = new wxMenuItem(NULL, wxID_UNDO, _("&Undo\tCtrl+Z"), _("Undo")); undoItem->SetBitmap(undo16Bitmap); wxMenuItem *redoItem = new wxMenuItem(NULL, wxID_REDO, _("&Redo\tCtrl+Y"), _("Redo")); redoItem->SetBitmap(redo16Bitmap); wxMenuItem *cutItem = new wxMenuItem(NULL, wxID_CUT, _("&Cut\tCtrl+X"), _("Cut")); cutItem->SetBitmap(cutBitmap); wxMenuItem *copyItem = new wxMenuItem(NULL, wxID_COPY, _("C&opy\tCtrl+C"), _("Copy")); copyItem->SetBitmap(copyBitmap); wxMenuItem *pasteItem = new wxMenuItem(NULL, wxID_PASTE, _("&Paste\tCtrl+V"), _("Paste")); pasteItem->SetBitmap(pasteBitmap); wxMenuItem *pasteNewDocumentItem = new wxMenuItem( NULL, ID_PASTE_NEW_DOCUMENT, _("P&aste As New Document"), _("Paste As New Document")); pasteNewDocumentItem->SetBitmap(wxNullBitmap); wxMenuItem *findItem = new wxMenuItem(NULL, ID_FIND, _("&Find...\tCtrl+F"), _("Find...")); findItem->SetBitmap(searchBitmap); wxMenuItem *findAgainItem = new wxMenuItem(NULL, ID_FIND_AGAIN, _("F&ind Again\tF3"), _("Find Again")); findAgainItem->SetBitmap(wxNullBitmap); wxMenuItem *replaceItem = new wxMenuItem(NULL, ID_REPLACE, _("&Replace...\tCtrl+R"), _("Replace...")); replaceItem->SetBitmap(wxNullBitmap); wxMenuItem *globalReplaceItem = new wxMenuItem( NULL, ID_GLOBAL_REPLACE, _("&Global Replace...\tCtrl+Shift+R"), _("Global Replace...")); globalReplaceItem->SetBitmap(wxNullBitmap); wxMenuItem *gotoItem = new wxMenuItem(NULL, ID_GOTO, _("G&o To...\tCtrl+G"), _("Go To...")); gotoItem->SetBitmap(wxNullBitmap); editMenu->Append(undoItem); editMenu->Append(redoItem); editMenu->AppendSeparator(); editMenu->Append(cutItem); editMenu->Append(copyItem); editMenu->Append(pasteItem); editMenu->Append(pasteNewDocumentItem); editMenu->AppendSeparator(); editMenu->Append(findItem); editMenu->Append(findAgainItem); editMenu->Append(replaceItem); editMenu->Append(globalReplaceItem); editMenu->AppendSeparator(); editMenu->Append(gotoItem); // font size menu wxMenu *fontSizeMenu = new wxMenu; fontSizeMenu->Append( ID_FONT_LARGER, _("Increase\tCtrl+U"), _("Increase")); fontSizeMenu->Append( ID_FONT_SMALLER, _("Decrease\tCtrl+D"), _("Decrease")); fontSizeMenu->AppendSeparator(); fontSizeMenu->Append(ID_FONT_NORMAL, _("Normal\tCtrl+0"), _("Normal")); // color scheme menu colorSchemeMenu = new wxMenu; colorSchemeMenu->AppendRadioItem( ID_COLOR_SCHEME_DEFAULT, _("&Default"), _("Default")); colorSchemeMenu->AppendRadioItem( ID_COLOR_SCHEME_REDUCED_GLARE, _("&Blue background, white text"), _("Blue background, white text")); colorSchemeMenu->AppendRadioItem( ID_COLOR_SCHEME_DEFAULT_BACKGROUND, _("&Light"), _("Light")); colorSchemeMenu->AppendRadioItem( ID_COLOR_SCHEME_NONE, _("&None"), _("None")); switch (properties.colorScheme) { case COLOR_SCHEME_DEFAULT: colorSchemeMenu->Check(ID_COLOR_SCHEME_DEFAULT, true); break; case COLOR_SCHEME_DEFAULT_BACKGROUND: colorSchemeMenu->Check(ID_COLOR_SCHEME_DEFAULT_BACKGROUND, true); break; case COLOR_SCHEME_REDUCED_GLARE: colorSchemeMenu->Check(ID_COLOR_SCHEME_REDUCED_GLARE, true); break; case COLOR_SCHEME_NONE: colorSchemeMenu->Check(ID_COLOR_SCHEME_NONE, true); break; default: break; } viewMenu = new wxMenu; // use class-wide data member viewMenu->Append(ID_PREVIOUS_DOCUMENT, _("&Previous Document\tCtrl+PgUp"), _("Previous Document")); viewMenu->Append(ID_NEXT_DOCUMENT, _("&Next Document\tCtrl+PgDn"), _("Next Document")); viewMenu->Append(ID_BROWSER, _("&Browser\tCtrl+B"), _("Browser")); viewMenu->AppendSeparator(); viewMenu->AppendRadioItem( ID_SHOW_TAGS, _("&Show Tags and Attributes\tCtrl+T"), _("Show Tags and Attributes")); viewMenu->AppendRadioItem( ID_HIDE_ATTRIBUTES, _("&Hide Attributes Only\tCtrl+Shift+A"), _("Hide Attributes Only")); viewMenu->AppendRadioItem( ID_HIDE_TAGS, _("H&ide Tags and Attributes\tCtrl+Shift+T"), _("Hide Tags and Attributes")); switch (visibilityState) { case SHOW_TAGS: viewMenu->Check(ID_SHOW_TAGS, true); break; case HIDE_TAGS: viewMenu->Check(ID_HIDE_TAGS, true); break; case HIDE_ATTRIBUTES: viewMenu->Check(ID_HIDE_ATTRIBUTES, true); break; default: viewMenu->Check(ID_SHOW_TAGS, true); break; } viewMenu->AppendSeparator(); viewMenu->Append( ID_TOGGLE_FOLD, _("&Toggle Fold"), _("Toggle Fold")); viewMenu->Append( ID_FOLD_ALL, _("&Fold Tags\tCtrl+Shift+F"), _("Fold Tags")); viewMenu->Append( ID_UNFOLD_ALL, _("&Unfold Tags\tCtrl+Shift+U"), _T("Unfold Tags")); viewMenu->AppendSeparator(); viewMenu->AppendCheckItem( ID_WRAP_WORDS, _("&Wrap Words\tCtrl+W"), _T("Wrap Words")); viewMenu->Check(ID_WRAP_WORDS, properties.wrap); viewMenu->Append(wxID_ANY, _("&Color Scheme"), colorSchemeMenu); viewMenu->Append(wxID_ANY, _("&Text Size"), fontSizeMenu); viewMenu->AppendSeparator(); viewMenu->AppendCheckItem( ID_LOCATION_PANE_VISIBLE, _("S&how Current Element Pane"), _("Show Current ElementPane")); viewMenu->Check(ID_LOCATION_PANE_VISIBLE, false); viewMenu->AppendCheckItem( ID_TOOLBAR_VISIBLE, _("Sh&ow Toolbar"), _("Show Toolbar")); viewMenu->Check(ID_TOOLBAR_VISIBLE, toolbarVisible); viewMenu->Append( ID_HIDE_PANE, _("C&lose Message Pane\tAlt+C"), _("Close Message Pane")); // insert menu wxMenu *insertMenu = new wxMenu; insertMenu->Append(ID_INSERT_CHILD, _("&Element...\tCtrl+I"), _("Element...")); insertMenu->Append(ID_INSERT_SIBLING, _("&Sibling...\tCtrl+Shift+I"), _("Sibling...")); insertMenu->Append(ID_INSERT_ENTITY, _("&Entity...\tCtrl+E"), _("Entity...")); insertMenu->AppendSeparator(); insertMenu->Append(ID_INSERT_TWIN, _("&Twin\tCtrl+Enter"), _("Twin")); insertMenu->AppendSeparator(); insertMenu->Append(ID_INSERT_SYMBOL, _("S&ymbol..."), _("Symbol...")); // validation menu wxMenu *validationMenu = new wxMenu; validationMenu->Append(ID_VALIDATE_DTD, _("&DTD\tF4"), _("DTD")); validationMenu->Append( ID_VALIDATE_W3C_SCHEMA, _("&XML Schema\tF5"), _("XML Schema")); validationMenu->AppendSeparator(); validationMenu->Append( ID_VALIDATE_RELAX_NG, _("&RELAX NG...\tF6"), _("RELAX NG...")); wxMenu *associateMenu = new wxMenu; associateMenu->Append(ID_ASSOCIATE_DTD_PUBLIC, _("&Public DTD..."), _("Public DTD...")); associateMenu->Append(ID_ASSOCIATE_DTD_SYSTEM, _("&System DTD..."), _("System DTD...")); associateMenu->Append(ID_ASSOCIATE_W3C_SCHEMA, _("&XML Schema..."), _("XML Schema...")); associateMenu->Append(ID_ASSOCIATE_XSL, _("XS< stylesheet..."), _("XSLT stylesheet...")); if (wxFileName::DirExists(rngDir)) { wxString rngMask, rngFile, displayName, shortcutString; rngMask = rngDir + wxFileName::GetPathSeparator() + _T("*.rng"); rngFile = wxFindFirstFile(rngMask, wxFILE); int id = ID_VALIDATE_PRESET1; if (!rngFile.empty()) { validationPresetMap.insert(make_pair(id, rngFile)); wxFileName::SplitPath(rngFile, NULL, NULL, &displayName, NULL); displayName.Replace(_T(".rng"), _T("")); shortcutString.Printf(_("\tCtrl+%i"), (id - ID_VALIDATE_PRESET1) + 1); validationMenu->Append(id, displayName + shortcutString, displayName); for (id = ID_VALIDATE_PRESET2; id <= ID_VALIDATE_PRESET9; ++id) { rngFile = wxFindNextFile(); if (rngFile.empty()) break; validationPresetMap.insert(make_pair(id, rngFile)); wxFileName::SplitPath(rngFile, NULL, NULL, &displayName, NULL); shortcutString.Printf(_("\tCtrl+%i"), (id - ID_VALIDATE_PRESET1) + 1); displayName.Replace(_T(".rng"), _T("")); validationMenu->Append(id, displayName + shortcutString, displayName); } } } // xsl menu wxMenu *xslMenu = new wxMenu; xslMenu->Append(ID_XSLT, _("&XSL Transform...\tF8"), _("XSL Transform...")); xslMenu->AppendSeparator(); xslMenu->Append( ID_XSLT_DOCBOOK_HTML, _("&DocBook to HTML\tAlt+1"), _("DocBook to HTML")); xslMenu->Append( ID_XSLT_DOCBOOK_XHTML, _("&DocBook to XHTML\tAlt+2"), _("DocBook to XHTML")); xslMenu->Append( ID_XSLT_DOCBOOK_FO, _("D&ocBook to XSL-FO\tAlt+3"), _("DocBook to XSL-FO")); xslMenu->Append( ID_XSLT_TEI_HTML, _("&TEI to HTML\tAlt+4"), _("TEI to HTML")); xslMenu->Append( ID_XSLT_TEI_LATEX, _("T&EI to LaTeX\tAlt+5"), _("TEI to LaTeX")); xslMenu->Append( ID_XSLT_TEI_XHTML, _("TE&I to XHTML\tAlt+6"), _("TEI to XHTML")); xslMenu->Append( ID_XSLT_TEI_FO, _("TEI to &XSL-FO\tAlt+7"), _("TEI to XSL-FO")); // xml menu xmlMenu = new wxMenu; // use class-wide data member xmlMenu->Append( ID_CHECK_WELLFORMED, _("&Check Well-formedness\tF2"), _("Check Well-formedness")); xmlMenu->Append( wxID_ANY, _("&Validate"), validationMenu); xmlMenu->AppendSeparator(); xmlMenu->Append( wxID_ANY, _("&Associate"), associateMenu); xmlMenu->AppendSeparator(); xmlMenu->Append(wxID_ANY, _("&XSLT"), xslMenu); xmlMenu->Append( ID_XPATH, _("&Evaluate XPath...\tF9"), _("Evaluate XPath...")); xmlMenu->AppendSeparator(); xmlMenu->Append( ID_PRETTYPRINT, _("&Pretty-print\tF11"), _("Pretty-print")); xmlMenu->AppendSeparator(); xmlMenu->AppendCheckItem( ID_PROTECT_TAGS, _("&Lock Tags\tCtrl+L"), _("Lock Tags")); xmlMenu->Check(ID_PROTECT_TAGS, protectTags); xmlMenu->AppendSeparator(); xmlMenu->Append( ID_ENCODING, _("E&ncoding..."), _("Encoding...")); // tools menu wxMenu *toolsMenu = new wxMenu; wxMenuItem *spellingItem = new wxMenuItem( NULL, ID_SPELL, _("&Spelling and Style...\tF7"), _("Spelling and Style...")); spellingItem->SetBitmap(spelling16Bitmap); wxMenuItem *wordCountItem = new wxMenuItem( NULL, ID_WORD_COUNT, _("&Word Count"), _("Word Count")); wordCountItem->SetBitmap(wxNullBitmap); wxMenuItem *commandItem = new wxMenuItem( NULL, ID_COMMAND, _("&Command\tCtrl+Alt+C"), _("Command")); commandItem->SetBitmap(wxNullBitmap); wxMenuItem *optionsItem = new wxMenuItem( NULL, ID_OPTIONS, _("&Options..."), _("Options...")); optionsItem->SetBitmap(wxNullBitmap); toolsMenu->Append(spellingItem); toolsMenu->Append(wordCountItem); toolsMenu->AppendSeparator(); toolsMenu->Append(commandItem); toolsMenu->AppendSeparator(); toolsMenu->Append(optionsItem); // help menu wxMenu *helpMenu = new wxMenu; wxMenuItem *helpItem = new wxMenuItem(NULL, wxID_HELP, _("&XML Copy Editor Help\tF1"), _("Help")); helpItem->SetBitmap(helpBitmap); wxMenuItem *homeItem = new wxMenuItem(NULL, ID_HOME, _("&Home Page"), _("Home Page")); homeItem->SetBitmap(wxNullBitmap); wxMenuItem *feedbackItem = new wxMenuItem(NULL, ID_FEEDBACK, _("&Forum"), _("Forum")); feedbackItem->SetBitmap(wxNullBitmap); wxMenuItem *aboutItem = new wxMenuItem(NULL, wxID_ABOUT, _("&About XML Copy Editor"), _("About")); aboutItem->SetBitmap(wxNullBitmap); wxMenuItem *downloadSourceItem = new wxMenuItem(NULL, ID_DOWNLOAD_SOURCE, _("&Download Source"), _("Download Source")); downloadSourceItem->SetBitmap(wxNullBitmap); helpMenu->Append(helpItem); helpMenu->AppendSeparator(); helpMenu->Append(homeItem); helpMenu->Append(feedbackItem); helpMenu->Append(downloadSourceItem); helpMenu->AppendSeparator(); helpMenu->Append(aboutItem); MyMenuBar *menuBar = new MyMenuBar(wxMB_DOCKABLE); menuBar->Append(fileMenu, _("&File")); menuBar->Append(editMenu, _("&Edit")); menuBar->Append(viewMenu, _("&View")); menuBar->Append(insertMenu, _("&Insert")); menuBar->Append(xmlMenu, _("&XML")); menuBar->Append(toolsMenu, _("&Tools")); menuBar->Append(helpMenu, _("&Help")); return menuBar; } void MyFrame::updateFileMenu(bool deleteExisting) { if (deleteExisting) { wxMenuItemList list = fileMenu->GetMenuItems(); size_t count = list.size(); for (size_t i = 0; i < count; ++i) fileMenu->Delete(list[i]); } wxMenuItem *newItem = new wxMenuItem(NULL, wxID_NEW, _("&New...\tCtrl+N"), _("New...")); newItem->SetBitmap(new16Bitmap); wxMenuItem *openItem = new wxMenuItem(NULL, wxID_OPEN, _("&Open...\tCtrl+O"), _("Open...")); openItem->SetBitmap(open16Bitmap); wxMenuItem *openLargeFileItem = new wxMenuItem(NULL, ID_OPEN_LARGE_FILE, _("O&pen Large Document...\tCtrl+Shift+O"), _("Open Large Document...")); openLargeFileItem->SetBitmap(wxNullBitmap); wxMenuItem *closeItem = new wxMenuItem(NULL, wxID_CLOSE, _("&Close\tCtrl+F4"), _("Close")); closeItem->SetBitmap(wxNullBitmap); wxMenuItem *closeAllItem = new wxMenuItem(NULL, wxID_CLOSE_ALL, _("C&lose All"), _("Close All")); closeAllItem->SetBitmap(wxNullBitmap); wxMenuItem *saveItem = new wxMenuItem(NULL, wxID_SAVE, _("&Save\tCtrl+S"), _("Save")); saveItem->SetBitmap(save16Bitmap); wxMenuItem *saveAsItem = new wxMenuItem(NULL, wxID_SAVEAS, _("S&ave As...\tF12"), _("Save As...")); saveAsItem->SetBitmap(wxNullBitmap); wxMenuItem *revertItem = new wxMenuItem(NULL, wxID_REVERT, _("&Revert"), _("Revert")); revertItem->SetBitmap(wxNullBitmap); wxMenuItem *printSetupItem = new wxMenuItem(NULL, ID_PRINT_SETUP, _("Pa&ge Setup..."), _("Page Setup...")); printSetupItem->SetBitmap(wxNullBitmap); wxMenuItem *printPreviewItem = new wxMenuItem(NULL, ID_PRINT_PREVIEW, _("P&rint Preview..."), _("Print Preview...")); printPreviewItem->SetBitmap(printPreviewBitmap); wxMenuItem *printItem = new wxMenuItem(NULL, ID_PRINT, _("Pr&int...\tCtrl+P"), _("Print...")); printItem->SetBitmap(print16Bitmap); wxMenuItem *importMSWordItem = new wxMenuItem( NULL, ID_IMPORT_MSWORD, _("I&mport Microsoft Word Document...")); importMSWordItem->SetBitmap(wxNullBitmap); wxMenuItem *exportMSWordItem = new wxMenuItem( NULL, ID_EXPORT_MSWORD, _("&Export Microsoft Word Document...")); exportMSWordItem->SetBitmap(wxNullBitmap); wxMenuItem *exitItem = new wxMenuItem(NULL, wxID_EXIT, _("E&xit"), _("Exit")); exitItem->SetBitmap(wxNullBitmap); fileMenu->Append(newItem); fileMenu->Append(openItem); fileMenu->Append(openLargeFileItem); fileMenu->AppendSeparator(); fileMenu->Append(closeItem); fileMenu->Append(closeAllItem); fileMenu->Append(saveItem); fileMenu->Append(saveAsItem); fileMenu->Append(revertItem); fileMenu->AppendSeparator(); fileMenu->Append(printSetupItem); fileMenu->Append(printPreviewItem); fileMenu->Append(printItem); #ifdef __WXMSW__ fileMenu->AppendSeparator(); fileMenu->Append(importMSWordItem); fileMenu->Append(exportMSWordItem); #endif history.AddFilesToMenu(fileMenu); fileMenu->AppendSeparator(); fileMenu->Append(exitItem); } MyToolBar *MyFrame::getToolBar() { MyToolBar *myToolBar = new MyToolBar( this, ID_TOOLBAR, wxDefaultPosition, wxDefaultSize, wxTB_FLAT | wxTB_HORIZONTAL | wxTB_DOCKABLE); int w, h; #ifdef __WXMSW__ w = saveBitmap.GetWidth(), h = saveBitmap.GetHeight(); #else w = h = 24; #endif myToolBar->SetToolBitmapSize(wxSize(w, h)); myToolBar->AddTool( wxID_NEW, _("New"), newBitmap, _("New")); myToolBar->AddTool( wxID_OPEN, _("Open"), openBitmap, _("Open")); myToolBar->AddTool( wxID_SAVE, _("Save"), saveBitmap, wxNullBitmap, wxITEM_NORMAL, _("Save")); myToolBar->AddTool( ID_PRINT, _("Print"), printBitmap, wxNullBitmap, wxITEM_NORMAL, _("Print")); myToolBar->AddTool( ID_BROWSER, _("Browser"), internetBitmap, wxNullBitmap, wxITEM_NORMAL, _("Browser")); myToolBar->AddTool( ID_SPELL, _("Spelling and Style"), spellingBitmap, wxNullBitmap, wxITEM_NORMAL, _("Spelling and Style")); myToolBar->AddCheckTool( ID_PROTECT_TAGS, _("Lock Tags"), hyperlinkBitmap, wxNullBitmap, _("Lock Tags")); myToolBar->ToggleTool( ID_PROTECT_TAGS, protectTags); myToolBar->Realize(); return myToolBar; } XmlDoc *MyFrame::getActiveDocument() { if (!mainBook->GetPageCount()) return NULL; return (XmlDoc *)mainBook->GetPage(mainBook->GetSelection()); } void MyFrame::addSafeSeparator(wxToolBar *toolBar) { if (xpThemeActive()) { toolBar->AddSeparator(); return; } wxStaticText *staticControl = new wxStaticText( toolBar, wxID_ANY, _T(" ")); toolBar->AddControl(staticControl); } void MyFrame::statusProgress(const wxString& s) { wxStatusBar *status = GetStatusBar(); if (!status) return; status->SetStatusText(s, 0); } void MyFrame::messagePane(const wxString& s, int iconType) { wxString paneTitle; switch (iconType) { case (CONST_INFO): if (s.Length() < 50) // magic no. necessary? { statusProgress(s); return; } paneTitle = _("Information"); break; case (CONST_WARNING): paneTitle = _("Warning"); break; case (CONST_STOP): paneTitle = _("Stopped"); break; case (CONST_QUESTION): paneTitle = _("Question"); break; default: paneTitle = _("Message"); break; } wxAuiPaneInfo info = manager.GetPane(htmlReport); if (!info.IsShown()) { manager.GetPane(htmlReport).Show(true); manager.Update(); } manager.GetPane(htmlReport).Caption(paneTitle); wxString htmlString = s; htmlString.Replace(_T("&"), _T("&"), true); htmlString.Replace(_T("<"), _T("<"), true); htmlString.Replace(_T(">"), _T(">"), true); wxString htmlBuffer; htmlBuffer += _T("
"); htmlBuffer += htmlString; htmlBuffer += _T("
"); htmlReport->SetPage(htmlBuffer); manager.Update(); } void MyFrame::documentOk(const wxString& status) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; wxString message; message.Printf(_("%s is %s"), doc->getShortFileName().c_str(), status.c_str()); messagePane(message, CONST_INFO); } void MyFrame::applyEditorProperties(bool zoomOnly) { XmlDoc *doc; size_t documentCount = mainBook->GetPageCount(); for (size_t i = 0; i < documentCount; i++) { doc = (XmlDoc *)mainBook->GetPage(i); if (doc) { doc->applyProperties(properties, zoomOnly); if (!properties.validateAsYouType) doc->clearErrorIndicators(); } } } void MyFrame::modifiedMessage() { messagePane( _("Document has been modified: save or discard changes"), CONST_STOP); } void MyFrame::xmliseWideTextNode(wxString& s) { s.Replace(_T("&"), _T("&"), true); s.Replace(_T("<"), _T("<"), true); s.Replace(_T(">"), _T(">"), true); } int MyFrame::getFileType(const wxString& fileName) { std::string fileNameLocal, fileNameLocalLC; fileNameLocal = fileName.mb_str(wxConvLocal); fileNameLocalLC = CaseHandler::lowerCase(fileNameLocal); if (fileNameLocalLC.find(".dtd") != std::string::npos || fileNameLocalLC.find(".ent") != std::string::npos) return FILE_TYPE_DTD; else if (fileNameLocalLC.find(".css") != std::string::npos) return FILE_TYPE_CSS; else if (fileNameLocalLC.find(".php") != std::string::npos) return FILE_TYPE_PHP; else if (fileNameLocalLC.find(".exe") != std::string::npos) return FILE_TYPE_BINARY; else if (fileNameLocalLC.find(".rnc") != std::string::npos) return FILE_TYPE_RNC; return FILE_TYPE_XML; } long MyFrame::getNotebookStyleMask() { /* if (notebookStyleMenu->IsChecked(ID_NOTEBOOK_STYLE_FLAT)) return wxFNB_FANCY_TABS | wxFNB_MOUSE_MIDDLE_CLOSES_TABS | wxFNB_X_ON_TAB; else if (notebookStyleMenu->IsChecked(ID_NOTEBOOK_STYLE_VC8)) return wxFNB_BACKGROUND_GRADIENT | wxFNB_VC8 | wxFNB_MOUSE_MIDDLE_CLOSES_TABS | wxFNB_X_ON_TAB | wxFNB_DROPDOWN_TABS_LIST | wxFNB_NO_NAV_BUTTONS; else return wxFNB_BACKGROUND_GRADIENT | wxFNB_VC8 | wxFNB_MOUSE_MIDDLE_CLOSES_TABS | wxFNB_COLORFUL_TABS | wxFNB_X_ON_TAB | wxFNB_DROPDOWN_TABS_LIST | wxFNB_NO_NAV_BUTTONS; //wxFNB_BACKGROUND_GRADIENT | wxFNB_VC8 | wxFNB_MOUSE_MIDDLE_CLOSES_TABS | wxFNB_COLORFUL_TABS; */ return 0; } bool MyFrame::isSpecialFileType(const wxString& fileName) { std::string fileNameLocal, fileNameLocalLC; fileNameLocal = fileName.mb_str(wxConvLocal); fileNameLocalLC = CaseHandler::lowerCase(fileNameLocal); return ( fileNameLocalLC.find(".dtd") != std::string::npos || fileNameLocalLC.find(".css") != std::string::npos || fileNameLocalLC.find(".php") != std::string::npos); } void MyFrame::encodingMessage() { wxString msg = _("Encoding should be one of "); msg += ENCODING_INFO; messagePane(msg, CONST_STOP); } void MyFrame::updatePaths() { ruleSetDir = applicationDir + wxFileName::GetPathSeparator() + _T("rulesets"); filterDir = applicationDir + wxFileName::GetPathSeparator() + _T("filters"); templateDir = applicationDir + wxFileName::GetPathSeparator() + _T("templates") + wxFileName::GetPathSeparator(); binDir = applicationDir + wxFileName::GetPathSeparator() + _T("bin") + wxFileName::GetPathSeparator(); helpDir = applicationDir + wxFileName::GetPathSeparator() + _T("help") + wxFileName::GetPathSeparator(); rngDir = applicationDir + wxFileName::GetPathSeparator() + _T("rng") + wxFileName::GetPathSeparator(); htmlDir = applicationDir + wxFileName::GetPathSeparator() + _T("html") + wxFileName::GetPathSeparator(); pngDir = applicationDir + wxFileName::GetPathSeparator() + _T("png") + wxFileName::GetPathSeparator(); wxString wideCatalogPath = applicationDir + wxFileName::GetPathSeparator() + _T("catalog") + wxFileName::GetPathSeparator() + _T("catalog"); catalogPath = wideCatalogPath.mb_str(wxConvLocal); wxString wideXslDtdPath = applicationDir + wxFileName::GetPathSeparator() + _T("dtd") + wxFileName::GetPathSeparator() + _T("xslt10.dtd"); xslDtdPath = wideXslDtdPath.mb_str(wxConvLocal); wxString wideRssDtdPath = applicationDir + wxFileName::GetPathSeparator() + _T("dtd") + wxFileName::GetPathSeparator() + _T("rss2.dtd"); rssDtdPath = wideRssDtdPath.mb_str(wxConvLocal); wxString wideXtmDtdPath = applicationDir + wxFileName::GetPathSeparator() + _T("dtd") + wxFileName::GetPathSeparator() + _T("xtm1.dtd"); xtmDtdPath = wideXtmDtdPath.mb_str(wxConvLocal); wxString wideLzxDtdPath = applicationDir + wxFileName::GetPathSeparator() + _T("dtd") + wxFileName::GetPathSeparator() + _T("lzx.dtd"); lzxDtdPath = wideLzxDtdPath.mb_str(wxConvLocal); wxString wideXliffDtdPath = applicationDir + wxFileName::GetPathSeparator() + _T("dtd") + wxFileName::GetPathSeparator() + _T("xliff.dtd"); xliffDtdPath = wideXliffDtdPath.mb_str(wxConvLocal); } void MyFrame::OnAssociate(wxCommandEvent& event) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; wxString title, label, type, extension, path, defaulturl, defaultaux; wxString auxiliaryLabel; int id = event.GetId(); switch (id) { case ID_ASSOCIATE_DTD_PUBLIC: type = _("Public DTD"); extension = _T("*.dtd"); defaulturl = lastDtdPublic; defaultaux = lastDtdPublicAux; break; case ID_ASSOCIATE_DTD_SYSTEM: type = _("System DTD"); extension = _T("*.dtd"); defaulturl = lastDtdSystem; defaultaux = _T(""); break; case ID_ASSOCIATE_W3C_SCHEMA: type = _("XML Schema"); extension = _T("*.xsd"); defaulturl = lastSchema; defaultaux = _T(""); break; case ID_ASSOCIATE_XSL: type = _("XSLT stylesheet"); extension = _T("*.xsl;*.xslt"); defaulturl = lastXslStylesheet; defaultaux = _T(""); break; default: return; } std::string utf8Buffer; getRawText(doc, utf8Buffer); std::auto_ptr wellformedparser(new WrapExpat()); if (!wellformedparser->parse(utf8Buffer)) { std::string error = wellformedparser->getLastError(); wxString wideError = wxString(error.c_str(), wxConvUTF8, error.size()); wxString message; message.Printf( _("Cannot associate %s: %s"), type.c_str(), wideError.c_str()); messagePane(message, CONST_STOP); return; } title.Printf(_("Associate %s"), type.c_str()); label = _("Choose a file:"); bool auxiliaryBox = (id == ID_ASSOCIATE_DTD_PUBLIC); //(id == ID_ASSOCIATE_W3C_SCHEMA_NS || id == ID_ASSOCIATE_DTD_PUBLIC); if (auxiliaryBox) { auxiliaryLabel = _("Choose a public identifier:"); /* (id == ID_ASSOCIATE_DTD_PUBLIC) ? _("Choose a public identifier:") : _("Choose a namespace:"); */ } AssociateDialog ad( this, title, label, type, extension, defaulturl, auxiliaryBox, auxiliaryLabel, defaultaux); if (ad.ShowModal() != wxID_OK) return; path = ad.getUrl(); wxString aux, schemaPathMemory; if (auxiliaryBox) { aux = ad.getAux(); } std::string utf8Path = (const char *)path.mb_str(wxConvUTF8); std::string modifiedBuffer; // remember choice switch (id) { case ID_ASSOCIATE_W3C_SCHEMA: lastSchema = path; break; case ID_ASSOCIATE_DTD_PUBLIC: lastDtdPublic = path; lastDtdPublicAux = aux; break; case ID_ASSOCIATE_DTD_SYSTEM: lastDtdSystem = path; break; case ID_ASSOCIATE_XSL: lastXslStylesheet = path; break; default: break; } if (id == ID_ASSOCIATE_W3C_SCHEMA) { std::auto_ptr parser(new XmlAssociateXsd(utf8Path)); if (!parser->parse(utf8Buffer)) return; modifiedBuffer = parser->getBuffer(); } else if (id == ID_ASSOCIATE_DTD_SYSTEM || id == ID_ASSOCIATE_DTD_PUBLIC) { std::auto_ptr parser(new XmlAssociateDtd( utf8Path, (auxiliaryBox) ? (const char *)aux.mb_str(wxConvUTF8) : "")); if (!parser->parse(utf8Buffer)) return; modifiedBuffer = parser->getBuffer(); } else if (id == ID_ASSOCIATE_XSL) { std::auto_ptr parser(new XmlAssociateXsl( utf8Path)); if (!parser->parse(utf8Buffer)) return; modifiedBuffer = parser->getBuffer(); } else return; doc->SetTextRaw(modifiedBuffer.c_str()); doc->SetFocus(); } void MyFrame::openRememberedTabs() { if (openTabsOnClose.empty()) return; wchar_t *s, *it; s = it = (wchar_t *)openTabsOnClose.wc_str(); std::vector v; wxString buffer = wxEmptyString; for (; *it; it++) { if (*it == L'|') { if (!buffer.empty()) { v.push_back(buffer); } buffer = wxEmptyString; } else buffer += *it; } if (!buffer.empty()) { v.push_back(buffer); } if (v.empty()) return; std::vector::iterator vit; for (vit = v.begin(); vit != v.end(); vit++) { if (!openFile(*vit)) break; } XmlDoc *doc; if ((doc = getActiveDocument()) != NULL) doc->SetFocus(); } void MyFrame::getRawText(XmlDoc *doc, std::string& buffer) { if (!doc) { buffer = ""; return; } //wxString wideBuffer = doc->GetText(); //buffer = wideBuffer.mb_str(wxConvUTF8); buffer = doc->myGetTextRaw(); } void MyFrame::OnWordCount(wxCommandEvent& event) { XmlDoc *doc; if ((doc = getActiveDocument()) == NULL) return; wxString wideBuffer; std::string buffer; wideBuffer = doc->GetText(); buffer = wideBuffer.mb_str(wxConvUTF8); auto_ptr xwc(new XmlWordCount()); wxString msg; if (!xwc->parse(buffer.c_str())) { std::string error = xwc->getLastError(); wxString werror = wxString(error.c_str(), wxConvUTF8, error.size()); statusProgress(wxEmptyString); msg.Printf(_("Cannot count words: %s"), werror.c_str()); messagePane(msg, CONST_STOP); return; } int count = xwc->getWordCount(); msg.Printf( ngettext(L"%s contains %i word", L"%s contains %i words", count), doc->getShortFileName().c_str(), count); messagePane(msg, CONST_INFO); doc->SetFocus(); } void MyFrame::removeUtf8Bom(std::string& buffer) { if (buffer.size() > 3 && (unsigned char)buffer[0] == 0xEF && (unsigned char)buffer[1] == 0xBB && (unsigned char)buffer[2] == 0xBF) { buffer.erase(0, 3); } } void MyFrame::loadBitmaps() { #ifdef __WXMSW__ // toolbar icons newBitmap = wxBITMAP(stock_new); openBitmap = wxBITMAP(stock_open); saveBitmap = wxBITMAP(stock_save); printBitmap = wxBITMAP(stock_print); spellingBitmap = wxBITMAP(stock_spellcheck); internetBitmap = wxBITMAP(stock_internet); hyperlinkBitmap = wxBITMAP(stock_hyperlink); filtersBitmap = wxBITMAP(stock_filters); // menu icons new16Bitmap = wxBITMAP(stock_new_16); open16Bitmap = wxBITMAP(stock_open_16); save16Bitmap = wxBITMAP(stock_save_16); printPreviewBitmap = wxBITMAP(stock_print_preview_16); print16Bitmap = wxBITMAP(stock_print_16); undo16Bitmap = wxBITMAP(stock_undo_16); redo16Bitmap = wxBITMAP(stock_redo_16); cutBitmap = wxBITMAP(stock_cut_16); copyBitmap = wxBITMAP(stock_copy_16); pasteBitmap = wxBITMAP(stock_paste_16); findBitmap = wxBITMAP(stock_search_16); spelling16Bitmap = wxBITMAP(stock_spellcheck_16); helpBitmap = wxBITMAP(stock_help_16); #else // toolbar icons newBitmap.LoadFile(pngDir + _T("stock_new.png"), wxBITMAP_TYPE_PNG); openBitmap.LoadFile(pngDir + _T("stock_open.png"), wxBITMAP_TYPE_PNG); saveBitmap.LoadFile(pngDir + _T("stock_save.png"), wxBITMAP_TYPE_PNG); printBitmap.LoadFile(pngDir + _T("stock_print.png"), wxBITMAP_TYPE_PNG); spellingBitmap.LoadFile(pngDir + _T("stock_spellcheck.png"), wxBITMAP_TYPE_PNG); internetBitmap.LoadFile(pngDir + _T("stock_internet.png"), wxBITMAP_TYPE_PNG); hyperlinkBitmap.LoadFile(pngDir + _T("stock_hyperlink.png"), wxBITMAP_TYPE_PNG); filtersBitmap.LoadFile(pngDir + _T("stock_filters.png"), wxBITMAP_TYPE_PNG); // menu icons new16Bitmap.LoadFile(pngDir + _T("stock_new-16.png"), wxBITMAP_TYPE_PNG); open16Bitmap.LoadFile(pngDir + _T("stock_open-16.png"), wxBITMAP_TYPE_PNG); save16Bitmap.LoadFile(pngDir + _T("stock_save-16.png"), wxBITMAP_TYPE_PNG); printPreviewBitmap.LoadFile(pngDir + _T("stock_print_preview.png"), wxBITMAP_TYPE_PNG); print16Bitmap.LoadFile(pngDir + _T("stock_print-16.png"), wxBITMAP_TYPE_PNG); undo16Bitmap.LoadFile(pngDir + _T("stock_undo-16.png"), wxBITMAP_TYPE_PNG); redo16Bitmap.LoadFile(pngDir + _T("stock_redo-16.png"), wxBITMAP_TYPE_PNG); cutBitmap.LoadFile(pngDir + _T("stock_cut-16.png"), wxBITMAP_TYPE_PNG); copyBitmap.LoadFile(pngDir + _T("stock_copy-16.png"), wxBITMAP_TYPE_PNG); pasteBitmap.LoadFile(pngDir + _T("stock_paste-16.png"), wxBITMAP_TYPE_PNG); findBitmap.LoadFile(pngDir + _T("stock_find-16.png"), wxBITMAP_TYPE_PNG); spelling16Bitmap.LoadFile(pngDir + _T("stock_spellcheck-16.png"), wxBITMAP_TYPE_PNG); helpBitmap.LoadFile(pngDir + _T("stock_help-16.png"), wxBITMAP_TYPE_PNG); #endif } #ifdef __WXMSW__ void MyFrame::OnDropFiles(wxDropFilesEvent& event) { int no = event.GetNumberOfFiles(); wxString *iterator = event.GetFiles(); if (!no || !iterator) return; for (int i = 0; i < no; i++, iterator++) { if (!openFile(*iterator)) break; } } #endif std::string MyFrame::getAuxPath(const std::string& fileName) { if (fileName.find(".xsl") != std::string::npos || fileName.find(".XSL") != std::string::npos) return xslDtdPath; else if (fileName.find(".rss") != std::string::npos || fileName.find(".RSS") != std::string::npos) return rssDtdPath; else if (fileName.find(".xtm") != std::string::npos || fileName.find(".xtmm") != std::string::npos || fileName.find(".XTM") != std::string::npos || fileName.find(".XTMM") != std::string::npos) return xtmDtdPath; else if (fileName.find(".lzx") != std::string::npos || fileName.find(".LZX") != std::string::npos) return lzxDtdPath; else if (fileName.find(".xlf") != std::string::npos || fileName.find(".XLF") != std::string::npos) return xliffDtdPath; return ""; } void MyFrame::OnActivateApp(wxActivateEvent& event) { event.Skip(); if (!mainBook || !event.GetActive()) return; restoreFocusToNotebook = true; } void MyFrame::OnIconize(wxIconizeEvent& event) { event.Skip(); if (event.Iconized()) return; restoreFocusToNotebook = true; } void MyFrame::OnKeyPressed(wxKeyEvent& event) { event.Skip(); } void MyFrame::setStrictScrolling(bool b) { XmlDoc *doc; doc = getActiveDocument(); if (!doc) return; doc->SetYCaretPolicy((b) ? (wxSTC_CARET_STRICT | wxSTC_CARET_SLOP) : wxSTC_CARET_EVEN, (b) ? 10 : 0); }