1 /*
2  * Copyright 2005-2007 Gerald Schmidt.
3  *
4  * This file is part of Xml Copy Editor.
5  *
6  * Xml Copy Editor is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * Xml Copy Editor is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Xml Copy Editor; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20 
21 #include <iostream>
22 #include <fstream>
23 #include <string>
24 #include <wx/aboutdlg.h>
25 #include "xmlcopyeditor.h"
26 #include "xmlcopyeditorcopy.h"
27 #include "readfile.h"
28 #include "xmldoc.h"
29 #include "xmlctrl.h"
30 #include "wraplibxml.h"
31 #include "xmlschemalocator.h"
32 #include "xsllocator.h"
33 #include "xmlutf8reader.h"
34 #include "xmlpromptgenerator.h"
35 #include "xmlencodingspy.h"
36 #include "styledialog.h"
37 #include "mypropertysheet.h"
38 #include "wraptempfilename.h"
39 #include "globalreplacedialog.h"
40 #include "replace.h"
41 #include "associatedialog.h"
42 #include "xmlassociatexsd.h"
43 #include "xmlassociatexsl.h"
44 #include "xmlassociatedtd.h"
45 #include "wrapdaisy.h"
46 #include "aboutdialog.h"
47 #include "pathresolver.h"
48 #include "locationpanel.h"
49 #include "insertpanel.h"
50 #include "xmlwordcount.h"
51 #include "mynotebook.h"
52 #include "commandpanel.h"
53 #include "binaryfile.h"
54 #include "exportdialog.h"
55 #include <wx/aui/auibook.h>
56 #include <wx/richtext/richtextsymboldlg.h>
57 #include <wx/textctrl.h>
58 #include <wx/artprov.h>
59 #include <wx/stockitem.h>
60 #include <iconv.h>
61 #include <wx/stdpaths.h>
62 #include <wx/tokenzr.h>
63 #include <wx/dir.h>
64 #include "xmlschemagenerator.h"
65 #include "threadreaper.h"
66 #include <wx/wupdlock.h>
67 #include "dtd2schema.h"
68 #include "myipc.h"
69 #include <wx/debug.h>
70 
71 #ifdef NEWFINDREPLACE
72 #include "findreplacepanel.h"
73 #endif
74 
75 #include "wrapxerces.h"
76 #ifndef __WXMSW__
77 #include "xpm/appicon.xpm"
78 #endif
79 
80 typedef size_t universal_iconv (iconv_t cd,
81         char* * inbuf, size_t * inbytesleft,
82         char* * outbuf, size_t * outbytesleft);
83 /* On other platform, it could be:
84 size_t iconv (iconv_t cd,
85         const char* * inbuf, size_t * inbytesleft,
86         char* * outbuf, size_t * outbytesleft);
87 and a char ** can't be assigned to const char **
88     http://c-faq.com/ansi/constmismatch.html
89 Let's deal with this mess.
90 */
91 
BEGIN_EVENT_TABLE(MyFrame,wxFrame)92 BEGIN_EVENT_TABLE ( MyFrame, wxFrame )
93 	EVT_ACTIVATE_APP ( MyFrame::OnActivateApp )
94 	EVT_CLOSE ( MyFrame::OnFrameClose )
95 	EVT_KEY_DOWN ( MyFrame::OnKeyPressed )
96 	EVT_MENU ( wxID_ABOUT, MyFrame::OnAbout )
97 	EVT_MENU ( wxID_CLOSE, MyFrame::OnClose )
98 	EVT_MENU ( wxID_CLOSE_ALL, MyFrame::OnCloseAll )
99 	EVT_MENU ( wxID_CUT, MyFrame::OnCut )
100 	EVT_MENU ( wxID_COPY, MyFrame::OnCopy )
101 	EVT_MENU ( wxID_HELP, MyFrame::OnHelp )
102 	EVT_MENU ( wxID_PASTE, MyFrame::OnPaste )
103 	EVT_MENU ( ID_PASTE_NEW_DOCUMENT, MyFrame::OnPasteNewDocument )
104 	EVT_MENU ( wxID_EXIT, MyFrame::OnQuit )
105 	EVT_MENU ( wxID_NEW, MyFrame::OnNew )
106 	EVT_MENU ( wxID_OPEN, MyFrame::OnOpen )
107 	EVT_MENU ( wxID_SAVE, MyFrame::OnSave )
108 	EVT_MENU ( wxID_SAVEAS, MyFrame::OnSaveAs )
109 	EVT_MENU ( ID_RELOAD, MyFrame::OnReload )
110 	EVT_MENU ( wxID_UNDO, MyFrame::OnUndo )
111 	EVT_MENU ( wxID_REDO, MyFrame::OnRedo )
112 	EVT_MENU ( wxID_REVERT, MyFrame::OnRevert )
113 	EVT_MENU ( ID_INSERT_CHILD, MyFrame::OnInsertChild )
114 	EVT_MENU ( ID_INSERT_SIBLING, MyFrame::OnInsertSibling )
115 	EVT_MENU ( ID_INSERT_ENTITY, MyFrame::OnInsertEntity )
116 	EVT_MENU ( ID_INSERT_TWIN, MyFrame::OnInsertTwin )
117 	EVT_MENU ( ID_INSERT_SYMBOL, MyFrame::OnInsertSymbol )
118 	EVT_MENU ( ID_TOGGLE_FOLD, MyFrame::OnToggleFold )
119 	EVT_MENU ( ID_FOLD_ALL, MyFrame::OnFoldAll )
120 	EVT_MENU ( ID_UNFOLD_ALL, MyFrame::OnUnfoldAll )
121 	EVT_MENU ( ID_OPEN_LARGE_FILE, MyFrame::OnOpen )
122 	EVT_MENU ( ID_PRINT_PREVIEW, MyFrame::OnPrintPreview )
123 	EVT_MENU ( ID_PRINT_SETUP, MyFrame::OnPrintSetup )
124 	EVT_MENU ( ID_PRINT, MyFrame::OnPrint )
125 	EVT_MENU ( ID_WORD_COUNT, MyFrame::OnWordCount )
126 	EVT_MENU ( ID_IMPORT_MSWORD, MyFrame::OnImportMSWord )
127 	EVT_MENU ( ID_EXPORT_MSWORD, MyFrame::OnExportMSWord )
128 	EVT_MENU ( ID_EXPORT, MyFrame::OnExport )
129 	EVT_MENU ( ID_CLOSE_MESSAGE_PANE, MyFrame::OnCloseMessagePane )
130 	EVT_MENU ( ID_CLOSE_FIND_REPLACE_PANE, MyFrame::OnCloseFindReplacePane )
131 	EVT_MENU ( ID_CLOSE_COMMAND_PANE, MyFrame::OnCloseCommandPane )
132 	EVT_MENU ( ID_COMMAND, MyFrame::OnCommand )
133 	EVT_MENU ( ID_FIND, MyFrame::OnFind )
134 	EVT_MENU ( ID_FIND_AGAIN, MyFrame::OnFindAgain )
135 	EVT_MENU ( ID_GOTO, MyFrame::OnGoto )
136 	EVT_MENU ( ID_TOGGLE_COMMENT, MyFrame::OnToggleComment )
137 	EVT_MENU ( ID_FEEDBACK, MyFrame::OnFeedback )
138 	EVT_MENU ( ID_PREVIOUS_DOCUMENT, MyFrame::OnPreviousDocument )
139 	EVT_MENU ( ID_NEXT_DOCUMENT, MyFrame::OnNextDocument )
140 	EVT_MENU ( ID_BROWSER, MyFrame::OnBrowser )
141 	EVT_MENU ( ID_REPLACE, MyFrame::OnFindReplace )
142 	EVT_MENU ( ID_GLOBAL_REPLACE, MyFrame::OnGlobalReplace )
143 	EVT_MENU ( ID_CHECK_WELLFORMED, MyFrame::OnCheckWellformedness )
144 	EVT_MENU ( ID_VALIDATE_RELAX_NG, MyFrame::OnValidateRelaxNG )
145 	EVT_MENU ( ID_VALIDATE_W3C_SCHEMA, MyFrame::OnValidateSchema )
146 	EVT_MENU ( ID_CREATE_SCHEMA, MyFrame::OnCreateSchema )
147 	EVT_MENU ( ID_DTD_TO_SCHEMA, MyFrame::OnDtd2Schema )
148 	EVT_MENU ( ID_XPATH, MyFrame::OnXPath )
149 	EVT_MENU_RANGE ( ID_XSLT, ID_XSLT_WORDML_DOCBOOK, MyFrame::OnXslt )
150 	EVT_MENU ( ID_PRETTYPRINT, MyFrame::OnPrettyPrint )
151 	EVT_MENU ( ID_ENCODING, MyFrame::OnEncoding )
152 	EVT_MENU ( ID_STYLE, MyFrame::OnSpelling )
153 	EVT_MENU ( ID_SPELL, MyFrame::OnSpelling )
154 	EVT_MENU ( ID_FONT_SMALLER, MyFrame::OnFontSmaller )
155 	EVT_MENU ( ID_FONT_NORMAL, MyFrame::OnFontMedium )
156 	EVT_MENU ( ID_FONT_LARGER, MyFrame::OnFontLarger )
157 	EVT_MENU ( ID_OPTIONS, MyFrame::OnOptions )
158 	EVT_MENU ( ID_HOME, MyFrame::OnHome )
159 	EVT_MENU ( ID_DOWNLOAD_SOURCE, MyFrame::OnDownloadSource )
160 	EVT_MENU ( ID_TOOLBAR_VISIBLE, MyFrame::OnToolbarVisible )
161 	EVT_MENU ( ID_LOCATION_PANE_VISIBLE, MyFrame::OnLocationPaneVisible )
162 	EVT_MENU ( ID_PROTECT_TAGS, MyFrame::OnProtectTags )
163 	EVT_MENU ( ID_WRAP_WORDS, MyFrame::OnWrapWords )
164 	EVT_MENU ( ID_COPY_XPATH, MyFrame::OnCopyXPath )
165 	EVT_MENU_RANGE ( ID_SHOW_TAGS, ID_HIDE_TAGS, MyFrame::OnVisibilityState )
166 	EVT_MENU_RANGE ( ID_ASSOCIATE_DTD_PUBLIC, ID_ASSOCIATE_XSL, MyFrame::OnAssociate )
167 	EVT_MENU_RANGE ( wxID_FILE1, wxID_FILE9, MyFrame::OnHistoryFile )
168 	EVT_MENU_RANGE (
169 	    ID_VALIDATE_PRESET1, ID_VALIDATE_PRESET9, MyFrame::OnValidatePreset )
170 	EVT_MENU_RANGE (
171 	    ID_COLOR_SCHEME_DEFAULT,
172 	    ID_COLOR_SCHEME_NONE,
173 	    MyFrame::OnColorScheme )
174 
175 	EVT_MENU_RANGE (
176 	    ID_SPLIT_TAB_TOP,
177 	    ID_SPLIT_TAB_LEFT,
178 	    MyFrame::OnSplitTab )
179 
180 	EVT_UPDATE_UI_RANGE ( ID_REPLACE, ID_GLOBAL_REPLACE, MyFrame::OnUpdateReplaceRange )
181 	EVT_FIND ( wxID_ANY, MyFrame::OnDialogFind )
182 	EVT_FIND_NEXT ( wxID_ANY, MyFrame::OnDialogFind )
183 	EVT_FIND_REPLACE ( wxID_ANY, MyFrame::OnDialogReplace )
184 	EVT_FIND_REPLACE_ALL ( wxID_ANY, MyFrame::OnDialogReplaceAll )
185 	EVT_ICONIZE ( MyFrame::OnIconize )
186 	EVT_UPDATE_UI ( ID_LOCATION_PANE_VISIBLE, MyFrame::OnUpdateLocationPaneVisible )
187 	EVT_UPDATE_UI ( wxID_CLOSE, MyFrame::OnUpdateDocRange )
188 	EVT_UPDATE_UI ( wxID_SAVEAS, MyFrame::OnUpdateDocRange )
189 	EVT_UPDATE_UI ( wxID_CLOSE_ALL, MyFrame::OnUpdateCloseAll )
190 	EVT_UPDATE_UI_RANGE ( ID_SPLIT_TAB_TOP, ID_SPLIT_TAB_LEFT, MyFrame::OnUpdateCloseAll )
191 	EVT_UPDATE_UI ( wxID_REVERT, MyFrame::OnUpdateUndo )
192 	EVT_UPDATE_UI ( wxID_SAVE, MyFrame::OnUpdateDocRange ) // always allow save if doc present
193 	EVT_UPDATE_UI ( wxID_UNDO, MyFrame::OnUpdateUndo )
194 	EVT_UPDATE_UI ( wxID_REDO, MyFrame::OnUpdateRedo )
195 	EVT_UPDATE_UI ( wxID_PASTE, MyFrame::OnUpdatePaste )
196 	EVT_UPDATE_UI ( wxID_CUT, MyFrame::OnUpdateCutCopy )
197 	EVT_UPDATE_UI ( wxID_COPY, MyFrame::OnUpdateCutCopy )
198 	EVT_UPDATE_UI ( ID_FIND_AGAIN, MyFrame::OnUpdateFindAgain )
199 	EVT_UPDATE_UI ( ID_TOGGLE_COMMENT, MyFrame::OnUpdateToggleComment )
200 	EVT_UPDATE_UI_RANGE ( ID_FIND, ID_EXPORT_MSWORD, MyFrame::OnUpdateDocRange )
201 	EVT_UPDATE_UI ( ID_PREVIOUS_DOCUMENT, MyFrame::OnUpdatePreviousDocument )
202 	EVT_UPDATE_UI ( ID_NEXT_DOCUMENT, MyFrame::OnUpdateNextDocument )
203 	EVT_UPDATE_UI ( ID_CLOSE_MESSAGE_PANE, MyFrame::OnUpdateCloseMessagePane )
204 	EVT_UPDATE_UI ( ID_CLOSE_FIND_REPLACE_PANE, MyFrame::OnUpdateCloseFindReplacePane )
205 	EVT_UPDATE_UI ( ID_CLOSE_COMMAND_PANE, MyFrame::OnUpdateCloseCommandPane )
206 	EVT_UPDATE_UI ( ID_RELOAD, MyFrame::OnUpdateReload )
207 	EVT_UPDATE_UI ( ID_COPY_XPATH, MyFrame::OnUpdateCopyXPath )
208 	EVT_IDLE ( MyFrame::OnIdle )
209 	EVT_AUINOTEBOOK_PAGE_CLOSE ( wxID_ANY, MyFrame::OnPageClosing )
210 #ifdef __WXMSW__
211 	EVT_DROP_FILES ( MyFrame::OnDropFiles )
212 #endif
213 	EVT_NOTIFY ( myEVT_NOTIFY_PROMPT_GENERATED, wxID_ANY, MyFrame::OnPromptGenerated )
214 END_EVENT_TABLE()
215 
216 IMPLEMENT_APP ( MyApp)
217 
218 MyApp::MyApp()
219 	: checker ( NULL )
220 	, server ( NULL )
221 	, singleInstanceCheck ( false )
222 	, lang ( 0 )
223 #if defined(__WXMSW__) && !wxCHECK_VERSION(2,9,0)
224 	, config ( new wxFileConfig ( _T ( ".xmlcopyeditor" ) ) )//( _T ( "SourceForge Project\\XML Copy Editor" ) ) )
225 #else
226 	, config ( new wxFileConfig ( _T ( "xmlcopyeditor" ) ) )
227 #endif
228 {
229 #if wxCHECK_VERSION(2,9,0) && !defined ( __WXDEBUG__ )
230 	wxDisableAsserts();
231 #endif
232 
233 #if defined ( __WXGTK__ ) && !defined ( __WXDEBUG__ )
234 	int fdnull = open ( "/dev/null", O_WRONLY, 0 );
235 	dup2 ( fdnull, STDERR_FILENO );
236 #endif
237 }
238 
~MyApp()239 MyApp::~MyApp()
240 {
241 	delete checker;
242 	delete server;
243 }
244 
OnInit()245 bool MyApp::OnInit()
246 {
247 #ifdef __WXDEBUG__
248 	wxLog::SetActiveTarget ( new wxLogStderr() );
249 	wxLog::SetLogLevel ( wxLOG_Max );
250 #endif
251 
252 	int systemLocale = myLocale.GetSystemLanguage();
253 	switch ( systemLocale )
254 	{
255 		case wxLANGUAGE_GERMAN:
256 		case wxLANGUAGE_GERMAN_AUSTRIAN:
257 		case wxLANGUAGE_GERMAN_BELGIUM:
258 		case wxLANGUAGE_GERMAN_LIECHTENSTEIN:
259 		case wxLANGUAGE_GERMAN_LUXEMBOURG:
260 		case wxLANGUAGE_GERMAN_SWISS:
261 			systemLocale = wxLANGUAGE_GERMAN;
262 			break;
263 		case wxLANGUAGE_CHINESE_SIMPLIFIED:
264 			systemLocale = wxLANGUAGE_CHINESE_SIMPLIFIED;
265 			break;
266 		case wxLANGUAGE_CHINESE_TRADITIONAL:
267 			systemLocale = wxLANGUAGE_CHINESE_TRADITIONAL;
268 			break;
269 		case wxLANGUAGE_CATALAN:
270 			systemLocale = wxLANGUAGE_CATALAN;
271 			break;
272 		case wxLANGUAGE_SPANISH:
273 		case wxLANGUAGE_SPANISH_ARGENTINA:
274 		case wxLANGUAGE_SPANISH_BOLIVIA:
275 		case wxLANGUAGE_SPANISH_CHILE:
276 		case wxLANGUAGE_SPANISH_COLOMBIA:
277 		case wxLANGUAGE_SPANISH_COSTA_RICA:
278 		case wxLANGUAGE_SPANISH_DOMINICAN_REPUBLIC:
279 		case wxLANGUAGE_SPANISH_ECUADOR:
280 		case wxLANGUAGE_SPANISH_EL_SALVADOR:
281 		case wxLANGUAGE_SPANISH_GUATEMALA:
282 		case wxLANGUAGE_SPANISH_HONDURAS:
283 		case wxLANGUAGE_SPANISH_MEXICAN:
284 		case wxLANGUAGE_SPANISH_MODERN:
285 		case wxLANGUAGE_SPANISH_NICARAGUA:
286 		case wxLANGUAGE_SPANISH_PANAMA:
287 		case wxLANGUAGE_SPANISH_PARAGUAY:
288 		case wxLANGUAGE_SPANISH_PERU:
289 		case wxLANGUAGE_SPANISH_PUERTO_RICO:
290 		case wxLANGUAGE_SPANISH_URUGUAY:
291 		case wxLANGUAGE_SPANISH_US:
292 		case wxLANGUAGE_SPANISH_VENEZUELA:
293 			systemLocale = wxLANGUAGE_SPANISH;
294 			break;
295 		case wxLANGUAGE_SLOVAK:
296 			systemLocale = wxLANGUAGE_SLOVAK;
297 			break;
298 		case wxLANGUAGE_SWEDISH:
299 			systemLocale = wxLANGUAGE_SWEDISH;
300 			break;
301 		case wxLANGUAGE_FRENCH:
302 			systemLocale = wxLANGUAGE_FRENCH;
303 			break;
304 		case wxLANGUAGE_UKRAINIAN:
305 			systemLocale = wxLANGUAGE_UKRAINIAN;
306 			break;
307 		case wxLANGUAGE_ITALIAN:
308 			systemLocale = wxLANGUAGE_ITALIAN;
309 			break;
310 		case wxLANGUAGE_RUSSIAN:
311 			systemLocale = wxLANGUAGE_RUSSIAN;
312 			break;
313 		case wxLANGUAGE_DUTCH:
314 			systemLocale = wxLANGUAGE_DUTCH;
315 			break;
316 		default:
317 			systemLocale = wxLANGUAGE_DEFAULT;
318 			break;
319 	}
320 
321 	wxString dataDir = wxStandardPaths::Get().GetDataDir();
322 #ifdef __WXMSW__
323 	singleInstanceCheck = true;
324 #else
325 	singleInstanceCheck = false;
326 #endif
327 	if ( config.get() )
328 	{
329 		singleInstanceCheck = config->Read ( _T ( "singleInstanceCheck" ),
330 				singleInstanceCheck );
331 		lang = config->Read ( _T ( "lang" ), systemLocale );
332 		dataDir = config->Read ( _T ( "applicationDir" ), dataDir );
333 	}
334 	else
335 	{
336 		lang = systemLocale;
337 	}
338 
339 	if ( singleInstanceCheck )
340 	{
341 		wxString name;
342 		name.Printf ( _T ( "xmlcopyeditor-%s" ), wxGetUserId().c_str() );
343 		checker = new wxSingleInstanceChecker ( name );
344 		if ( checker->IsAnotherRunning() )
345 		{
346 			MyClient client;
347 			if ( client.talkToServer ( argc, argv ) )
348 				return false;
349 		}
350 	}
351 
352 	server = new MyServer;
353 	server->Create ( IPC_SERVICE );
354 
355 	myLocale.Init ( lang, wxLOCALE_LOAD_DEFAULT );
356 
357 	wxArrayString prefixes;
358 #ifdef __WXGTK__
359 	prefixes.Add ( _T ( "/usr/share/locale" ) );
360 	prefixes.Add ( _T ( "/usr/share/locale-langpack" ) );
361 	prefixes.Add ( _T ( "/usr/local/share/locale" ) );
362 #endif
363 	wxString poDir = dataDir + wxFileName::GetPathSeparator() + _T ( "po" )
364 			+ wxFileName::GetPathSeparator();
365 	prefixes.Add ( poDir );
366 	for ( size_t i = 0; i < prefixes.Count(); )
367 	{
368 		if ( wxDirExists ( prefixes[i] ) )
369 			wxLocale::AddCatalogLookupPathPrefix ( prefixes[i++] );
370 		else
371 			prefixes.RemoveAt ( i );
372 	}
373 
374 	wxString catalog = _T ( "xmlcopyeditor" );
375 	getAvailableTranslations ( &prefixes, &catalog );
376 
377 	if ( !myLocale.AddCatalog ( catalog ) )
378 	{}
379 
380 #ifndef __WXMSW__
381 	{
382 		wxLogNull noLog;
383 		myLocale.AddCatalog ( _T ( "coreutils" ) );
384 	}
385 #endif
386 
387 	MyFrame *frame;
388 	try
389 	{
390 		wxImage::AddHandler ( new wxPNGHandler );
391 		wxSystemOptions::SetOption ( _T ( "msw.remap" ), 0 );
392 
393 		frame = new MyFrame (
394 		    _ ( "XML Copy Editor" ),
395 		    config.get(),
396 		    myLocale,
397 		    singleInstanceCheck,
398 		    lang );
399 		frame->Show ( true );
400 
401 		bool rememberOpenTabs = config->Read ( _T ( "rememberOpenTabs" ), true );
402 		if ( rememberOpenTabs )
403 			frame->openRememberedTabs();
404 		else if ( !frame->getHandleCommandLineFlag() )
405 			frame->newDocument ( wxEmptyString );
406 
407 		if ( frame->getHandleCommandLineFlag() )
408 			frame->handleCommandLine();
409 	}
410 	catch ( const XMLException &e )
411 	{
412 		wxString error;
413 		error << _ ( "Failed to initialize Xerces-C:\n" )
414 		    << WrapXerces::toString ( e.getMessage() );
415 		wxMessageBox ( error, _ ( "Error" ), wxOK | wxICON_ERROR );
416 		return false;
417 	}
418 	catch ( exception &e )
419 	{
420 		const char *what;
421 		what = e.what();
422 		wxString wideWhat, errorString;
423 		wideWhat = wxString ( what, wxConvLocal, strlen ( what ) );
424 
425 		if ( wideWhat.empty() )
426 			wideWhat = _ ( "(unknown error)" );
427 
428 		errorString = _ ( "XML Copy Editor has encountered the following error and needs to close: " );
429 		errorString += wideWhat;
430 		errorString += _T ( "." );
431 #ifdef __WXMSW__
432 		::MessageBox (
433 		    NULL,
434 		    errorString,
435 		    _ ( "Error" ),
436 		    MB_ICONERROR | MB_TASKMODAL );
437 #else
438 		wxMessageBox ( errorString, _ ( "Error" ), wxICON_ERROR );
439 #endif
440 		exit ( EXIT_FAILURE );
441 	}
442 	catch ( ... )
443 	{
444 		exit ( EXIT_FAILURE );
445 	}
446 	return true;
447 }
448 
OnUnhandledException()449 void MyApp::OnUnhandledException()
450 {
451 #ifdef __WXMSW__
452 	::MessageBox (
453 	    NULL,
454 	    _ ( "XML Copy Editor has encountered an error and needs to close." ),
455 	    _ ( "Error" ),
456 	    MB_ICONERROR | MB_TASKMODAL );
457 #else
458 	wxMessageBox (
459 	    _ ( "XML Copy Editor has encountered an error and needs to close." ),
460 	    _ ( "Error" ),
461 	    wxICON_ERROR );
462 #endif
463 	exit ( EXIT_FAILURE );
464 }
465 
OnExceptionInMainLoop()466 bool MyApp::OnExceptionInMainLoop()
467 {
468 	try
469 	{
470 		throw;
471 	}
472 #ifdef __WXMSW__
473 	catch ( bad_alloc& )
474 	{
475 		::MessageBox (
476 		    NULL,
477 		    _ ( "The operating system has turned down a request for additional memory" ),
478 		    _ ( "Out of memory" ),
479 		    MB_ICONERROR );
480 		return true;
481 	}
482 #endif
483 	catch ( exception &e )
484 	{
485 		const char *what;
486 		what = e.what();
487 		wxString wideWhat, errorString;
488 		wideWhat = wxString ( what, wxConvLocal, strlen ( what ) );
489 
490 		if ( wideWhat.empty() )
491 			_ ( "(unknown error)" );
492 
493 		errorString = _ ( "The following error has occurred: " );
494 		errorString += wideWhat;
495 		errorString += _ ( ".\n\nSelect \"Abort\" to exit, \"Retry\" to close this window and \"Ignore\" to continue." );
496 #ifdef __WXMSW__
497 		int ret = ::MessageBox (
498 		              NULL,
499 		              errorString,
500 		              _ ( "Error" ),
501 		              MB_ABORTRETRYIGNORE |
502 		              MB_ICONERROR |
503 		              MB_TASKMODAL );
504 		switch ( ret )
505 		{
506 			case IDABORT:
507 				exit ( EXIT_FAILURE );
508 				break;
509 			case IDRETRY:
510 				return false;
511 			case IDIGNORE:
512 				return true;
513 			default:
514 				throw;
515 		}
516 #else
517 		// wxGTK does not reach this point; see HandleEvent below
518 		wxMessageBox (
519 		    errorString,
520 		    _ ( "Error" ),
521 		    wxICON_ERROR );
522 		return false;
523 #endif
524 	}
525 	catch ( ... )
526 	{
527 		wxString otherError ( _ ( "XML Copy Editor has encountered an error and needs to close." ) );
528 #ifdef __WXMSW__
529 		::MessageBox (
530 		    NULL,
531 		    otherError,
532 		    _ ( "Error" ),
533 		    MB_ICONERROR );
534 		return false;
535 #else
536 		wxMessageBox (
537 		    otherError,
538 		    _ ( "Error" ),
539 		    wxICON_ERROR );
540 		return false;
541 #endif
542 	}
543 	return false;
544 }
545 
546 #ifndef __WXMSW__
HandleEvent(wxEvtHandler * handler,wxEventFunction func,wxEvent & event) const547 void MyApp::HandleEvent ( wxEvtHandler *handler, wxEventFunction func, wxEvent& event ) const
548 {
549 	try
550 	{
551 		wxApp::HandleEvent ( handler, func, event );
552 	}
553 	catch ( std::bad_alloc& )
554 	{
555 		wxMessageBox (
556 		    _ ( "The operating system has turned down a request for additional memory" ),
557 		    _ ( "Out of memory" ),
558 		    wxICON_ERROR );
559 		return;
560 	}
561 	catch ( std::exception& e )
562 	{
563 		std::string s ( e.what() );
564 		wxString ws = wxString ( s.c_str(), wxConvUTF8, s.size() );
565 		wxMessageBox (
566 		    ws,
567 		    _ ( "Error" ),
568 		    wxICON_ERROR );
569 		return;
570 	}
571 	catch ( ... )
572 	{
573 		throw;
574 	}
575 }
576 #endif
577 
getAvailableTranslations(const wxArrayString * catalogLookupPathPrefixes,const wxString * catalog)578 const std::set<const wxLanguageInfo *> &MyApp::getAvailableTranslations (
579     const wxArrayString *catalogLookupPathPrefixes /*= NULL*/,
580     const wxString *catalog /*= NULL*/ )
581 {
582 	static class Translations // Most of the code was copied from wxTranslations
583 	{
584 	public:
585 		Translations ( const wxArrayString *catalogLookupPathPrefixes,
586 		    const wxString *catalog )
587 		{
588 			if ( catalogLookupPathPrefixes == NULL )
589 				throw std::invalid_argument ( "catalogLookupPathPrefixes" );
590 			if ( catalog == NULL )
591 				throw std::invalid_argument ( "catelog" );
592 
593 			const wxLanguageInfo *info;
594 #if wxCHECK_VERSION(2,9,0)
595 			wxTranslations *t = wxTranslations::Get();
596 			if ( t != NULL )
597 			{
598 				wxArrayString all = t->GetAvailableTranslations ( *catalog );
599 				wxArrayString::const_iterator trans = all.begin();
600 				for ( ; trans != all.end(); trans++ )
601 				{
602 					info = wxLocale::FindLanguageInfo ( *trans );
603 					if ( info != NULL )
604 						translations.insert ( info );
605 				}
606 			}
607 #else
608 			wxArrayString::const_iterator i = catalogLookupPathPrefixes->begin();
609 			for ( i = catalogLookupPathPrefixes->begin();
610 			    i != catalogLookupPathPrefixes->end(); ++i )
611 			{
612 				if ( i->empty() )
613 					continue;
614 
615 				wxDir dir;
616 				if ( !dir.Open(*i) )
617 					continue;
618 
619 				wxString lang;
620 				for ( bool ok = dir.GetFirst ( &lang, wxEmptyString, wxDIR_DIRS ); ok;
621 						ok = dir.GetNext (&lang) ) {
622 					const wxString langdir = *i + wxFILE_SEP_PATH + lang;
623 					if ( HasMsgCatalogInDir ( langdir, *catalog ) ) {
624 #ifdef __WXOSX__
625 						wxString rest;
626 						if ( lang.EndsWith(".lproj", &rest) )
627 						lang = rest;
628 #endif // __WXOSX__
629 						info = wxLocale::FindLanguageInfo ( lang );
630 						if ( info != NULL )
631 							translations.insert ( info );
632 					}
633 				}
634 			}
635 #endif
636 		}
637 		bool HasMsgCatalogInDir ( const wxString &dir, const wxString &catelog )
638 		{
639 			return wxFileName ( dir, catelog, _T ( "mo" ) ).FileExists()
640 				|| wxFileName ( dir + wxFILE_SEP_PATH + _T ( "LC_MESSAGES" ), catelog, _T ( "mo" ) ).FileExists();
641 		}
642 		const std::set<const wxLanguageInfo *> &operator()() { return translations; }
643 	protected:
644 		std::set<const wxLanguageInfo *> translations;
645 	} translations ( catalogLookupPathPrefixes, catalog );
646 
647 	return translations();
648 }
649 
MyFrame(const wxString & title,wxFileConfig * configParameter,wxLocale & locale,bool singleInstanceCheckParameter,int langParameter)650 MyFrame::MyFrame (
651     const wxString& title,
652     wxFileConfig *configParameter,
653     wxLocale& locale,
654     bool singleInstanceCheckParameter,
655     int langParameter ) :
656 		wxFrame ( NULL, wxID_ANY, title ),
657 		config ( configParameter ),
658 		myLocale ( locale ),
659 		singleInstanceCheck ( singleInstanceCheckParameter ),
660 		lang ( langParameter ),
661 		htmlPrinting ( new wxHtmlEasyPrinting (
662 		                   wxEmptyString,
663 		                   this ) ),
664 		findDialog ( 0 ),
665 		helpController ( new wxHtmlHelpController (
666 #ifdef __WXOSX__
667 					wxHF_CONTENTS | wxHF_INDEX | wxHF_SEARCH | wxHF_BOOKMARKS | wxHF_PRINT
668 #endif
669 		) ),
670 		menuBar ( 0 ),
671 		toolBar ( 0 ),
672 		xmlMenu ( 0 ),
673 		mainBook ( 0 ),
674 		restoreFocusToNotebook ( false )
675 {
676 	manager.SetManagedWindow ( this );
677 
678 	lastPos = 0;
679 	htmlReport = NULL;
680 	lastDoc = NULL;
681 
682 	wxString defaultFont = wxSystemSettings::GetFont ( wxSYS_ANSI_VAR_FONT ).GetFaceName();
683 
684 	bool findMatchCase;
685 
686 	// fetch configuration
687 	if ( config ) // config found
688 	{
689 		history.Load ( *config );
690 		properties.insertCloseTag =
691 		    config->Read ( _T ( "insertCloseTag" ), true );
692 		properties.completion =
693 		    config->Read ( _T ( "completion" ), true );
694 		properties.number =
695 		    config->Read ( _T ( "number" ), true );
696 		properties.fold =
697 		    config->Read ( _T ( "fold" ), true );
698 		properties.foldCompact =
699 		    config->Read ( _T ( "foldCompact" ), true );
700 		properties.currentLine =
701 		    config->Read ( _T ( "currentLine" ), true );
702 		properties.highlightSyntax =
703 		    config->Read ( _T ( "highlightSyntax" ), true );
704 		properties.whitespaceVisible =
705 		    config->Read ( _T ( "whitespaceVisible" ), true );
706 		properties.indentLines =
707 		    config->Read ( _T ( "indentLines" ), true );
708 		properties.toggleLineBackground =
709 		    config->Read ( _T ( "toggleLineBackground" ), true );
710 		properties.protectHiddenElements =
711 		    config->Read ( _T ( "protectHiddenElements" ), true );
712 		properties.deleteWholeTag =
713 		    config->Read ( _T ( "deleteWholeTag" ), true );
714 		properties.validateAsYouType =
715 		    config->Read ( _T ( "validateAsYouType" ), true );
716 		properties.font =
717 		    config->Read ( _T ( "font" ), defaultFont );
718 		findRegex =
719 		    config->Read ( _T ( "findRegex" ), true );
720 		xpathExpression =
721 		    config->Read ( _T ( "xpathExpression" ), wxEmptyString );
722 		lastXslStylesheet =
723 		    config->Read ( _T ( "lastXslStylesheet" ), wxEmptyString );
724 		lastRelaxNGSchema =
725 		    config->Read ( _T ( "lastRelaxNGSchema" ), wxEmptyString );
726 
727 		exportQuiet =
728 		  config->Read ( _T ( "exportQuiet" ), (long)true );
729 		exportMp3Album =
730 		  config->Read ( _T ( "exportMp3Album" ), (long)true );
731         exportSuppressOptional =
732             config->Read ( _T ( "exportSuppressOptional" ), (long)true );
733         exportHtml =
734             config->Read ( _T ( "exportHtml" ), (long)true );
735         exportEpub =
736             config->Read ( _T ( "exportEpub" ), (long)true );
737         exportRtf =
738             config->Read ( _T ( "exportRtf" ), (long)true );
739         exportDoc =
740             config->Read ( _T ( "exportDoc" ), (long)true );
741         exportFullDaisy =
742             config->Read ( _T ( "exportFullDaisy" ), (long)true );
743 
744 		applicationDir =
745 		    config->Read ( _T ( "applicationDir" ), wxStandardPaths::Get().GetDataDir() );
746 
747 		// if default value != true, type as long int
748 		long valZoom, longFalse;
749 		longFalse = false;
750 		valZoom = 0;
751 		frameWidth = frameHeight = framePosX = framePosY = 0;
752 
753 		properties.wrap =
754 		    config->Read ( _T ( "wrap" ), longFalse );
755 
756 		properties.zoom =
757 		    config->Read ( _T ( "zoom" ), valZoom );
758 
759 		properties.colorScheme = config->Read ( _T ( "colorScheme" ), COLOR_SCHEME_DEFAULT );
760 
761 		globalReplaceAllDocuments =
762 		    config->Read ( _T ( "globalReplaceAllDocuments" ), longFalse );
763 		showFullPathOnFrame =
764 		    config->Read ( _T ( "showFullPathOnFrame" ), longFalse );
765 		findMatchCase =
766 		    config->Read ( _T ( "findMatchCase" ), longFalse );
767 
768 		commandSync = config->Read ( _T ( "commandSync" ), longFalse );
769 		commandOutput = config->Read ( _T ( "commandOutput" ), ID_COMMAND_OUTPUT_IGNORE );
770 		commandString = config->Read ( _T ( "commandString" ), wxEmptyString );
771 
772 		exportStylesheet = config->Read ( _T ( "exportStylesheet" ), wxEmptyString );
773 		exportFolder = config->Read ( _T ( "exportFolder" ), wxEmptyString );
774 
775 		ruleSetPreset =
776 		    config->Read ( _T ( "ruleSetPreset" ), _ ( "Default style" ) );
777 		dictionaryPreset =
778 		    config->Read ( _T ( "dictionaryPreset" ), _ ( "en_US" ) );
779 
780 		filterPreset =
781 		    config->Read ( _T ( "filterPreset" ), _ ( "(No filter)" ) );
782 		findData.SetFindString ( config->Read ( _T ( "findReplaceFind" ), _T ( "" ) ) );
783 		findData.SetReplaceString ( config->Read ( _T ( "findReplaceReplace" ), _T ( "" ) ) );
784 
785 		toolbarVisible =
786 		    config->Read ( _T ( "toolbarVisible" ), true );
787 		protectTags = config->Read ( _T ( "protectTags" ), longFalse );
788 		visibilityState = config->Read ( _T ( "visibilityState" ), ID_SHOW_TAGS );
789 
790 		framePosX = config->Read ( _T ( "framePosX" ), framePosX );
791 		framePosY = config->Read ( _T ( "framePosY" ), framePosY );
792 		frameWidth = config->Read ( _T ( "frameWidth" ), frameWidth );
793 		frameHeight = config->Read ( _T ( "frameHeight" ), frameHeight );
794 		rememberOpenTabs = config->Read ( _T ( "rememberOpenTabs" ), true );
795 		libxmlNetAccess = config->Read ( _T ( "libxmlNetAccess" ), longFalse );
796 		openTabsOnClose = config->Read ( _T ( "openTabsOnClose" ), _T ( "" ) );
797 		notebookStyle = config->Read ( _T ( "notebookStyle" ), ID_NOTEBOOK_STYLE_VC8_COLOR );
798 		saveBom = config->Read ( _T ( "saveBom" ), true );
799 		unlimitedUndo = config->Read ( _T ( "unlimitedUndo" ), true );
800 		layout = config->Read ( _T ( "layout" ), wxEmptyString );
801 		restoreLayout = config->Read ( _T ( "restoreLayout" ), true );
802 		showLocationPane = config->Read ( _T ( "showLocationPane" ), true );
803 		showInsertChildPane = config->Read ( _T ( "showInsertChildPane" ), true );
804 		showInsertSiblingPane = config->Read ( _T ( "showInsertSiblingPane" ), true );
805 		showInsertEntityPane = config->Read ( _T ( "showInsertEntityPane" ), true );
806 		expandInternalEntities = config->Read ( _T ( "expandInternalEntities" ), true );
807 
808 		lastSymbol = config->Read( _T( "lastSymbol" ), _T ( "*" ) );
809 
810 #if defined(XERCES_HAVE_SSE2_INTRINSIC) && defined(__WXDEBUG__)
811 		xercescSSE2Warning = config->Read ( _T ( "xercescSSE2Warning" ), true );
812 #endif
813 	}
814 	else // config not found
815 	{
816 		properties.insertCloseTag =
817 		    properties.completion =
818 		        properties.currentLine =
819 		            properties.indentLines =
820 		                properties.protectHiddenElements =
821 		                    properties.toggleLineBackground =
822 		                        properties.deleteWholeTag =
823 		                            properties.highlightSyntax = true;
824 		properties.font = defaultFont;
825 		properties.wrap = properties.whitespaceVisible = false;
826 		properties.zoom = 0;
827 		properties.colorScheme = COLOR_SCHEME_DEFAULT;
828 		applicationDir = wxStandardPaths::Get().GetDataDir();
829 		ruleSetPreset = _ ( "Default style" );
830 		dictionaryPreset = _ ( "en_US" );
831 		filterPreset = _ ( "No filter" );
832 		xpathExpression = lastXslStylesheet = lastRelaxNGSchema = wxEmptyString;
833 		findRegex = true;
834 		findMatchCase = globalReplaceAllDocuments =
835 		                    showFullPathOnFrame = false;
836 		toolbarVisible = true;
837 		protectTags = false;
838 		visibilityState = SHOW_TAGS;
839 		framePosX = framePosY = frameWidth = frameHeight = 0;
840 		rememberOpenTabs = true;
841 		libxmlNetAccess = false;
842 		openTabsOnClose = wxEmptyString;
843 		notebookStyle = ID_NOTEBOOK_STYLE_VC8_COLOR;
844 		saveBom = unlimitedUndo = true;
845 		layout = wxEmptyString;
846 		restoreLayout = true;
847 		showLocationPane = true;
848 		showInsertChildPane = true;
849 		showInsertSiblingPane = true;
850 		showInsertEntityPane = true;
851 		expandInternalEntities = true;
852 		properties.validateAsYouType = true;
853 
854 		commandSync = false;
855 		commandOutput = ID_COMMAND_OUTPUT_IGNORE;
856 		commandString = wxEmptyString;
857 
858 		exportStylesheet = exportFolder = wxEmptyString;
859 		exportQuiet = exportMp3Album = exportSuppressOptional = exportHtml =
860             exportEpub = exportRtf = exportDoc = exportFullDaisy = true;
861 
862 		lastSymbol = _T( "*" );
863 
864 #if defined(XERCES_HAVE_SSE2_INTRINSIC) && defined(__WXDEBUG__)
865 		xercescSSE2Warning = true;
866 #endif
867 	}
868 
869 	largeFileProperties.completion = false;
870 	largeFileProperties.fold = false;
871 	largeFileProperties.foldCompact = false;
872 	largeFileProperties.whitespaceVisible = false;
873 	largeFileProperties.wrap = false;
874 	largeFileProperties.indentLines = false;
875 	largeFileProperties.protectHiddenElements = false;
876 	largeFileProperties.toggleLineBackground = false;
877 	largeFileProperties.insertCloseTag = false;
878 	largeFileProperties.deleteWholeTag = false;
879 	largeFileProperties.highlightSyntax = false;
880 	largeFileProperties.validateAsYouType = false;
881 	largeFileProperties.number = properties.number;
882 	largeFileProperties.currentLine = properties.currentLine;
883 	largeFileProperties.font = properties.font;
884 	largeFileProperties.zoom = 0;
885 	largeFileProperties.colorScheme = COLOR_SCHEME_NONE;
886 
887 	updatePaths();
888 	loadBitmaps();
889 
890 	// Initialize libxml
891 	WrapLibxml::Init ( catalogPath );
892 
893 	// Initialize Xerces-C++
894 	WrapXerces::Init ( libxmlNetAccess );
895 
896 #if defined(XERCES_HAVE_SSE2_INTRINSIC) && defined(__WXDEBUG__)
897 	if ( xercescSSE2Warning && wxTheApp->argc == 1 )
898 	{
899 		xercescSSE2Warning = wxMessageBox (
900 			_ ("SSE2 is enabled in Xerces-C++ library. SSE2 should be "\
901 			   "checked at run time rather than compile time. The program " \
902 			   "may crash (segmentation fault) on a machine that " \
903 			   "doesn't support SSE2.\n\n"\
904 			   "If it happens, please try compiling Xerces-C++ with SSE2 "\
905 			   "disabled.\n\n"\
906 			   "OK:\tShow this warning next time\n"\
907 			   "Cancel:\tDisable the warning\n"),
908 			_ ("SSE2 is checked at compile time"),
909 			wxOK | wxCANCEL | wxICON_WARNING
910 		) == wxOK;
911 	}
912 #endif // XERCES_HAVE_SSE2_INTRINSIC
913 
914 	size_t findFlags = 0;
915 	findFlags |= wxFR_DOWN;
916 
917 	if ( findMatchCase )
918 		findFlags |= wxFR_MATCHCASE;
919 
920 	findData.SetFlags ( findFlags );
921 
922 	// initialise document count for tab labels
923 	documentCount = 1;
924 
925 	SetIcon ( wxICON ( appicon ) );
926 
927 	CreateStatusBar();
928 	wxStatusBar *status = GetStatusBar();
929 	int widths[] = { -24, -6, -6, -6, -8 };
930 	status->SetFieldsCount ( 5 );
931 	status->SetStatusWidths ( 5, widths );
932 
933 	if ( !frameWidth ||
934 	        !frameHeight ||
935 	        frameWidth < 0 ||
936 	        frameHeight < 0 ||
937 	        framePosX < 0 ||
938 	        framePosY < 0 )
939 	{
940 #ifdef __WXMSW__
941 		Maximize();
942 #else
943 		SetSize ( 50, 50, 640, 480 );
944 #endif
945 	}
946 	else
947 	{
948 		SetSize ( framePosX, framePosY, frameWidth, frameHeight );
949 	}
950 
951 	stylePosition = aboutPosition = wxDefaultPosition;
952 	styleSize = wxSize ( 720, 540 );
953 
954 	long style = wxAUI_NB_TOP |
955 	             wxAUI_NB_TAB_SPLIT |
956 	             wxAUI_NB_TAB_MOVE |
957 	             wxAUI_NB_SCROLL_BUTTONS |
958 	             wxAUI_NB_WINDOWLIST_BUTTON |
959 	             wxAUI_NB_CLOSE_ON_ALL_TABS |
960 	             wxNO_BORDER;
961 
962 	mainBook = new MyNotebook (
963 	    this,
964 	    ID_NOTEBOOK,
965 	    wxDefaultPosition,
966 	    wxDefaultSize,
967 	    style );
968 
969 	manager.AddPane ( mainBook, wxAuiPaneInfo().CenterPane()
970 	                  .PaneBorder ( false ).Name ( _T ( "documentPane" ) ) );
971 	manager.GetPane ( mainBook ).dock_proportion = 10;
972 
973 	// add insert child panes
974 	locationPanel = new LocationPanel ( this, ID_LOCATION_PANEL );
975 	insertChildPanel = new InsertPanel ( this, ID_INSERT_CHILD_PANEL,
976 	                                     INSERT_PANEL_TYPE_CHILD );
977 	insertSiblingPanel = new InsertPanel ( this, ID_INSERT_SIBLING_PANEL,
978 	                                       INSERT_PANEL_TYPE_SIBLING );
979 	insertEntityPanel = new InsertPanel ( this, ID_INSERT_ENTITY_PANEL,
980 	                                      INSERT_PANEL_TYPE_ENTITY );
981 
982 #ifdef __WXMSW__
983 	manager.AddPane ( ( wxWindow * ) locationPanel, wxRIGHT, _ ( "Current Element" ) );
984 	manager.AddPane ( ( wxWindow * ) insertChildPanel, wxRIGHT, _ ( "Insert Element" ) );
985 	manager.AddPane ( ( wxWindow * ) insertSiblingPanel, wxRIGHT, _ ( "Insert Sibling" ) );
986 	manager.AddPane ( ( wxWindow * ) insertEntityPanel, wxRIGHT, _ ( "Insert Entity" ) );
987 #else
988 	manager.AddPane ( ( wxWindow * ) insertEntityPanel, wxRIGHT, _ ( "Insert Entity" ) );
989 	manager.AddPane ( ( wxWindow * ) insertSiblingPanel, wxRIGHT, _ ( "Insert Sibling" ) );
990 	manager.AddPane ( ( wxWindow * ) insertChildPanel, wxRIGHT, _ ( "Insert Element" ) );
991 	manager.AddPane ( ( wxWindow * ) locationPanel, wxRIGHT, _ ( "Current Element" ) );
992 #endif
993 
994 	manager.GetPane ( locationPanel ).Name ( _T ( "locationPane" ) ).Show (
995 	    ( restoreLayout ) ? showLocationPane : true ).DestroyOnClose ( false ).PinButton ( true );
996 	manager.GetPane ( locationPanel ).dock_proportion = 1;
997 
998 	manager.GetPane ( insertChildPanel ).Name ( _T ( "insertChildPane" ) ).Show (
999 	    ( restoreLayout ) ? showInsertChildPane : true ).DestroyOnClose ( false ).PinButton ( true );
1000 	manager.GetPane ( insertChildPanel ).dock_proportion = 1;
1001 
1002 	manager.GetPane ( insertSiblingPanel ).Name ( _T ( "insertSiblingPane" ) ).Show (
1003 	    ( restoreLayout ) ? showInsertSiblingPane : true ).DestroyOnClose ( false ).PinButton ( true );
1004 	manager.GetPane ( insertSiblingPanel ).dock_proportion = 1;
1005 
1006 	manager.GetPane ( insertEntityPanel ).Name ( _T ( "insertEntityPane" ) ).Show (
1007 	    ( restoreLayout ) ? showInsertEntityPane : true ).DestroyOnClose ( false ).PinButton ( true );
1008 	manager.GetPane ( insertEntityPanel ).dock_proportion = 1;
1009 
1010 	// add (hidden) message pane
1011 	htmlReport = new MyHtmlPane (
1012 	    this,
1013 	    ID_VALIDATION_PANE,
1014 	    wxDefaultPosition,
1015 	    wxSize ( -1, 48 ) );
1016 #ifndef __WXMSW__
1017 	const int sizeArray[] =
1018 	{
1019 		8, 9, 10, 11, 12, 13, 14
1020 	};
1021 	htmlReport->SetFonts ( wxEmptyString, wxEmptyString, sizeArray );
1022 #endif
1023 	htmlReport->SetBorders ( 0 );
1024 	manager.AddPane ( htmlReport, wxAuiPaneInfo().Movable().Bottom()
1025 	                  .Hide().Name ( _T ( "messagePane" ) )
1026 	                  .DestroyOnClose ( false ).Layer ( 1 ) );
1027 	manager.GetPane ( htmlReport ).dock_proportion = 1;
1028 
1029 #ifdef NEWFINDREPLACE
1030 	findReplacePanel = new FindReplacePanel (
1031 	    this,
1032 	    ID_FIND_REPLACE_PANEL,
1033 	    &findData,
1034 	    true,
1035 	    findRegex );
1036 
1037 	manager.AddPane (
1038 	    ( wxWindow * ) findReplacePanel,
1039 	    wxAuiPaneInfo().Bottom().Hide().Caption ( wxEmptyString ).
1040 	    DestroyOnClose ( false ).Layer ( 2 ) );
1041 #endif
1042 
1043 	commandPanel = new CommandPanel (
1044 	    this,
1045 	    wxID_ANY,
1046 	    commandString, // tbd
1047 	    commandSync, // tbd
1048 	    commandOutput // tbd
1049 	);
1050 	manager.AddPane (
1051 	    ( wxWindow * ) commandPanel,
1052 	    wxAuiPaneInfo().Bottom().Hide().Caption ( _T ( "Command" ) ).DestroyOnClose ( false ).Layer ( 3 ) );
1053 
1054 	validatePaths();
1055 
1056 	// handle command line and, on Windows, MS Word integration
1057 	handleCommandLineFlag = ( wxTheApp->argc > 1 ) ? true : false;
1058 
1059 #ifdef __WXMSW__
1060 	DragAcceptFiles ( true ); // currently Windows only
1061 #endif
1062 
1063 	manager.Update();
1064 
1065 	showTopBars (
1066 #ifndef __WXOSX__
1067 		toolbarVisible
1068 #else
1069 		false
1070 #endif
1071 	);
1072 
1073 	wxAcceleratorEntry entry ( wxACCEL_CTRL, WXK_F4, wxID_CLOSE );
1074 	wxAcceleratorTable accel ( 1, &entry );
1075 	SetAcceleratorTable ( accel );
1076 
1077 	/*
1078 	  defaultLayout = manager.SavePerspective();
1079 
1080 	  // restore layout if req'd
1081 	  if (restoreLayout && !layout.empty())
1082 	  {
1083 	    if (!manager.LoadPerspective(layout, true))
1084 	      manager.LoadPerspective(defaultLayout, true);
1085 	  }
1086 	*/
1087 }
1088 
~MyFrame()1089 MyFrame::~MyFrame()
1090 {
1091 	ThreadReaper::get().clear();
1092 
1093 	std::vector<wxString>::iterator it;
1094 	for ( it = tempFileVector.begin(); it != tempFileVector.end(); ++it )
1095 		wxRemoveFile ( *it );
1096 
1097 	layout = manager.SavePerspective();
1098 	if ( !config )
1099 		return;
1100 	history.Save ( *config );
1101 	config->Write ( _T ( "insertCloseTag" ), properties.insertCloseTag );
1102 	config->Write ( _T ( "completion" ), properties.completion );
1103 	config->Write ( _T ( "number" ), properties.number );
1104 	config->Write ( _T ( "fold" ), properties.fold );
1105 	config->Write ( _T ( "foldCompact" ), properties.foldCompact );
1106 	config->Write ( _T ( "currentLine" ), properties.currentLine );
1107 	config->Write ( _T ( "whitespaceVisible" ), properties.whitespaceVisible );
1108 	config->Write ( _T ( "wrap" ), properties.wrap );
1109 	config->Write ( _T ( "indentLines" ), properties.indentLines );
1110 	config->Write ( _T ( "zoom" ), properties.zoom );
1111 	config->Write ( _T ( "colorScheme" ), properties.colorScheme );
1112 	config->Write ( _T ( "protectHiddenElements" ), properties.protectHiddenElements );
1113 	config->Write ( _T ( "toggleLineBackground" ), properties.toggleLineBackground );
1114 	config->Write ( _T ( "deleteWholeTag" ), properties.deleteWholeTag );
1115 	config->Write ( _T ( "validateAsYouType" ), properties.validateAsYouType );
1116 	config->Write ( _T ( "font" ), properties.font );
1117 	config->Write ( _T ( "highlightSyntax" ), properties.highlightSyntax );
1118 	config->Write ( _T ( "applicationDir" ), applicationDir );
1119 	config->Write ( _T ( "ruleSetPreset" ), ruleSetPreset );
1120 	config->Write ( _T ( "dictionaryPreset" ), dictionaryPreset );
1121 	config->Write ( _T ( "filterPreset" ), filterPreset );
1122 	config->Write ( _T ( "xpathExpression" ), xpathExpression );
1123 	config->Write ( _T ( "findReplaceFind" ), findData.GetFindString() );
1124 	config->Write ( _T ( "findReplaceReplace" ), findData.GetReplaceString() );
1125 	config->Write ( _T ( "globalReplaceAllDocuments" ), globalReplaceAllDocuments );
1126 	config->Write ( _T ( "showFullPathOnFrame" ), showFullPathOnFrame );
1127 	config->Write ( _T ( "toolbarVisible" ), toolbarVisible );
1128 	config->Write ( _T ( "protectTags" ), protectTags );
1129 	config->Write ( _T ( "visibilityState" ), visibilityState );
1130  	config->Write ( _T ( "showLocationPane" ), manager.GetPane ( locationPanel ).IsShown() );
1131 	config->Write ( _T ( "showInsertChildPane" ), manager.GetPane ( insertChildPanel ).IsShown() );
1132 	config->Write ( _T ( "showInsertSiblingPane" ), manager.GetPane ( insertSiblingPanel ).IsShown() );
1133 	config->Write ( _T ( "showInsertEntityPane" ), manager.GetPane ( insertEntityPanel ).IsShown() );
1134 	config->Write ( _T ( "expandInternalEntities" ), expandInternalEntities );
1135 	config->Write ( _T ( "findRegex" ), findReplacePanel->getRegex() );
1136 	config->Write ( _T ( "findMatchCase" ), ( findData.GetFlags() ) & wxFR_MATCHCASE );
1137 	config->Write ( _T ( "commandSync" ), commandPanel->getSync() );
1138 	config->Write ( _T ( "commandOutput" ), commandPanel->getOutput() );
1139 	config->Write ( _T ( "commandString" ), commandPanel->getCommand() );
1140 	config->Write ( _T ( "restoreLayout" ), restoreLayout );
1141 	config->Write ( _T ( "lastXslStylesheet" ), lastXslStylesheet );
1142 	config->Write ( _T ( "lastRelaxNGSchema" ), lastRelaxNGSchema );
1143 	config->Write ( _T ( "exportStylesheet" ), exportStylesheet );
1144 	config->Write ( _T ( "exportFolder" ), exportFolder );
1145 	config->Write ( _T ( "exportQuiet" ), exportQuiet );
1146 	config->Write ( _T ( "exportMp3Album" ), exportMp3Album );
1147 	config->Write ( _T ( "exportSuppressOptional" ), exportSuppressOptional );
1148 	config->Write ( _T ( "exportHtml" ), exportHtml );
1149 	config->Write ( _T ( "exportEpub" ), exportEpub );
1150 	config->Write ( _T ( "exportRtf" ), exportRtf );
1151 	config->Write ( _T ( "exportDoc" ), exportDoc );
1152 	config->Write ( _T ( "exportFullDaisy" ), exportFullDaisy );
1153 
1154 	GetPosition ( &framePosX, &framePosY );
1155 	config->Write ( _T ( "framePosX" ), framePosX );
1156 	config->Write ( _T ( "framePosY" ), framePosY );
1157 	GetSize ( &frameWidth, &frameHeight );
1158 	config->Write ( _T ( "frameWidth" ), frameWidth );
1159 	config->Write ( _T ( "frameHeight" ), frameHeight );
1160 
1161 	config->Write ( _T ( "rememberOpenTabs" ), rememberOpenTabs );
1162 	config->Write ( _T ( "openTabsOnClose" ), openTabsOnClose );
1163 	config->Write ( _T ( "libxmlNetAccess" ), libxmlNetAccess );
1164 
1165 	config->Write ( _T ( "singleInstanceCheck" ), singleInstanceCheck );
1166 	config->Write ( _T ( "lang" ), lang );
1167 	config->Write ( _T ( "notebookStyle" ), notebookStyle );
1168 	config->Write ( _T ( "saveBom" ), saveBom );
1169 	config->Write ( _T ( "unlimitedUndo" ), unlimitedUndo );
1170 
1171 	config->Write ( _T ( "lastSymbol" ), lastSymbol );
1172 
1173 #if defined(XERCES_HAVE_SSE2_INTRINSIC) && defined(__WXDEBUG__)
1174 	config->Write ( _T ( "xercescSSE2Warning" ), xercescSSE2Warning );
1175 #endif
1176 
1177 	manager.UnInit();
1178 	wxTheClipboard->Flush();
1179 }
1180 
showTopBars(bool b)1181 void MyFrame::showTopBars ( bool b )
1182 {
1183 	if ( !menuBar )
1184 	{
1185 		SetToolBar ( NULL );
1186 		menuBar = getMenuBar();
1187 		SetMenuBar ( menuBar );
1188 	}
1189 	if ( b )
1190 	{
1191 		if ( !toolBar )
1192 			toolBar = getToolBar();
1193 		SetToolBar ( toolBar );
1194 	}
1195 	else
1196 	{
1197 		SetToolBar ( NULL );
1198 		delete toolBar;
1199 		toolBar = NULL;
1200 	}
1201 }
1202 
handleCommandLine()1203 void MyFrame::handleCommandLine()
1204 {
1205 	bool wordFlag, styleFlag;
1206 	wordFlag = styleFlag = false;
1207 	wxChar c;
1208 
1209 	int argc = wxTheApp->argc;
1210 	wxChar **argv = wxTheApp->argv;
1211 
1212 	while ( ( --argc > 0 && ( *++argv ) [0] == L'-' ) != 0 )
1213 	{
1214 		wxString wideVersion ( ABOUT_VERSION );
1215 		std::string version = ( const char * ) wideVersion.mb_str ( wxConvUTF8 );
1216 		const wxChar *s = argv[0];
1217 		while ( ( c = *++s ) != 0 )
1218 		{
1219 			switch ( c )
1220 			{
1221 				case 'w':
1222 					wordFlag = true;
1223 					break;
1224 				case 's':
1225 					styleFlag = true;
1226 					break;
1227 				case '-':
1228 					if ( *++s == 'v' )
1229 					{
1230 						std::cout << version.c_str() << std::endl;
1231 					}
1232 					else
1233 					{
1234 						std::cout << "Usage: xmlcopyeditor [--version --help -ws] [<file>] [<file2>]" << std::endl
1235 						    << "Options -w (import Microsoft Word document) and -s (open Spelling and style check) are provided for integration with Microsoft Office and only available on Windows" << std::endl;
1236 					}
1237 					exit ( 0 );
1238 				default:
1239 					messagePane ( _ ( "Unknown command line switch (expecting 'w', 's', --version or --help)" ),
1240 					              CONST_STOP );
1241 					return;
1242 			}
1243 		}
1244 	}
1245 
1246 	if ( argc <= 0 )
1247 	{
1248 		messagePane ( _ ( "Command line processing incomplete: no file specified" ),
1249 		              CONST_STOP );
1250 		return;
1251 	}
1252 
1253 	wxString fileName;
1254 
1255 	// no flags specified or not Windows
1256 #ifdef __WXMSW__
1257 	if ( !styleFlag && !wordFlag )
1258 #endif
1259 	{
1260 		for ( ; argc > 0; --argc, ++argv )
1261 		{
1262 			fileName = wxString ( *argv, wxConvLocal );
1263 			fileName = PathResolver::run ( fileName );
1264 			if ( isOpen ( fileName ) )
1265 				continue;
1266 			else if ( !openFile ( fileName ) )
1267 				break;
1268 		}
1269 		return;
1270 	}
1271 
1272 	// options only available on Windows
1273 	fileName = wxString ( *argv, wxConvLocal );
1274 
1275 	// fetch as many parameters as possible
1276 	for ( ;; )
1277 	{
1278 		if ( --argc <= 0 )
1279 			break;
1280 		++argv;
1281 		ruleSetPreset = wxString ( *argv, wxConvLocal );
1282 
1283 		if ( --argc <= 0 )
1284 			break;
1285 		++argv;
1286 		filterPreset = wxString ( *argv, wxConvLocal );
1287 
1288 		if ( --argc <= 0 )
1289 			break;
1290 		++argv;
1291 		applicationDir = wxString ( *argv, wxConvLocal );
1292 		updatePaths();
1293 
1294 		break;
1295 	}
1296 	if ( wordFlag )
1297 		importMSWord ( fileName );
1298 	else
1299 		openFile ( fileName );
1300 
1301 	if ( styleFlag && !ruleSetPreset.empty() && !filterPreset.empty() )
1302 	{
1303 		wxCommandEvent e;
1304 		OnSpelling ( e );
1305 	}
1306 }
1307 
isOpen(const wxString & fileName)1308 bool MyFrame::isOpen ( const wxString& fileName )
1309 {
1310 	return ( openFileSet.find ( fileName ) != openFileSet.end() );
1311 }
1312 
activateTab(const wxString & fileName)1313 bool MyFrame::activateTab ( const wxString& fileName )
1314 {
1315 	int pageCount = mainBook->GetPageCount();
1316 	XmlDoc *currentDoc;
1317 	for ( int i = 0; i < pageCount; ++i )
1318 	{
1319 		currentDoc = ( XmlDoc * ) mainBook->GetPage ( i );
1320 		if ( !currentDoc )
1321 			break;
1322 		if ( currentDoc->getFullFileName() == fileName )
1323 		{
1324 			mainBook->SetSelection ( i );
1325 			return true;
1326 		}
1327 	}
1328 	return false;
1329 }
1330 
OnAbout(wxCommandEvent & WXUNUSED (event))1331 void MyFrame::OnAbout ( wxCommandEvent& WXUNUSED ( event ) )
1332 {
1333 	wxString description;
1334 	description = ABOUT_DESCRIPTION;
1335 	description.Append ( ABOUT_CONTRIBUTORS );
1336 	description.Append ( _T("\n\nFramework version: ") );
1337 	description.Append ( wxVERSION_STRING );
1338 	description.Append ( _T("\n") );
1339 
1340 	wxAboutDialogInfo info;
1341 	info.SetName ( _ ( "XML Copy Editor" ) );
1342 	info.SetWebSite ( _T ( "http://xml-copy-editor.sourceforge.net" ) );
1343 	info.SetVersion ( ABOUT_VERSION );
1344 	info.SetCopyright ( ABOUT_COPYRIGHT );
1345 	info.AddDeveloper ( _T ( "Gerald Schmidt (development) <gnschmidt at users dot sourceforge dot net>" ) );
1346 	info.AddDeveloper ( _T ( "Matt Smigielski (testing) <alectrus at users dot sourceforge dot net>" ) );
1347 	info.AddDeveloper ( _T ( "Justin Dearing (development) <j-pimp at users dot sourceforge dot net>" ) );
1348 	info.AddDeveloper ( _T ( "Kev James (development) <kmjames at users dot sourceforge dot net>" ) );
1349 	info.AddDeveloper ( _T ( "Anh Trinh (development) <ant271 at users dot sourceforge dot net>" ) );
1350 	info.AddDeveloper ( _T ( "Zane U. Ji (development) <zaneuji at users dot sourceforge dot net>" ) );
1351 	info.AddDeveloper ( _T ( "Hugh McMaster (development) <hugh dot mcmaster at outlook dot com>" ) );
1352 	info.AddDeveloper ( _T ( "Nikola Forró (development) <nforro at redhat dot com>" ) );
1353 	info.AddTranslator ( _T ( "Viliam Búr (Slovak) <viliam at bur dot sk>" ) );
1354 	info.AddTranslator ( _T ( "David Håsäther (Swedish) <hasather at gmail dot com>" ) );
1355 	info.AddTranslator ( _T ( "François Badier (French) <frabad at gmail dot com>" ) );
1356 	info.AddTranslator ( _T ( "Thomas Wenzel (German) <thowen at users dot sourceforge.net>" ) );
1357 	info.AddTranslator ( _T ( "SHiNE CsyFeK (Chinese Simplified) <csyfek at gmail dot com>" ) );
1358 	info.AddTranslator ( _T ( "HSU PICHAN, YANG SHUFUN, CHENG PAULIAN, CHUANG KUO-PING, Marcus Bingenheimer (Chinese Traditional)" ) );
1359 	info.AddTranslator ( _T ( "Serhij Dubyk (Ukrainian) <dubyk at library dot lviv dot ua>" ) );
1360 	info.AddTranslator ( _T ( "Antonio Angelo (Italian) <aangelo at users dot sourceforge dot net>" ) );
1361 	info.AddTranslator ( _T ( "Siarhei Kuchuk (Russian) <Cuchuk dot Sergey at gmail dot com>" ) );
1362 	info.AddTranslator ( _T ( "Marcos Pérez González (Spanish) <marcos_pg at yahoo dot com>" ) );
1363 	info.AddTranslator ( _T ( "Rob Elemans (Dutch) <relemans at gmail dot com>" ) );
1364 	info.AddTranslator ( _T ( "Robert Falcó Miramontes <rfalco at acett dot org>" ) );
1365 	info.AddTranslator ( _T ( "Khoem Sokhem (Khmer) <sokhem at open dot org dot kh>" ) );
1366 	info.AddTranslator ( _T ( "Roger Sperberg (Khmer) <rsperberg at gmail dot com>" ) );
1367 	info.SetLicense ( ABOUT_LICENSE );
1368 	info.SetDescription ( description );
1369 	wxAboutBox ( info );
1370 	XmlDoc *doc;
1371 	if ( ( doc = getActiveDocument() ) == NULL )
1372 		return;
1373 	doc->SetFocus();
1374 }
1375 
OnCheckWellformedness(wxCommandEvent & event)1376 void MyFrame::OnCheckWellformedness ( wxCommandEvent& event )
1377 {
1378     statusProgress ( wxEmptyString );
1379 	XmlDoc *doc;
1380 	if ( ( doc = getActiveDocument() ) == NULL )
1381 		return;
1382 
1383 	std::string utf8Buffer;
1384 	getRawText ( doc, utf8Buffer );
1385 	if ( utf8Buffer.empty() )
1386 		return;
1387 
1388 	doc->clearErrorIndicators();
1389 	statusProgress ( _ ( "Parse in progress..." ) );
1390 
1391 	// check for well-formedness
1392 	WrapExpat we ( "UTF-8" );
1393 	if ( !we.parse ( utf8Buffer ) )
1394 	{
1395 		statusProgress ( wxEmptyString );
1396 		messagePane ( we.getLastError(), CONST_WARNING );
1397 		std::pair<int, int> posPair = we.getErrorPosition();
1398 		-- ( posPair.first );
1399 		int cursorPos =
1400 		    doc->PositionFromLine ( posPair.first );
1401 		doc->SetSelection ( cursorPos, cursorPos );
1402 
1403 		doc->setErrorIndicator ( posPair.first, posPair.second );
1404 		return;
1405 	}
1406 
1407 	statusProgress ( wxEmptyString );
1408 	documentOk ( _ ( "well-formed" ) );
1409 }
1410 
OnPageClosing(wxAuiNotebookEvent & event)1411 void MyFrame::OnPageClosing ( wxAuiNotebookEvent& event ) //wxNotebookEvent& event)//wxFlatNotebookEvent& event)
1412 {
1413 	deletePageVetoed = false;
1414 
1415 	if ( insertChildPanel && insertSiblingPanel && locationPanel )
1416 	{
1417 		insertChildPanel->update ( NULL, wxEmptyString );
1418 		insertSiblingPanel->update ( NULL, wxEmptyString );
1419 		locationPanel->update();
1420 		manager.Update();
1421 	}
1422 
1423 	XmlDoc *doc;
1424 	doc = ( XmlDoc * ) mainBook->GetPage ( event.GetSelection() );
1425 	if ( !doc )
1426 		return;
1427 
1428 	statusProgress ( wxEmptyString );
1429 	closeMessagePane();
1430 
1431 	if ( doc->GetModify() ) //CanUndo())
1432 	{
1433 		int selection;
1434 		wxString fileName;
1435 		selection = mainBook->GetSelection();
1436 		if ( selection != -1 )
1437 			fileName = doc->getShortFileName();
1438 
1439 		int answer = wxMessageBox (
1440 		                 _ ( "Do you want to save the changes to " ) + fileName + _T ( "?" ),
1441 		                 _ ( "XML Copy Editor" ),
1442 		                 wxYES_NO | wxCANCEL | wxICON_QUESTION,
1443 		                 this );
1444 
1445 		if ( answer == wxCANCEL )
1446 		{
1447 			event.Veto();
1448 			deletePageVetoed = true;
1449 			return;
1450 		}
1451 		else if ( answer == wxYES )
1452 		{
1453 			wxCommandEvent event;
1454 			OnSave ( event );
1455 		}
1456 	}
1457 	statusProgress ( wxEmptyString );
1458 
1459 	openFileSet.erase ( doc->getFullFileName() );
1460 	event.Skip();
1461 }
1462 
OnClose(wxCommandEvent & WXUNUSED (event))1463 void MyFrame::OnClose ( wxCommandEvent& WXUNUSED ( event ) )
1464 {
1465 	closeActiveDocument();
1466 }
1467 
OnCloseAll(wxCommandEvent & WXUNUSED (event))1468 void MyFrame::OnCloseAll ( wxCommandEvent& WXUNUSED ( event ) )
1469 {
1470 	if ( !mainBook )
1471 		return;
1472 	openTabsOnClose = wxEmptyString;
1473 
1474 	// retain tab order
1475 	if ( rememberOpenTabs && !openFileSet.empty() )
1476 	{
1477 		XmlDoc *doc;
1478 		wxString fullPath;
1479 		size_t maxTabs = mainBook->GetPageCount();
1480 		for ( size_t i = 0; i < maxTabs; ++i )
1481 		{
1482 			doc = ( XmlDoc * ) mainBook->GetPage ( i );
1483 			if ( doc && !doc->getDirectory().empty() )
1484 			{
1485 				fullPath = doc->getFullFileName();
1486 				openTabsOnClose.Append ( fullPath );
1487 				openTabsOnClose.Append ( _T ( "|" ) );
1488 			}
1489 		}
1490 	}
1491 
1492 	while ( closeActiveDocument() )
1493 		;
1494 }
1495 
OnCloseMessagePane(wxCommandEvent & WXUNUSED (event))1496 void MyFrame::OnCloseMessagePane ( wxCommandEvent& WXUNUSED ( event ) )
1497 {
1498 	closeMessagePane();
1499 }
1500 
OnCloseFindReplacePane(wxCommandEvent & WXUNUSED (event))1501 void MyFrame::OnCloseFindReplacePane ( wxCommandEvent& WXUNUSED ( event ) )
1502 {
1503 	closeFindReplacePane();
1504 }
1505 
OnCloseCommandPane(wxCommandEvent & WXUNUSED (event))1506 void MyFrame::OnCloseCommandPane ( wxCommandEvent& WXUNUSED ( event ) )
1507 {
1508 	closeCommandPane();
1509 }
1510 
closeMessagePane()1511 void MyFrame::closeMessagePane()
1512 {
1513 	if ( !htmlReport )
1514 		return;
1515 	manager.GetPane ( htmlReport ).Hide();
1516 	manager.Update();
1517 
1518 	XmlDoc *doc = getActiveDocument();
1519 	if ( doc )
1520 		doc->SetFocus();
1521 }
1522 
closeFindReplacePane()1523 void MyFrame::closeFindReplacePane()
1524 {
1525 	if ( manager.GetPane ( findReplacePanel ).IsShown() )
1526 		manager.GetPane ( findReplacePanel ).Hide();
1527 	manager.Update();
1528 
1529 	XmlDoc *doc = getActiveDocument();
1530 	if ( doc != NULL )
1531 		doc->SetFocus();
1532 }
1533 
closeCommandPane()1534 void MyFrame::closeCommandPane()
1535 {
1536 	if ( manager.GetPane ( commandPanel ).IsShown() )
1537 		manager.GetPane ( commandPanel ).Hide();
1538 	manager.Update();
1539 
1540 	XmlDoc *doc = getActiveDocument();
1541 	if ( doc != NULL )
1542 		doc->SetFocus();
1543 }
1544 
panelHasFocus()1545 bool MyFrame::panelHasFocus()
1546 {
1547 	XmlDoc *doc = getActiveDocument();
1548 	return ( !doc || ( FindFocus() != ( wxWindow * ) doc ) );
1549 }
1550 
OnCut(wxCommandEvent & event)1551 void MyFrame::OnCut ( wxCommandEvent& event )
1552 {
1553 	if ( panelHasFocus() )
1554 	{
1555 		event.Skip();
1556 		return;
1557 	}
1558 
1559 	XmlDoc *doc;
1560 	if ( ( doc = getActiveDocument() ) == NULL )
1561 		return;
1562 
1563 	if ( protectTags )
1564 		doc->adjustSelection();
1565 
1566 	doc->Cut();
1567 	doc->setValidationRequired ( true );
1568 }
1569 
OnCopy(wxCommandEvent & event)1570 void MyFrame::OnCopy ( wxCommandEvent& event )
1571 {
1572 	if ( panelHasFocus() )
1573 	{
1574 		event.Skip();
1575 		return;
1576 	}
1577 
1578 	XmlDoc *doc;
1579 	if ( ( doc = getActiveDocument() ) == NULL )
1580 		return;
1581 	doc->Copy();
1582 }
1583 
OnPaste(wxCommandEvent & event)1584 void MyFrame::OnPaste ( wxCommandEvent& event )
1585 {
1586 	if ( panelHasFocus() )
1587 	{
1588 		event.Skip();
1589 		return;
1590 	}
1591 	XmlDoc *doc;
1592 	if ( ( doc = getActiveDocument() ) == NULL )
1593 		return;
1594 
1595 	// this has to be handled here to override Scintilla's default Ctrl+V support
1596 	if ( protectTags )
1597 	{
1598 		if ( !wxTheClipboard->Open() || !wxTheClipboard->IsSupported ( wxDF_TEXT ) )
1599 			return;
1600 		wxTextDataObject data;
1601 		wxTheClipboard->GetData ( data );
1602 		wxString buffer = data.GetText();
1603 		wxTheClipboard->Close();
1604 		xmliseWideTextNode ( buffer );
1605 		doc->adjustCursor();
1606 		doc->AddText ( buffer );
1607 	}
1608 	else
1609 		doc->Paste();
1610 }
1611 
OnIdle(wxIdleEvent & event)1612 void MyFrame::OnIdle ( wxIdleEvent& event )
1613 {
1614 	wxStatusBar *status = GetStatusBar();
1615 	if ( !status )
1616 		return;
1617 
1618     /*
1619     // IPC handling: take one file from fileQueue at a time
1620     if ( !fileQueue.empty() )
1621     {
1622       openFile ( * ( fileQueue.begin() ) );
1623       fileQueue.erase( fileQueue.begin() );
1624     }
1625     */
1626 
1627 	// update attributes hidden field even if no document loaded
1628 	wxString currentHiddenStatus = status->GetStatusText ( STATUS_HIDDEN );
1629 	if ( visibilityState == HIDE_ATTRIBUTES )
1630 	{
1631 		if ( currentHiddenStatus != _ ( "Attributes hidden" ) )
1632 			status->SetStatusText (
1633 			    _ ( "Attributes hidden" ),
1634 			    STATUS_HIDDEN );
1635 	}
1636 	else if ( visibilityState == HIDE_TAGS )
1637 	{
1638 		if ( currentHiddenStatus != _ ( "Tags hidden" ) )
1639 			status->SetStatusText (
1640 			    _ ( "Tags hidden" ),
1641 			    STATUS_HIDDEN );
1642 	}
1643 	else
1644 	{
1645 		if ( !currentHiddenStatus.empty() )
1646 			status->SetStatusText ( wxEmptyString, STATUS_HIDDEN );
1647 	}
1648 
1649 	// update protected field even if no document loaded
1650 	wxString currentProtectedStatus = status->GetStatusText ( STATUS_PROTECTED );
1651 	if ( protectTags )
1652 	{
1653 		if ( currentProtectedStatus != _ ( "Tags locked" ) )
1654 			status->SetStatusText (
1655 			    _ ( "Tags locked" ),
1656 			    STATUS_PROTECTED );
1657 	}
1658 	else
1659 	{
1660 		if ( !currentProtectedStatus.empty() )
1661 			status->SetStatusText ( wxEmptyString, STATUS_PROTECTED );
1662 	}
1663 
1664 	// check if document loaded
1665 	wxString frameTitle = GetTitle();
1666 
1667 	XmlDoc *doc = getActiveDocument();
1668 	if ( doc == NULL )
1669 	{
1670 		if ( lastDoc != NULL )
1671 		{
1672 			lastDoc = NULL;
1673 			status->SetStatusText ( wxEmptyString, STATUS_MODIFIED );
1674 			status->SetStatusText ( wxEmptyString, STATUS_POSITION );
1675 			locationPanel->update ( NULL, wxEmptyString );
1676 			insertChildPanel->update ( NULL, wxEmptyString );
1677 			insertSiblingPanel->update ( NULL, wxEmptyString );
1678 			insertEntityPanel->update ( NULL, wxEmptyString );
1679 			wxString minimal = _ ( "XML Copy Editor" );
1680 			if ( frameTitle != minimal )
1681 				SetTitle ( minimal );
1682 
1683 			closeFindReplacePane();
1684 
1685 			event.Skip();
1686 			manager.Update();
1687 		}
1688 		return;
1689 	}
1690 
1691 	if ( restoreFocusToNotebook )
1692 	{
1693 		doc->SetFocus();
1694 		restoreFocusToNotebook = false;
1695 	}
1696 
1697 	// update modified field
1698 	if ( !mainBook )
1699 		return;
1700 	int index = mainBook->GetSelection();
1701 
1702 	wxString currentModifiedStatus = status->GetStatusText ( STATUS_MODIFIED );
1703 	wxString currentTabLabel = mainBook->GetPageText ( index );
1704 	if ( doc->GetModify() )
1705 	{
1706 		if ( currentModifiedStatus != _ ( "Modified" ) )
1707 		{
1708 			status->SetStatusText ( _ ( "Modified" ), STATUS_MODIFIED );
1709 
1710 			if ( ! ( currentTabLabel.Mid ( 0, 1 ) == _T ( "*" ) ) )
1711 			{
1712 				currentTabLabel.Prepend ( _T ( "*" ) );
1713 				mainBook->SetPageText ( index, currentTabLabel );
1714 			}
1715 		}
1716 	}
1717 	else
1718 	{
1719 		if ( !currentModifiedStatus.empty() )
1720 		{
1721 			status->SetStatusText ( _T ( "" ), STATUS_MODIFIED );
1722 
1723 			if ( currentTabLabel.Mid ( 0, 1 ) == _T ( "*" ) )
1724 			{
1725 				currentTabLabel.Remove ( 0, 1 );
1726 				mainBook->SetPageText ( index, currentTabLabel );
1727 			}
1728 		}
1729 	}
1730 
1731 	// update coordinates field
1732 	int current = doc->GetCurrentPos();
1733 	if ( current != lastPos )
1734 	{
1735 		wxString coordinates;
1736 		coordinates.Printf (
1737 		    _ ( "Ln %i Col %i" ),
1738 			doc->LineFromPosition ( current ) + 1,
1739 			doc->GetColumn ( current ) + 1 );
1740 		GetStatusBar()->SetStatusText ( coordinates, STATUS_POSITION );
1741 	}
1742 
1743 	// update parent element field
1744 	wxString parent, grandparent;
1745 	if ( current == lastPos && doc == lastDoc )
1746 		return;
1747 
1748 	lastPos = current;
1749 	lastDoc = doc;
1750 
1751 	wxString docTitle;
1752 	if ( doc->getFullFileName().empty() || !showFullPathOnFrame )
1753 		docTitle = doc->getShortFileName();
1754 	else
1755 		docTitle = doc->getFullFileName();
1756 
1757 	docTitle += _T ( " - " );
1758 	docTitle += _ ( "XML Copy Editor" );
1759 
1760 	if ( frameTitle != docTitle )
1761 		SetTitle ( docTitle );
1762 
1763 	// don't try to find parent if pane is not shown
1764 	if ( !manager.GetPane ( insertChildPanel ).IsShown() && !properties.validateAsYouType )
1765 		return;
1766 
1767 	int parentCloseAngleBracket = -1;
1768 	if ( !doc->canInsertAt ( current ) )
1769 		parent = grandparent = wxEmptyString;
1770 	else
1771 	{
1772 		parentCloseAngleBracket = doc->getParentCloseAngleBracket ( current );
1773 		parent = doc->getLastElementName ( parentCloseAngleBracket );
1774 	}
1775 
1776 	if ( !parent.empty() && properties.validateAsYouType && doc->getValidationRequired() )
1777 	{
1778 		// tbd: limit to parent element
1779 		doc->backgroundValidate();
1780 	}
1781 
1782 
1783 	if ( parent == lastParent )
1784 		return;
1785 	lastParent = parent;
1786 
1787 	bool mustUpdate = false;
1788 	if ( locationPanel && insertChildPanel && insertEntityPanel )
1789 	{
1790 		locationPanel->update ( doc, parent );
1791 		insertChildPanel->update ( doc, parent );
1792 		insertEntityPanel->update ( doc );
1793 		mustUpdate = true;
1794 	}
1795 
1796 	if ( parent.empty() )
1797 	{
1798 		if ( insertSiblingPanel )
1799 			insertSiblingPanel->update ( doc, wxEmptyString );
1800 		if ( mustUpdate )
1801 			manager.Update();
1802 		return;
1803 	}
1804 
1805 	if ( !manager.GetPane ( insertSiblingPanel ).IsShown() )
1806 	{
1807 		if ( mustUpdate )
1808 			manager.Update();
1809 		return;
1810 	}
1811 
1812 	// try to fetch grandparent if necessary/possible
1813 	if ( !parent.empty() && parentCloseAngleBracket != -1 )
1814 	{
1815 		int grandParentCloseAngleBracket;
1816 		grandParentCloseAngleBracket =
1817 		    doc->getParentCloseAngleBracket (
1818 		        doc->getTagStartPos ( parentCloseAngleBracket ) );
1819 		grandparent = doc->getLastElementName ( grandParentCloseAngleBracket );
1820 
1821 		if ( insertSiblingPanel )
1822 			insertSiblingPanel->update ( doc, parent, grandparent );
1823 		if ( grandparent != lastGrandparent )
1824 		{
1825 			mustUpdate = true;
1826 			lastGrandparent = grandparent;
1827 		}
1828 
1829 	}
1830 	if ( mustUpdate )
1831 		manager.Update();
1832 }
1833 
OnInsertChild(wxCommandEvent & event)1834 void MyFrame::OnInsertChild ( wxCommandEvent& event )
1835 {
1836 	if ( !insertChildPanel )
1837 		return;
1838 
1839 	wxAuiPaneInfo info = manager.GetPane ( insertChildPanel );
1840 	if ( !info.IsOk() )
1841 	{
1842 		return;
1843 	}
1844 	if ( !info.IsShown() )
1845 	{
1846 		manager.GetPane ( insertChildPanel ).Show ( true );
1847 		manager.Update();
1848 	}
1849 	insertChildPanel->setEditFocus();
1850 }
1851 
OnInsertSibling(wxCommandEvent & event)1852 void MyFrame::OnInsertSibling ( wxCommandEvent& event )
1853 {
1854 	if ( !insertSiblingPanel )
1855 		return;
1856 
1857 	wxAuiPaneInfo info = manager.GetPane ( insertSiblingPanel );
1858 	if ( !info.IsOk() )
1859 	{
1860 		return;
1861 	}
1862 
1863 	if ( !info.IsShown() )
1864 	{
1865 		manager.GetPane ( insertSiblingPanel ).Show ( true );
1866 		manager.Update();
1867 	}
1868 	insertSiblingPanel->setEditFocus();
1869 }
1870 
OnInsertEntity(wxCommandEvent & event)1871 void MyFrame::OnInsertEntity ( wxCommandEvent& event )
1872 {
1873 	if ( !insertEntityPanel )
1874 		return;
1875 
1876 	wxAuiPaneInfo info = manager.GetPane ( insertEntityPanel );
1877 	if ( !info.IsOk() )
1878 	{
1879 		return;
1880 	}
1881 
1882 	if ( !info.IsShown() )
1883 	{
1884 		manager.GetPane ( insertEntityPanel ).Show ( true );
1885 		manager.Update();
1886 	}
1887 	insertEntityPanel->setEditFocus();
1888 }
1889 
OnInsertSymbol(wxCommandEvent & event)1890 void MyFrame::OnInsertSymbol ( wxCommandEvent& event )
1891 {
1892 	XmlDoc *doc;
1893 	if ( ( doc = getActiveDocument() ) == NULL )
1894 		return;
1895 
1896 	wxSymbolPickerDialog dlg ( lastSymbol, wxEmptyString, properties.font, this );
1897 	if ( dlg.ShowModal() == wxID_OK )
1898 	{
1899 		if ( dlg.HasSelection() )
1900 		{
1901 			lastSymbol = dlg.GetSymbol();
1902 			doc->AddText ( lastSymbol );
1903 		}
1904 	}
1905 }
1906 
OnInsertTwin(wxCommandEvent & event)1907 void MyFrame::OnInsertTwin ( wxCommandEvent& event )
1908 {
1909 	XmlDoc *doc;
1910 	if ( ( doc = getActiveDocument() ) == NULL )
1911 		return;
1912 
1913 	wxString parent = doc->getParent();
1914 	if ( !doc->insertSibling ( parent, parent ) )
1915 	{
1916 		wxString msg;
1917 		msg.Printf ( _T ( "Cannot insert twin '%s'" ), parent.c_str() );
1918 		messagePane ( msg, CONST_STOP );
1919 	}
1920 	doc->setValidationRequired ( true );
1921 	doc->SetFocus();
1922 }
1923 
OnPasteNewDocument(wxCommandEvent & event)1924 void MyFrame::OnPasteNewDocument ( wxCommandEvent& event )
1925 {
1926 	if ( !wxTheClipboard->Open() )
1927 	{
1928 		messagePane ( _ ( "Cannot open clipboard" ), CONST_STOP );
1929 		return;
1930 	}
1931 	if ( !wxTheClipboard->IsSupported ( wxDF_TEXT ) )
1932 	{
1933 		messagePane ( _ ( "Cannot paste as new document: no text on clipboard" ), CONST_STOP );
1934 		return;
1935 	}
1936 	wxTextDataObject data;
1937 	wxTheClipboard->GetData ( data );
1938 
1939 	wxString buffer = data.GetText();
1940 	xmliseWideTextNode ( buffer );
1941 
1942 	buffer.Prepend ( _T ( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<root>" ) );
1943 	buffer.Append ( _T ( "</root>\n" ) );
1944 
1945 	newDocument ( buffer );
1946 	wxTheClipboard->Close();
1947 }
1948 
OnDialogFind(wxFindDialogEvent & event)1949 void MyFrame::OnDialogFind ( wxFindDialogEvent& event )
1950 {
1951 	findAgain ( event.GetFindString(), event.GetFlags() );
1952 }
1953 
OnDialogReplace(wxFindDialogEvent & event)1954 void MyFrame::OnDialogReplace ( wxFindDialogEvent& event )
1955 {
1956 	statusProgress ( wxEmptyString );
1957 	XmlDoc *doc;
1958 	if ( ( doc = getActiveDocument() ) == NULL )
1959 		return;
1960 
1961 	int start = doc->GetTargetStart();
1962 	int end = doc->GetTargetEnd();
1963 	if ( start != end )
1964 	{
1965 		if ( findReplacePanel->getRegex() )
1966 		{
1967 			start += doc->ReplaceTargetRE ( event.GetReplaceString() );
1968 		}
1969 		else
1970 		{
1971 			start += doc->ReplaceTarget ( event.GetReplaceString() );
1972 		}
1973 		// Move to the next position
1974 		doc->SetSelection ( start, start );
1975 	}
1976 	OnDialogFind ( event );
1977 }
1978 
OnDialogReplaceAll(wxFindDialogEvent & event)1979 void MyFrame::OnDialogReplaceAll ( wxFindDialogEvent& event )
1980 {
1981 	statusProgress ( wxEmptyString );
1982 	XmlDoc *doc;
1983 	if ( ( doc = getActiveDocument() ) == NULL )
1984 		return;
1985 
1986 	int flags = 0;
1987 	if ( event.GetFlags() & wxFR_WHOLEWORD )
1988 		flags |= wxSTC_FIND_WHOLEWORD;
1989 	if ( event.GetFlags() & wxFR_MATCHCASE )
1990 		flags |= wxSTC_FIND_MATCHCASE;
1991 	if ( findReplacePanel->getRegex() )
1992 		flags |= wxSTC_FIND_REGEXP;
1993 
1994 	doc->SetTargetStart ( 0 );
1995 	doc->SetTargetEnd ( doc->GetLength() );
1996 	doc->SetSearchFlags ( flags );
1997 
1998 	doc->BeginUndoAction();
1999 
2000 	int newLocation, replacementCount, regexWidth;
2001 	newLocation = replacementCount = regexWidth = 0;
2002 
2003 	while ( ( newLocation = doc->SearchInTarget ( event.GetFindString() ) ) != -1 )
2004 	{
2005 		if ( findReplacePanel->getRegex() )
2006 		{
2007 			regexWidth = doc->ReplaceTargetRE ( event.GetReplaceString() );
2008 			doc->SetTargetStart ( newLocation + regexWidth );
2009 		}
2010 		else
2011 		{
2012 			doc->ReplaceTarget ( event.GetReplaceString() );
2013 			doc->SetTargetStart ( newLocation + event.GetReplaceString().size() );
2014 		}
2015 		doc->SetTargetEnd ( doc->GetLength() );
2016 		++replacementCount;
2017 	}
2018 
2019 	doc->EndUndoAction();
2020 
2021 	wxString msg;
2022 	msg.Printf (
2023 	    wxPLURAL ( "%i replacement made", "%i replacements made", replacementCount ),
2024 	    replacementCount );
2025 	statusProgress ( msg );
2026 }
2027 
OnPrintSetup(wxCommandEvent & WXUNUSED (event))2028 void MyFrame::OnPrintSetup ( wxCommandEvent &WXUNUSED ( event ) )
2029 {
2030 	if ( !htmlPrinting.get() )
2031 		return;
2032 	htmlPrinting->PageSetup();
2033 }
2034 
OnPrintPreview(wxCommandEvent & WXUNUSED (event))2035 void MyFrame::OnPrintPreview ( wxCommandEvent &WXUNUSED ( event ) )
2036 {
2037 	XmlDoc *doc;
2038 	if ( !htmlPrinting.get() || ( doc = getActiveDocument() ) == NULL )
2039 		return;
2040 	wxString shortFileName, header;
2041 	shortFileName = doc->getShortFileName();
2042 	if ( !shortFileName.empty() )
2043 		header = shortFileName + _T ( " " );
2044 	header += _T ( "(@PAGENUM@/@PAGESCNT@)<hr>" );
2045 
2046 	htmlPrinting->SetHeader (
2047 	    header,
2048 	    wxPAGE_ALL );
2049 	statusProgress ( _ ( "Preparing Print Preview..." ) );
2050 	wxString htmlBuffer = getHtmlBuffer();
2051 	statusProgress ( wxEmptyString );
2052 	if ( ! ( htmlPrinting->PreviewText ( htmlBuffer ) ) )
2053 	{}
2054 }
2055 
OnPrint(wxCommandEvent & WXUNUSED (event))2056 void MyFrame::OnPrint ( wxCommandEvent &WXUNUSED ( event ) )
2057 {
2058 	XmlDoc *doc;
2059 	if ( !htmlPrinting.get() || ( doc = getActiveDocument() ) == NULL )
2060 		return;
2061 	wxString shortFileName, header;
2062 	shortFileName = doc->getShortFileName();
2063 	if ( !shortFileName.empty() )
2064 		header = shortFileName + _T ( " " );
2065 	header += _T ( "(@PAGENUM@/@PAGESCNT@)<hr>" );
2066 
2067 	htmlPrinting->SetHeader (
2068 	    header,
2069 	    wxPAGE_ALL );
2070 	statusProgress ( _ ( "Preparing to print..." ) );
2071 	wxString htmlBuffer = getHtmlBuffer();
2072 	statusProgress ( wxEmptyString );
2073 	if ( ! ( htmlPrinting->PrintText ( htmlBuffer ) ) )
2074 	{}
2075 }
2076 
getHtmlBuffer()2077 wxString MyFrame::getHtmlBuffer()
2078 {
2079 	XmlDoc *doc;
2080 	if ( ( doc = getActiveDocument() ) == NULL )
2081 		return _T ( "<html><head></head><body></body></html>" );
2082 	wxString buffer, htmlBuffer;
2083 	buffer = doc->GetText();
2084 	size_t size = buffer.size();
2085 	htmlBuffer.reserve ( size * 2 );
2086 
2087 	htmlBuffer = _T ( "<html><body><p>" );
2088 	bool startOfLine = true;
2089 	for ( size_t i = 0; i < size; ++i )
2090 	{
2091 		wchar_t c = buffer[i];
2092 		switch ( c )
2093 		{
2094 			case L' ':
2095 				htmlBuffer += ( startOfLine ) ? _T ( "&nbsp;" ) : _T ( " " );
2096 				break;
2097 			case L'\t':
2098 				htmlBuffer += _T ( "&nbsp;&nbsp;" );
2099 				break;
2100 			case L'<':
2101 				htmlBuffer += _T ( "&lt;" );
2102 				startOfLine = false;
2103 				break;
2104 			case L'>':
2105 				htmlBuffer += _T ( "&gt;" );
2106 				startOfLine = false;
2107 				break;
2108 			case L'\n':
2109 				htmlBuffer += _T ( "<br>" );
2110 				startOfLine = true;
2111 				break;
2112 			case L'&':
2113 				htmlBuffer + _T ( "&amp;" );
2114 				startOfLine = false;
2115 				break;
2116 			default:
2117 				htmlBuffer += c;
2118 				startOfLine = false;
2119 				break;
2120 		}
2121 	}
2122 	htmlBuffer += _T ( "</p></body></html>" );
2123 	return htmlBuffer;
2124 }
2125 
OnFind(wxCommandEvent & WXUNUSED (event))2126 void MyFrame::OnFind ( wxCommandEvent& WXUNUSED ( event ) )
2127 {
2128 #ifdef NEWFINDREPLACE
2129 	manager.GetPane ( findReplacePanel ).Caption ( _ ( "Find" ) );
2130 	bool visible = manager.GetPane ( findReplacePanel ).IsShown();
2131 	if ( !visible )
2132 	{
2133 		manager.GetPane ( findReplacePanel ).Show();
2134 	}
2135 	manager.Update();
2136 	findReplacePanel->refresh();
2137 	findReplacePanel->setReplaceVisible ( false );
2138 	findReplacePanel->focusOnFind();
2139 	return;
2140 #endif
2141 
2142 	findDialog.reset ( new wxFindReplaceDialog (
2143 	                   this,
2144 	                   &findData,
2145 	                   _ ( "Find" ) ) );
2146 	findDialog->Show();
2147 }
2148 
OnImportMSWord(wxCommandEvent & event)2149 void MyFrame::OnImportMSWord ( wxCommandEvent& event )
2150 {
2151 #ifndef __WXMSW__
2152 	messagePane ( _ ( "This functionality requires Microsoft Windows" ) );
2153 	return;
2154 #endif
2155 
2156 	boost::scoped_ptr<wxFileDialog> fd ( new wxFileDialog (
2157 	                                     this,
2158 	                                     _ ( "Import Microsoft Word Document" ),
2159 	                                     mLastDir,
2160 	                                     _T ( "" ),
2161 	                                     _T ( "Microsoft Word (*.doc)|*.doc" ),
2162 #if wxCHECK_VERSION(2,9,0)
2163 	                                     wxFD_OPEN | wxFD_FILE_MUST_EXIST
2164 #else
2165 	                                     wxOPEN | wxFILE_MUST_EXIST
2166 #endif
2167 	                                     ) );
2168 	if ( fd->ShowModal() == wxID_CANCEL )
2169 		return;
2170 
2171 	mLastDir = fd->GetDirectory();
2172 
2173 	wxString path = fd->GetPath();
2174 
2175 	if ( path == _T ( "" ) )
2176 		return;
2177 
2178 	importMSWord ( path );
2179 }
2180 
OnExport(wxCommandEvent & event)2181 void MyFrame::OnExport ( wxCommandEvent& event )
2182 {
2183 	statusProgress ( wxEmptyString );
2184 	closeMessagePane();
2185 
2186 	XmlDoc *doc;
2187 	if ( ( doc = getActiveDocument() ) == NULL )
2188 		return;
2189 
2190     wxString testDir = applicationDir + wxFileName::GetPathSeparator() + _T ( "daisy" );
2191     bool downloadLink = !wxDirExists ( testDir );
2192 
2193     boost::scoped_ptr<ExportDialog> ed ( new ExportDialog (
2194         this,
2195         exportStylesheet,
2196         exportFolder,
2197         exportQuiet,
2198         exportSuppressOptional,
2199         exportHtml,
2200         exportEpub,
2201         exportRtf,
2202         exportDoc,
2203         exportFullDaisy,
2204         exportMp3Album,
2205         downloadLink ) );
2206     int ret = ed->ShowModal();
2207 
2208     if ( ret != wxID_OK )
2209         return;
2210 
2211     exportStylesheet = ed->getUrlString();
2212     exportFolder = ed->getFolderString();
2213     exportQuiet = ed->getQuiet();
2214     exportMp3Album = ed->getMp3Album();
2215     exportSuppressOptional = ed->getSuppressOptional();
2216     exportHtml = ed->getHtml();
2217     exportEpub = ed->getEpub();
2218     exportRtf = ed->getRtf();
2219     exportDoc = ed->getDoc();
2220     exportFullDaisy = ed->getFullDaisy();
2221 
2222 	std::string rawBufferUtf8;
2223 	getRawText ( doc, rawBufferUtf8 );
2224 	if ( !XmlEncodingHandler::setUtf8 ( rawBufferUtf8 ) )
2225 	{
2226 		encodingMessage();
2227 		return;
2228 	}
2229 
2230 	WrapTempFileName tempFileName ( doc->getFullFileName() );
2231 
2232 	ofstream rawBufferStream ( tempFileName.name().c_str() );
2233 	if ( !rawBufferStream )
2234 		return;
2235 	rawBufferStream << rawBufferUtf8;
2236 	rawBufferStream.close();
2237 
2238     wxString tempFile= tempFileName.wideName();
2239 
2240     WrapDaisy wd ( this, daisyDir, doc->getFullFileName() );
2241     if ( !wd.run (
2242         tempFile,
2243         exportStylesheet,
2244         exportFolder,
2245         exportQuiet,
2246         exportSuppressOptional,
2247         exportEpub,
2248         exportRtf,
2249         exportDoc,
2250         exportFullDaisy,
2251         exportMp3Album ) )
2252     {
2253         messagePane ( _ ("[b]DAISY export stopped[/b]: ") + wd.getLastError(), CONST_STOP );
2254         return;
2255     }
2256 	messagePane ( _ ( "DAISY export completed. Output files are stored in: [b]" ) + exportFolder + _T ( "[/b]." ), CONST_INFO );
2257 }
2258 
importMSWord(const wxString & path)2259 void MyFrame::importMSWord ( const wxString& path )
2260 {
2261 #ifndef __WXMSW__
2262 	messagePane ( _ ( "This functionality requires Microsoft Windows" ) );
2263 	return;
2264 #endif
2265 
2266 	WrapTempFileName tempFileName ( _T ( "" ) ), swapFileName ( _T ( "" ) );
2267 	wxString completeSwapFileName = swapFileName.wideName() + _T ( ".doc" );
2268 	if ( !wxCopyFile ( path, completeSwapFileName, true ) )
2269 	{
2270 		wxString message;
2271 		message.Printf ( _ ( "Cannot open [b]%s[/b] for import" ), path.c_str() );
2272 		messagePane ( message, CONST_STOP );
2273 		return;
2274 	}
2275 
2276 	wxString cmd = binDir +
2277 	               _T ( "doc2xml.exe \"" ) +
2278 	               completeSwapFileName + _T ( "\" \"" ) +
2279 	               tempFileName.wideName() + _T ( "\"" );
2280 
2281 	statusProgress ( _ ( "Import in progress..." ) );
2282 	int result = wxExecute ( cmd, wxEXEC_SYNC );
2283 
2284 	wxRemoveFile ( completeSwapFileName ); // necessary because .doc extension added
2285 
2286 	statusProgress ( wxEmptyString );
2287 	wxString message;
2288 	wxString versionMessage (
2289 	    _ ( "(lossless conversion requires version 2003 or later)" ) );
2290 
2291 	switch ( result )
2292 	{
2293 		case 0:
2294 			break;
2295 		case 1:
2296 			messagePane ( _ ( "Cannot start Microsoft Word" ), CONST_STOP );
2297 			return;
2298 		case 2:
2299 			messagePane (
2300 			    _ ( "A more recent version of Microsoft Word is required" ), CONST_STOP );
2301 			return;
2302 		case 3:
2303 			message.Printf ( _T ( "Microsoft Word cannot open [b]%s[/b]" ), path.c_str() );
2304 			messagePane ( message + path, CONST_STOP );
2305 			return;
2306 		case 4:
2307 			message.Printf ( _ ( "Microsoft Word cannot save [b]%s[/b] as XML" ), path.c_str() );
2308 			messagePane ( message, CONST_STOP );
2309 			return;
2310 		case 5:
2311 			messagePane (
2312 			    _ ( "Microsoft Word cannot save this document as WordprocessingML " ) +
2313 			    versionMessage,
2314 			    CONST_INFO );
2315 			break;
2316 		default:
2317 			break;
2318 	}
2319 
2320 	statusProgress ( _ ( "Opening imported file..." ) );
2321 	std::string buffer;
2322 
2323 	wxString displayBuffer;
2324 
2325 	if ( result != 5 ) // Word 2003 or later
2326 	{
2327 		boost::scoped_ptr<WrapLibxml> prettyPrinter ( new WrapLibxml ( libxmlNetAccess ) );
2328 		prettyPrinter->parse ( tempFileName.wideName(), true );
2329 		buffer = prettyPrinter->getOutput();
2330 		displayBuffer = wxString ( buffer.c_str(), wxConvUTF8, buffer.size() );
2331 	}
2332 	else // earlier versions
2333 	{
2334 		if ( !ReadFile::run ( tempFileName.name(), buffer ) )
2335 		{
2336 			statusProgress ( wxEmptyString );
2337 			messagePane ( _ ( "Cannot open imported file" ), CONST_STOP );
2338 			return;
2339 		}
2340 		displayBuffer = wxString ( buffer.c_str(), wxConvUTF8, buffer.size() );
2341 		displayBuffer.Remove ( 0, 1 ); // remove byte order mark
2342 		xmliseWideTextNode ( displayBuffer );
2343 
2344 		displayBuffer.Prepend (
2345 		    _T ( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<root>" ) );
2346 		displayBuffer.Append ( _T ( "</root>\n" ) );
2347 	}
2348 
2349 	newDocument ( displayBuffer, tempFileName.wideName() );
2350 	statusProgress ( wxEmptyString );
2351 }
2352 
OnExportMSWord(wxCommandEvent & event)2353 void MyFrame::OnExportMSWord ( wxCommandEvent& event )
2354 {
2355 #ifndef __WXMSW__
2356 	messagePane ( _ ( "This functionality requires Microsoft Windows" ) );
2357 	return;
2358 #endif
2359 	statusProgress ( wxEmptyString );
2360 
2361 	// fetch document contents
2362 	XmlDoc *doc;
2363 	if ( ( doc = getActiveDocument() ) == NULL )
2364 		return;
2365 
2366 	WrapTempFileName wtfn ( _T ( "" ) );
2367 	wxString sourceFileName = doc->getFullFileName();
2368 
2369 	if ( doc->getDirectory().empty() )
2370 	{
2371 		sourceFileName = wtfn.wideName();
2372 		std::fstream ofs ( wtfn.name().c_str() );
2373 		if ( !ofs )
2374 			return;
2375 
2376 		std::string utf8Buffer;
2377 		getRawText ( doc, utf8Buffer );
2378 		ofs << utf8Buffer;
2379 		ofs.close();
2380 	}
2381 	else if ( doc->GetModify() ) //CanUndo())
2382 	{
2383 		modifiedMessage();
2384 		return;
2385 	}
2386 
2387 	boost::scoped_ptr<wxFileDialog> fd ( new wxFileDialog (
2388 	                                     this,
2389 	                                     _ ( "Export Microsoft Word Document" ),
2390 	                                     _T ( "" ),
2391 	                                     _T ( "" ),
2392 	                                     _T ( "Microsoft Word (*.doc)|*.doc" ),
2393 #if wxCHECK_VERSION(2,9,0)
2394 	                                     wxFD_SAVE | wxFD_OVERWRITE_PROMPT));
2395 #else
2396 	                                     wxSAVE | wxOVERWRITE_PROMPT ) );
2397 #endif
2398 	fd->ShowModal();
2399 
2400 	wxString path = fd->GetPath();
2401 
2402 	if ( path == _T ( "" ) )
2403 		return;
2404 
2405 	wxString cmd = binDir +
2406 	               _T ( "xml2doc.exe -v \"" ) +
2407 	               sourceFileName + _T ( "\" \"" ) +
2408 	               path + _T ( "\"" );
2409 
2410 	statusProgress ( _ ( "Export in progress..." ) );
2411 	int result = wxExecute ( cmd, wxEXEC_SYNC );
2412 	statusProgress ( wxEmptyString );
2413 	wxString message;
2414 	switch ( result )
2415 	{
2416 		case 1:
2417 			messagePane ( _ ( "Cannot start Microsoft Word" ), CONST_STOP );
2418 			return;
2419 		case 2:
2420 			messagePane (
2421 			    _ ( "A more recent version of Microsoft Word is required" ), CONST_STOP );
2422 			return;
2423 		case 3:
2424 			message.Printf ( _ ( "Microsoft Word cannot save %s" ), path.c_str() );
2425 			messagePane ( message, CONST_STOP );
2426 			return;
2427 		case 0:
2428 			break;
2429 		default:
2430 			break;
2431 	}
2432 }
2433 
OnBrowser(wxCommandEvent & WXUNUSED (event))2434 void MyFrame::OnBrowser ( wxCommandEvent& WXUNUSED ( event ) )
2435 {
2436 	statusProgress ( wxEmptyString );
2437 
2438 	// fetch document contents
2439 	XmlDoc *doc;
2440 	if ( ( doc = getActiveDocument() ) == NULL )
2441 		return;
2442 
2443 	wxString sourceFileName = doc->getFullFileName();
2444 	WrapTempFileName wtfn ( sourceFileName, _T ( ".html" ) );
2445 
2446 	if ( doc->getDirectory().empty() || doc->GetModify() )
2447 	{
2448 		sourceFileName = wtfn.wideName();
2449 
2450 		std::ofstream ofs ( ( const char * ) wtfn.name().c_str() );
2451 		if ( !ofs )
2452 		{
2453 			messagePane ( _ ( "Cannot save temporary file" ), CONST_STOP );
2454 			return;
2455 		}
2456 
2457 		std::string utf8Buffer;
2458 		getRawText ( doc, utf8Buffer );
2459 		ofs << utf8Buffer;
2460 		ofs.close();
2461 
2462 		// keep files until application closes
2463 		tempFileVector.push_back ( sourceFileName );
2464 		tempFileVector.push_back ( wtfn.originalWideName() );
2465 		wtfn.setKeepFiles ( true );
2466 	}
2467 
2468 	wxLaunchDefaultBrowser ( sourceFileName, wxBROWSER_NEW_WINDOW );
2469 }
2470 
OnHelp(wxCommandEvent & event)2471 void MyFrame::OnHelp ( wxCommandEvent& event )
2472 {
2473 #ifdef __WXMSW__
2474 	wxString cmd = _T ( "hh.exe \"" ) + helpDir + _T ( "xmlcopyeditor.chm\"" );
2475 	wxExecute ( cmd );
2476 #else
2477 	wxString helpFileName = helpDir + _T ( "xmlcopyeditor.hhp" );
2478 	helpController->AddBook ( wxFileName ( helpFileName ) );
2479 	helpController->DisplayContents();
2480 #endif
2481 }
2482 
OnSplitTab(wxCommandEvent & event)2483 void MyFrame::OnSplitTab ( wxCommandEvent& event )
2484 {
2485 /*
2486 	int id = event.GetId();
2487 	XmlDoc *doc = getActiveDocument();
2488 	if ( !doc )
2489 		return;
2490 	wxString fileName = doc->getFullFileName();
2491 
2492 	// mainBook->GetSelection() is currently unreliable, so fetch by title
2493 
2494 	    int pageCount = mainBook->GetPageCount();
2495 	    XmlDoc *currentDoc;
2496 	    int currentSelection = -1;
2497 	    for ( int i = 0; i < pageCount; ++i )
2498 	    {
2499 	        currentDoc = ( XmlDoc * ) mainBook->GetPage ( i );
2500 	        if ( !currentDoc )
2501 	            break;
2502 	        if ( currentDoc->getFullFileName() == fileName )
2503 	        {
2504 	            currentSelection = i;
2505 	        }
2506 	    }
2507 	    if ( currentSelection == -1 )
2508 	        return;
2509 	*/
2510 	int currentSelection, direction;
2511 	currentSelection = mainBook->GetSelection();
2512 	direction = wxAUI_NB_RIGHT;
2513 /*
2514 	switch ( id )
2515 	{
2516 			    ID_SPLIT_TAB_TOP:
2517 			        direction = wxAUI_NB_TOP;
2518 			        break;
2519 			    ID_SPLIT_TAB_RIGHT:
2520 			        direction = wxAUI_NB_RIGHT;
2521 			        break;
2522 			    ID_SPLIT_TAB_BOTTOM:
2523 			        direction = wxAUI_NB_BOTTOM;
2524 			        break;
2525 			    ID_SPLIT_TAB_LEFT:
2526 			        direction = wxAUI_NB_LEFT;
2527 			        break;
2528 		default:
2529 			direction = wxAUI_NB_RIGHT;
2530 			break;
2531 	}
2532 */
2533 	mainBook->Split ( currentSelection, direction );
2534 }
2535 
OnColorScheme(wxCommandEvent & event)2536 void MyFrame::OnColorScheme ( wxCommandEvent& event )
2537 {
2538 	int id = event.GetId();
2539 	switch ( id )
2540 	{
2541 		case ID_COLOR_SCHEME_DEFAULT:
2542 			properties.colorScheme = COLOR_SCHEME_DEFAULT;
2543 			break;
2544 		case ID_COLOR_SCHEME_DEFAULT_BACKGROUND:
2545 			properties.colorScheme = COLOR_SCHEME_DEFAULT_BACKGROUND;
2546 			break;
2547 		case ID_COLOR_SCHEME_REDUCED_GLARE:
2548 			properties.colorScheme = COLOR_SCHEME_REDUCED_GLARE;
2549 			break;
2550 		case ID_COLOR_SCHEME_NONE:
2551 			properties.colorScheme = COLOR_SCHEME_NONE;
2552 			break;
2553 		default:
2554 			return;
2555 	}
2556 	colorSchemeMenu->Check ( id, true );
2557 
2558 	XmlDoc *doc;
2559 	if ( ( doc = getActiveDocument() ) == NULL )
2560 		return;
2561 
2562 	properties.zoom = doc->GetZoom(); // ensure temp changes to font size are kept
2563 
2564 	applyEditorProperties ( false );
2565 	doc->SetFocus();
2566 }
2567 
OnFontSmaller(wxCommandEvent & event)2568 void MyFrame::OnFontSmaller ( wxCommandEvent& event )
2569 {
2570 	XmlDoc *doc;
2571 	if ( ( doc = getActiveDocument() ) == NULL )
2572 		return;
2573 	doc->ZoomOut();
2574 	properties.zoom = doc->GetZoom();
2575 	applyEditorProperties ( true );
2576 	doc->SetFocus();
2577 }
2578 
OnFontMedium(wxCommandEvent & event)2579 void MyFrame::OnFontMedium ( wxCommandEvent& event )
2580 {
2581 	XmlDoc *doc;
2582 	if ( ( doc = getActiveDocument() ) == NULL )
2583 		return;
2584 	doc->SetZoom ( 0 );
2585 	properties.zoom = doc->GetZoom();
2586 	applyEditorProperties ( true );
2587 	doc->SetFocus();
2588 }
2589 
OnFontLarger(wxCommandEvent & event)2590 void MyFrame::OnFontLarger ( wxCommandEvent& event )
2591 {
2592 	XmlDoc *doc;
2593 	if ( ( doc = getActiveDocument() ) == NULL )
2594 		return;
2595 	doc->ZoomIn();
2596 	properties.zoom = doc->GetZoom();
2597 	applyEditorProperties ( true );
2598 	doc->SetFocus();
2599 }
2600 
OnOptions(wxCommandEvent & WXUNUSED (event))2601 void MyFrame::OnOptions ( wxCommandEvent& WXUNUSED ( event ) )
2602 {
2603 	// ensure font size does not change after
2604 	XmlDoc *doc = getActiveDocument();
2605 	if ( doc )
2606 	{
2607 		properties.zoom = doc->GetZoom();
2608 	}
2609 
2610 	wxString title
2611 #ifdef __WXMSW__
2612 	( _ ( "Options" ) );
2613 #else
2614 	( _ ( "Preferences" ) );
2615 #endif
2616 	boost::scoped_ptr<MyPropertySheet> mpsd ( new MyPropertySheet (
2617 	                                          this,
2618 	                                          properties,
2619 	                                          applicationDir,
2620 	                                          rememberOpenTabs,
2621 	                                          libxmlNetAccess,
2622 	                                          singleInstanceCheck,
2623 	                                          saveBom,
2624 	                                          unlimitedUndo,
2625 	                                          restoreLayout,
2626 	                                          expandInternalEntities,
2627 	                                          showFullPathOnFrame,
2628 	                                          lang,
2629 	                                          wxGetApp().getAvailableTranslations(),
2630 	                                          wxID_ANY,
2631 	                                          title ) );
2632 	if ( mpsd->ShowModal() == wxID_OK )
2633 	{
2634 		WrapXerces::enableNetwork ( libxmlNetAccess );
2635 		applyEditorProperties();
2636 		updatePaths();
2637 	}
2638 	if ( doc )
2639 		doc->SetFocus();
2640 }
2641 
OnHistoryFile(wxCommandEvent & event)2642 void MyFrame::OnHistoryFile ( wxCommandEvent& event )
2643 {
2644 	wxString f ( history.GetHistoryFile ( event.GetId() - wxID_FILE1 ) );
2645 	if ( !f.empty() )
2646 		openFile ( f );
2647 }
2648 
OnGoto(wxCommandEvent & WXUNUSED (event))2649 void MyFrame::OnGoto ( wxCommandEvent& WXUNUSED ( event ) )
2650 {
2651 	statusProgress ( wxEmptyString );
2652 
2653 	XmlDoc *doc;
2654 	if ( ( doc = getActiveDocument() ) == NULL )
2655 		return;
2656 
2657 	wxTextEntryDialog *dlg = new wxTextEntryDialog (
2658 	    this,
2659 	    _ ( "Enter line number:" ),
2660 	    _ ( "Go To" ) );
2661 	int ret = dlg->ShowModal();
2662 	if ( ret == wxID_CANCEL )
2663 		return;
2664 	wxString val = dlg->GetValue();
2665 	long line;
2666 	if ( !val.ToLong ( &line ) || line < 1 )
2667 	{
2668 		wxString msg;
2669 		msg.Printf ( _ ( "'%s' is not a valid line number" ), val.c_str() );
2670 		messagePane ( msg, CONST_STOP );
2671 		return;
2672 	}
2673 	--line;
2674 	doc->GotoLine ( ( int ) line );
2675 	doc->SetFocus();
2676 }
2677 
OnFindAgain(wxCommandEvent & event)2678 void MyFrame::OnFindAgain ( wxCommandEvent& event )
2679 {
2680 	//findAgain(findData.GetFindString(), findData.GetFlags());
2681 	findReplacePanel->OnFindNext ( event );
2682 }
2683 
OnCommand(wxCommandEvent & WXUNUSED (event))2684 void MyFrame::OnCommand ( wxCommandEvent& WXUNUSED ( event ) )
2685 {
2686 	bool visible = manager.GetPane ( commandPanel ).IsShown();
2687 	if ( !visible )
2688 	{
2689 		manager.GetPane ( commandPanel ).Show();
2690 	}
2691 	manager.Update();
2692 	commandPanel->focusOnCommand();
2693 }
2694 
OnFindReplace(wxCommandEvent & WXUNUSED (event))2695 void MyFrame::OnFindReplace ( wxCommandEvent& WXUNUSED ( event ) )
2696 {
2697 #ifdef NEWFINDREPLACE
2698 	manager.GetPane ( findReplacePanel ).Caption ( _ ( "Replace" ) );
2699 	bool visible = manager.GetPane ( findReplacePanel ).IsShown();
2700 	if ( !visible )
2701 	{
2702 		manager.GetPane ( findReplacePanel ).Show();
2703 	}
2704 	manager.Update();
2705 	findReplacePanel->refresh();
2706 	findReplacePanel->setReplaceVisible ( true );
2707 	findReplacePanel->focusOnFind();
2708 	return;
2709 #endif
2710 
2711 
2712 	findDialog.reset ( new wxFindReplaceDialog (
2713 	                 this,
2714 	                 &findData,
2715 	                 _ ( "Find and Replace" ),
2716 	                 wxFR_REPLACEDIALOG ) );
2717 	findDialog->Show();
2718 }
2719 
OnGlobalReplace(wxCommandEvent & event)2720 void MyFrame::OnGlobalReplace ( wxCommandEvent& event )
2721 {
2722 	if ( getActiveDocument() == NULL )
2723 		return;
2724 
2725 	size_t flags = findData.GetFlags();
2726 	boost::scoped_ptr<GlobalReplaceDialog> grd ( new GlobalReplaceDialog (
2727 	            this,
2728 	            findData.GetFindString(),
2729 	            findData.GetReplaceString(),
2730 	            flags & wxFR_MATCHCASE,
2731 	            globalReplaceAllDocuments,
2732 	            findRegex ) );
2733 	int res = grd->ShowModal();
2734 
2735 	flags = 0;
2736 	flags |= wxFR_DOWN;
2737 	if ( grd->getMatchCase() )
2738 		flags |= wxFR_MATCHCASE;
2739 	findRegex = grd->getRegex();
2740 	globalReplaceAllDocuments = grd->getAllDocuments();
2741 
2742 	findData.SetFindString ( grd->getFindString() );
2743 	findData.SetReplaceString ( grd->getReplaceString() );
2744 	findData.SetFlags ( flags );
2745 	findReplacePanel->setRegex ( findRegex );
2746 	findReplacePanel->setMatchCase ( flags & wxFR_MATCHCASE );
2747 	findReplacePanel->refresh();
2748 
2749 	if ( res != wxID_OK )
2750 	{
2751 		return;
2752 	}
2753 
2754 	int globalMatchCount, pageCount;
2755 	globalMatchCount = 0;
2756 	pageCount = mainBook->GetPageCount();
2757 	XmlDoc *currentDoc = getActiveDocument();
2758 	if ( !currentDoc )
2759 		return;
2760 
2761 	for ( int i = 0; i < pageCount; ++i )
2762 	{
2763 		std::string bufferUtf8;
2764 		if ( !globalReplaceAllDocuments )
2765 		{
2766 			getRawText ( currentDoc, bufferUtf8 );
2767 		}
2768 		else
2769 		{
2770 			currentDoc = ( XmlDoc * ) mainBook->GetPage ( i );
2771 			if ( !currentDoc )
2772 				return;
2773 			getRawText ( currentDoc, bufferUtf8 );
2774 		}
2775 
2776 		size_t flags = findData.GetFlags();
2777 		if ( !findRegex )
2778 		{
2779 			std::string findUtf8, replaceUtf8;
2780 			findUtf8 =findData.GetFindString().mb_str ( wxConvUTF8 );
2781 			replaceUtf8 = findData.GetReplaceString().mb_str ( wxConvUTF8 );
2782 			globalMatchCount += Replace::run (
2783 			                        bufferUtf8,
2784 			                        findUtf8,
2785 			                        replaceUtf8,
2786 			                        flags & wxFR_MATCHCASE );
2787 			currentDoc->SetTextRaw ( bufferUtf8.c_str() );
2788 			currentDoc->setValidationRequired ( true );
2789 		}
2790 		else
2791 		{
2792 			try
2793 			{
2794 				boost::scoped_ptr<WrapRegex> wr ( new WrapRegex (
2795 				                                  ( const char * ) findData.GetFindString().mb_str ( wxConvUTF8 ),
2796 				                                  flags & wxFR_MATCHCASE,
2797 				                                  ( const char * ) findData.GetReplaceString().mb_str ( wxConvUTF8 ) ) );
2798 
2799 				int matchCount;
2800 				std::string outputBuffer = wr->replaceGlobal ( bufferUtf8, &matchCount );
2801 				globalMatchCount += matchCount;
2802 				currentDoc->SetTextRaw ( outputBuffer.c_str() );
2803 				currentDoc->setValidationRequired ( true );
2804 			}
2805 			catch ( std::exception& e )
2806 			{
2807 				wxString wideError = wxString ( e.what(), wxConvUTF8, strlen ( e.what() ) );
2808 				messagePane ( _ ( "Cannot replace: " ) + wideError, CONST_STOP );
2809 				return;
2810 			}
2811 		}
2812 		if ( !globalReplaceAllDocuments )
2813 			break;
2814 	}
2815 	wxString msg;
2816 
2817 	msg.Printf (
2818 	    wxPLURAL ( "%i replacement made", "%i replacements made", globalMatchCount ),
2819 	    globalMatchCount );
2820 
2821 	statusProgress ( msg );
2822 }
2823 
OnToggleComment(wxCommandEvent & event)2824 void MyFrame::OnToggleComment ( wxCommandEvent& event )
2825 {
2826 	XmlDoc *doc = getActiveDocument();
2827 	if ( doc == NULL )
2828 		return;
2829 
2830 	wxBusyCursor cursor;
2831 	doc->toggleComment();
2832 }
2833 
OnFrameClose(wxCloseEvent & event)2834 void MyFrame::OnFrameClose ( wxCloseEvent& event )
2835 {
2836 	wxCommandEvent e;
2837 	OnCloseAll ( e );
2838 	if ( mainBook->GetPageCount() )
2839 	{
2840 		event.Veto();
2841 		return;
2842 	}
2843 	event.Skip();
2844 }
2845 
OnNew(wxCommandEvent & WXUNUSED (event))2846 void MyFrame::OnNew ( wxCommandEvent& WXUNUSED ( event ) )
2847 {
2848 	wxString defaultSelection, typeSelection, templateFile;
2849 	defaultSelection = _ ( "XML document (*.xml)" );
2850 	if ( wxDirExists ( templateDir ) )
2851 	{
2852 		wxArrayString templateArray;
2853 		wxString templateMask, name, extension, entry;
2854 		wxFileName fn;
2855 		templateMask = templateDir + wxFileName::GetPathSeparator() + _T ( "*.*" );
2856 		templateFile = wxFindFirstFile ( templateMask, wxFILE );
2857 		while ( !templateFile.empty() )
2858 		{
2859 			templateFile.Replace ( _T("_"), _T(" ") );
2860 			fn.Assign ( templateFile );
2861 			name = fn.GetName();
2862 			extension = fn.GetExt();
2863 
2864 			entry.Printf ( _T ( "%s (*.%s)" ), name.c_str(), extension.c_str() );
2865 			templateArray.Add ( entry );
2866 
2867 			templateFile = wxFindNextFile();
2868 		}
2869 		templateArray.Sort();
2870 		templateArray.Insert ( defaultSelection, 0 );
2871 
2872 		wxSingleChoiceDialog scd (
2873 		    this, _ ( "Choose a document type:" ), _ ( "New Document" ), templateArray );
2874 		if ( scd.ShowModal() == wxID_CANCEL )
2875 		{
2876 			XmlDoc *doc = getActiveDocument();
2877 			if ( doc )
2878 				doc->SetFocus();
2879 			return;
2880 		}
2881 		typeSelection = scd.GetStringSelection();
2882 	}
2883 
2884 	if ( typeSelection == defaultSelection )
2885 	{
2886 		wxString emptyString ( _T ( "" ) );
2887 		newDocument ( emptyString );
2888 		return;
2889 	}
2890 
2891 	typeSelection.Replace ( _T ( " (*" ), wxEmptyString );
2892 	typeSelection.Replace ( _T ( ")" ), wxEmptyString );
2893 	typeSelection.Replace ( _T ( " " ), _T ( "_" ) );
2894 	templateFile = templateDir + typeSelection;
2895 	std::string templateFileLocal, buffer;
2896 	templateFileLocal = templateFile.mb_str ( wxConvLocal );
2897 	ReadFile::run ( templateFileLocal, buffer );
2898 	wxString documentContents = wxString ( buffer.c_str(), wxConvUTF8, buffer.size() );
2899 
2900 	newDocument ( buffer, templateFile );
2901 }
2902 
newDocument(const wxString & s,const wxString & path,bool canSave)2903 void MyFrame::newDocument ( const wxString& s, const wxString& path, bool canSave )
2904 {
2905 	std::string bufferUtf8 = ( const char * ) s.mb_str ( wxConvUTF8 );
2906 	newDocument ( bufferUtf8, path, canSave );
2907 }
2908 
newDocument(const std::string & s,const wxString & path,bool canSave)2909 void MyFrame::newDocument ( const std::string& s, const wxString& path, bool canSave )
2910 {
2911 	XmlDoc *doc;
2912 
2913 	wxString documentLabel;
2914 	documentLabel.Printf ( _ ( "Document%i" ), documentCount++ );
2915 
2916 	wxString auxPath = getAuxPath ( path );
2917 
2918 	{
2919 		wxWindowUpdateLocker noupdate (this);
2920 
2921 		doc = ( s.empty() ) ?
2922 			  new XmlDoc (
2923 				  mainBook,
2924 				  properties,
2925 				  &protectTags,
2926 				  visibilityState,
2927 				  FILE_TYPE_XML,
2928 				  wxID_ANY,
2929 				  NULL, 0 // new: NULL pointer leads to default document
2930 			  )
2931 			  : new XmlDoc (
2932 				  mainBook,
2933 				  properties,
2934 				  &protectTags,
2935 				  visibilityState,
2936 				  FILE_TYPE_XML,
2937 				  wxID_ANY,
2938 				  s.c_str(), // modified
2939 				  s.size(), // new
2940 				  path,
2941 				  auxPath );
2942 		mainBook->AddPage ( ( wxWindow * ) doc, documentLabel );
2943 	}
2944 
2945 	mainBook->Layout();
2946 
2947 	if ( properties.completion )
2948 		doc->updatePromptMaps();
2949 	doc->setShortFileName ( documentLabel );
2950 	doc->SetFocus();
2951 	manager.Update();
2952 	if ( properties.validateAsYouType )
2953 		doc->backgroundValidate();
2954 }
2955 
OnOpen(wxCommandEvent & event)2956 void MyFrame::OnOpen ( wxCommandEvent& event )
2957 {
2958 	bool largeFile;
2959 	largeFile = ( event.GetId() == ID_OPEN_LARGE_FILE );
2960 
2961 	wxString file = event.GetString();
2962 	if ( !file.empty() )
2963 	{
2964 		openFile ( file );
2965 		return;
2966 	}
2967 
2968 	wxString defaultFile, defaultDir;
2969 	XmlDoc *doc;
2970 	if ( ( doc = getActiveDocument() ) != NULL )
2971 	{
2972 		defaultDir = doc->getDirectory();
2973 		if ( defaultDir.empty() )
2974 			defaultDir = mLastDir;
2975 	}
2976 	else
2977 		defaultDir = mLastDir;
2978 
2979 	wxFileDialog fd (
2980 	    this,
2981 	    ( largeFile ) ? _ ( "Open Large Document" ) : _ ( "Open" ),
2982 	    defaultDir,
2983 	    wxEmptyString,
2984 	    FILE_FILTER,
2985 #if wxCHECK_VERSION(2,9,0)
2986 	    wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST
2987 #else
2988 	    wxOPEN | wxMULTIPLE | wxFILE_MUST_EXIST
2989 #endif
2990 	    );
2991 
2992 
2993 	if ( fd.ShowModal() == wxID_CANCEL )
2994 		return;
2995 
2996 	mLastDir = fd.GetDirectory();
2997 
2998 	wxArrayString paths;
2999 	fd.GetPaths ( paths );
3000 	size_t count = paths.Count();
3001 	if ( !count )
3002 		return;
3003 	for ( size_t i = 0; i < count; ++i )
3004 		if ( !openFile ( paths[i], largeFile ) )
3005 			break;
3006 }
3007 
openFile(const wxString & file,bool largeFile)3008 bool MyFrame::openFile ( const wxString &file, bool largeFile )
3009 {
3010 	wxFileName fn = WrapLibxml::URLToFileName ( file );
3011 	fn.Normalize();
3012 
3013 	wxString fileName = fn.GetFullPath();
3014 	if ( !fn.IsFileReadable() )
3015 	{
3016 		wxString message;
3017 		message.Printf ( _ ( "Cannot open %s." ), fileName.c_str() );
3018 		messagePane ( message, CONST_STOP );
3019 		return false;
3020 	}
3021 
3022 	if ( openFileSet.count ( fileName ) )
3023 	{
3024 		wxString message;
3025 		message.Printf ( _ ( "%s is already open" ), fileName.c_str() );
3026 		statusProgress ( message );
3027 		activateTab ( fileName );
3028 		return false;
3029 	}
3030 
3031 	wxString wideError;
3032 	pair<int, int> posPair;
3033 	XmlDoc *doc;
3034 
3035 	int type = getFileType ( fileName );
3036 	wxString auxPath = getAuxPath ( fileName );
3037 
3038 	char *docBuffer = NULL;
3039 	size_t docBufferLen = 0;
3040 	bool fileEmpty = false;
3041 
3042 	statusProgress ( _T ( "Opening file..." ) );
3043 	BinaryFile binaryfile ( fileName );
3044 	if ( !binaryfile.getData() )
3045 	{
3046 		wxString message;
3047 		message.Printf ( _ ( "Cannot open %s" ), fileName.c_str() );
3048 		messagePane ( message, CONST_STOP );
3049 		statusProgress ( wxEmptyString );
3050 		return false;
3051 	}
3052 	/*
3053 	//wxMemoryMappedFile memorymap (
3054 	  fileName,
3055 	  true, // readOnly
3056 	  true // fread
3057 	);
3058 	*/
3059 
3060 	/*
3061 	  catch (wxMemoryMappedFileEmptyException&)
3062 	  {
3063 	    fileEmpty = true;
3064 	  }
3065 	*/
3066 
3067 	bool isUtf8 = false;
3068 
3069 	if ( !fileEmpty )
3070 	{
3071 		docBuffer = ( char * ) binaryfile.getData();//memorymap->GetStream();
3072 		docBufferLen = binaryfile.getDataLen();//memorymap->GetMapSize();
3073 	}
3074 	else
3075 	{
3076 		docBuffer = NULL;
3077 		docBufferLen = 0;
3078 		isUtf8 = true;
3079 	}
3080 
3081 	statusProgress ( wxEmptyString );
3082 
3083 	wxCharBuffer iconvBuffer;
3084 	size_t iconvBufferLen = 0;
3085 
3086 	char *finalBuffer;
3087 	size_t finalBufferLen;
3088 
3089 	std::string encoding;
3090 	if ( docBufferLen >= 4 && // UTF-32 BE
3091 			( unsigned char ) docBuffer[0] == 0x00 &&
3092 			( unsigned char ) docBuffer[1] == 0x00 &&
3093 			( unsigned char ) docBuffer[2] == 0xFE &&
3094 			( unsigned char ) docBuffer[3] == 0xFF )
3095 	{
3096 		docBuffer += 4;
3097 		docBufferLen -= 4;
3098 		encoding = "UTF-32BE";
3099 	}
3100 	else if ( docBufferLen >= 4 && // UTF-32 LE
3101 			( unsigned char ) docBuffer[0] == 0xFF &&
3102 			( unsigned char ) docBuffer[1] == 0xFE &&
3103 			( unsigned char ) docBuffer[2] == 0x00 &&
3104 			( unsigned char ) docBuffer[3] == 0x00 )
3105 	{
3106 		docBuffer += 4;
3107 		docBufferLen -= 4;
3108 		encoding = "UTF-32LE";
3109 	}
3110 	else if ( docBufferLen >= 2 && //UTF-16 BE
3111 			( unsigned char ) docBuffer[0] == 0xFE &&
3112 			( unsigned char ) docBuffer[1] == 0xFF )
3113 	{
3114 		docBuffer += 2;
3115 		docBufferLen -= 2;
3116 		encoding = "UTF-16BE";
3117 	}
3118 	else if ( docBufferLen >= 2 && //UTF-16 LE
3119 			( unsigned char ) docBuffer[0] == 0xFF &&
3120 			( unsigned char ) docBuffer[1] == 0xFE )
3121 	{
3122 		docBuffer += 2;
3123 		docBufferLen -= 2;
3124 		encoding = "UTF-16LE";
3125 	}
3126 	else if ( docBufferLen >= 3 && //UTF-8
3127 			( unsigned char ) docBuffer[0] == 0xEF &&
3128 			( unsigned char ) docBuffer[1] == 0xBB &&
3129 			( unsigned char ) docBuffer[2] == 0xBF )
3130 	{
3131 		docBuffer += 3;
3132 		docBufferLen -= 3;
3133 		encoding = "UTF-8";
3134 	}
3135 
3136 	if ( encoding.empty() )
3137 	{
3138 		XmlEncodingSpy es;
3139 		es.parse ( docBuffer, docBufferLen );
3140 		encoding = es.getEncoding();
3141 		if ( encoding.empty() )  // Expat couldn't parse file (e.g. UTF-32)
3142 		{
3143 			encoding = getApproximateEncoding ( docBuffer, docBufferLen );
3144 			if ( encoding.empty() )
3145 				encoding = "UTF-8";
3146 		}
3147 	}
3148 
3149 	// convert buffer if not UTF-8
3150 	if ( encoding == "UTF-8" ||
3151 		encoding == "utf-8" ||
3152 		encoding == "US-ASCII" ||
3153 		encoding == "us-ascii" || // US-ASCII is a subset of UTF-8
3154 		docBufferLen == 0 )
3155 	{
3156 		finalBuffer = docBuffer;
3157 		finalBufferLen = docBufferLen;
3158 		isUtf8 = true;
3159 	}
3160 	else
3161 	{
3162 		wxString wideEncoding = wxString (
3163 		                            encoding.c_str(),
3164 		                            wxConvLocal,
3165 		                            encoding.size() );
3166 		iconv_t cd = iconv_open ( "UTF-8", encoding.c_str() );
3167 		if ( cd == ( iconv_t )-1 )
3168 		{
3169 			wxString message;
3170 			message.Printf ( _ ( "Cannot open %s: unknown encoding %s" ),
3171 			                 fileName.c_str(),
3172 			                 wideEncoding.c_str() );
3173 			messagePane ( message, CONST_STOP );
3174 			return false;
3175 		};
3176 
3177 		int iconvLenMultiplier = 4; // worst case scenario
3178 		if ( encoding == "ISO-8859-1" ||
3179 		        encoding == "UTF-16" ||
3180 		        encoding == "UTF-16BE" ||
3181 		        encoding == "UTF-16LE" )
3182 		{
3183 			iconvLenMultiplier = 2;
3184 		}
3185 		else if ( encoding == "UTF-32" ||
3186 		          encoding == "UTF-32BE" ||
3187 		          encoding == "UTF-32LE" )
3188 		{
3189 			iconvLenMultiplier = 1;
3190 		}
3191 
3192 		size_t nconv;
3193 		char *buffer;
3194 		size_t iconvBufferLeft, docBufferLeft;
3195 		iconvBufferLen = iconvBufferLeft = docBufferLen * iconvLenMultiplier + 1;
3196 		docBufferLeft = docBufferLen;
3197 		if ( ( ( ( size_t ) -1 ) - 1 ) / iconvLenMultiplier < docBufferLen
3198 			|| !iconvBuffer.extend ( iconvBufferLen ) )
3199 		{
3200 			wxString message;
3201 			message.Printf ( _ ( "Cannot open %s: out of memory" ),
3202 					fileName.c_str() );
3203 			messagePane ( message, CONST_STOP );
3204 			statusProgress ( wxEmptyString );
3205 			return false;
3206 		}
3207 		finalBuffer = buffer = iconvBuffer.data(); // buffer will be incremented by iconv
3208 		nconv = reinterpret_cast < universal_iconv & > ( iconv ) (
3209 		            cd,
3210 		            &docBuffer,
3211 		            &docBufferLeft,
3212 		            &buffer,
3213 		            &iconvBufferLeft );
3214 
3215 		*buffer = '\0';
3216 
3217 		iconv_close ( cd );
3218 
3219 		if ( nconv == ( size_t )-1 )
3220 		{
3221 			wxString message;
3222 			message.Printf ( _ ( "Cannot open %s: conversion from encoding %s failed" ),
3223 			                 fileName.c_str(),
3224 			                 wideEncoding.c_str() );
3225 			messagePane ( message, CONST_STOP );
3226 			return false;
3227 		}
3228 		finalBufferLen = iconvBufferLen - iconvBufferLeft;
3229 	}
3230 
3231 	statusProgress ( _ ( "Creating document view..." ) );
3232 	{
3233 		wxWindowUpdateLocker noupdate ( this );
3234 
3235 		doc = new XmlDoc (
3236 			mainBook,
3237 			( largeFile ) ? largeFileProperties: properties,
3238 			&protectTags,
3239 			visibilityState,
3240 			( !binaryfile.getDataLen() ) ? FILE_TYPE_XML : type,
3241 			wxID_ANY,
3242 			finalBuffer,
3243 			finalBufferLen,
3244 			fileName,
3245 			auxPath );
3246 #ifdef __WXMSW__
3247 		doc->SetUndoCollection ( false );
3248 		doc->SetUndoCollection ( true );
3249 #endif
3250 
3251 		doc->setFullFileName ( fileName );
3252 		openFileSet.insert ( fileName );
3253 		history.AddFileToHistory ( fileName );
3254 		updateFileMenu();
3255 
3256 		mainBook->AddPage ( ( wxWindow * ) doc, fn.GetFullName(), _T ( "" ) );
3257 	}
3258 	statusProgress ( wxEmptyString );
3259 
3260 	mainBook->Layout();
3261 
3262 	doc->setLastModified ( fn.GetModificationTime() );
3263 	doc->SetFocus();
3264 
3265 	if ( type != FILE_TYPE_XML || !binaryfile.getDataLen() )
3266 	{
3267 		return true;
3268 	}
3269 
3270 	// NOW parse the document, but don't create a UTF-8 copy
3271 	statusProgress ( _T ( "Parsing document..." ) );
3272 	boost::scoped_ptr<WrapExpat> we ( new WrapExpat() );
3273 
3274 	// omit XML declaration
3275 	if ( !isUtf8 && finalBufferLen > 5 &&
3276 	        finalBuffer[0] == '<' &&
3277 	        finalBuffer[1] == '?' &&
3278 	        finalBuffer[2] == 'x' &&
3279 	        finalBuffer[3] == 'm' &&
3280 	        finalBuffer[4] == 'l' )
3281 	{
3282 		for ( ; *finalBuffer && finalBufferLen; finalBuffer++ && finalBufferLen-- )
3283 		{
3284 			if ( *finalBuffer == '>' )
3285 			{
3286 				finalBuffer++;
3287 				finalBufferLen--;
3288 				break;
3289 			}
3290 		}
3291 	}
3292 
3293 	bool optimisedParseSuccess = false;
3294 	if ( finalBuffer )
3295 	{
3296 		optimisedParseSuccess = we->parse ( finalBuffer, finalBufferLen );
3297 		statusProgress ( wxEmptyString );
3298 	}
3299 
3300 	// NOW update prompt maps if necessary
3301 	if ( !largeFile && ( properties.completion || properties.validateAsYouType ) )
3302 	{
3303 		statusProgress ( _T ( "Compiling autocompletion lists..." ) );
3304 		doc->updatePromptMaps ( finalBuffer, finalBufferLen );
3305 		statusProgress ( wxEmptyString );
3306 	}
3307 
3308 	if ( !largeFile && ( properties.validateAsYouType && doc->getGrammarFound() ) )
3309 	{
3310 		statusProgress ( _T ( "Validating document..." ) );
3311 		//doc->backgroundValidate ( finalBuffer, doc->getFullFileName().mb_str(wxConvUTF8), finalBufferLen );
3312 		doc->backgroundValidate();
3313 		statusProgress ( wxEmptyString );
3314 	}
3315 
3316 	if ( !optimisedParseSuccess )
3317 	{
3318 		posPair = we->getErrorPosition();
3319 		-- ( posPair.first );
3320 		messagePane ( we->getLastError(), CONST_WARNING );
3321 
3322 		int newPosition = doc->PositionFromLine ( posPair.first );
3323 		doc->SetSelection ( newPosition, newPosition );
3324 		doc->SetFocus();
3325 		doc->setErrorIndicator ( posPair.first, posPair.second );
3326 	}
3327 	else
3328 	{
3329 		closeMessagePane();
3330 	}
3331 	return true;
3332 }
3333 
getApproximateEncoding(char * docBuffer,size_t docBufferLen)3334 std::string MyFrame::getApproximateEncoding ( char *docBuffer,
3335         size_t docBufferLen )
3336 {
3337 	std::string line;
3338 	char *it;
3339 	size_t i;
3340 
3341 	// grab first line
3342 	for (
3343 	    i = 0, it = docBuffer;
3344 	    i < docBufferLen && *it != '\n' && i < BUFSIZ;
3345 	    i++, it++ )
3346 	{
3347 		if ( *it )
3348 			line += *it;
3349 	}
3350 
3351 	std::pair<int, int> limits = XmlEncodingHandler::getEncodingValueLimits ( line );
3352 
3353 	if ( limits.first == -1 || limits.second == -1 )
3354 		return "";
3355 
3356 	return line.substr ( limits.first, limits.second );
3357 }
3358 
OnToggleFold(wxCommandEvent & WXUNUSED (event))3359 void MyFrame::OnToggleFold ( wxCommandEvent& WXUNUSED ( event ) )
3360 {
3361 	XmlDoc *doc;
3362 	if ( ( doc = getActiveDocument() ) == NULL )
3363 		return;
3364 	doc->toggleFold();
3365 }
3366 
OnFoldAll(wxCommandEvent & WXUNUSED (event))3367 void MyFrame::OnFoldAll ( wxCommandEvent& WXUNUSED ( event ) )
3368 {
3369 	XmlDoc *doc;
3370 	if ( ( doc = getActiveDocument() ) == NULL )
3371 		return;
3372 	doc->foldAll();
3373 	doc->SetFocus();
3374 }
3375 
OnUnfoldAll(wxCommandEvent & WXUNUSED (event))3376 void MyFrame::OnUnfoldAll ( wxCommandEvent& WXUNUSED ( event ) )
3377 {
3378 	XmlDoc *doc;
3379 	if ( ( doc = getActiveDocument() ) == NULL )
3380 		return;
3381 	doc->unfoldAll();
3382 	doc->SetFocus();
3383 }
3384 
3385 
OnQuit(wxCommandEvent & WXUNUSED (event))3386 void MyFrame::OnQuit ( wxCommandEvent& WXUNUSED ( event ) )
3387 {
3388 	Close ( true );
3389 }
3390 
OnUndo(wxCommandEvent & WXUNUSED (event))3391 void MyFrame::OnUndo ( wxCommandEvent& WXUNUSED ( event ) )
3392 {
3393 	XmlDoc *doc;
3394 	if ( ( doc = getActiveDocument() ) == NULL )
3395 		return;
3396 	doc->Undo();
3397 	doc->setValidationRequired ( true );
3398 	doc->SetFocus();
3399 }
3400 
OnRedo(wxCommandEvent & WXUNUSED (event))3401 void MyFrame::OnRedo ( wxCommandEvent& WXUNUSED ( event ) )
3402 {
3403 	XmlDoc *doc;
3404 	if ( ( doc = getActiveDocument() ) == NULL )
3405 		return;
3406 	doc->Redo();
3407 	doc->setValidationRequired ( true );
3408 	doc->SetFocus();
3409 }
3410 
OnRevert(wxCommandEvent & WXUNUSED (event))3411 void MyFrame::OnRevert ( wxCommandEvent& WXUNUSED ( event ) )
3412 {
3413 	XmlDoc *doc;
3414 	if ( ( doc = getActiveDocument() ) == NULL )
3415 		return;
3416 
3417 	while ( doc->GetModify() )
3418 	{
3419 		if ( !doc->CanUndo() )
3420 			return;
3421 		doc->Undo();
3422 		doc->setValidationRequired ( true );
3423 	}
3424 	doc->SetFocus();
3425 }
3426 
OnSpelling(wxCommandEvent & event)3427 void MyFrame::OnSpelling ( wxCommandEvent& event )
3428 {
3429 	XmlDoc *doc;
3430 	if ( ( doc = getActiveDocument() ) == NULL )
3431 		return;
3432 
3433 	statusProgress ( wxEmptyString );
3434 	closeMessagePane();
3435 
3436 #ifdef __WXMSW__
3437 	doc->SetUndoCollection ( false );
3438 	doc->SetUndoCollection ( true );
3439 #endif
3440 
3441 	int id, type;
3442 	id = event.GetId();
3443 	type = (id == ID_STYLE) ? ID_TYPE_STYLE : ID_TYPE_SPELL;
3444 
3445 
3446 	std::string rawBufferUtf8;
3447 	getRawText ( doc, rawBufferUtf8 );
3448 	bool success = true; // always true for now: well-formedness not req'd
3449 
3450 	boost::scoped_ptr<StyleDialog> sd ( new StyleDialog (
3451 	                               this,
3452 	                               wxICON ( appicon ),
3453 	                               rawBufferUtf8,
3454 	                               doc->getShortFileName(),
3455 	                               ruleSetDir,
3456 	                               filterDir,
3457 				                   ( type == ID_TYPE_SPELL ) ? dictionaryPreset : ruleSetPreset,
3458 	                               filterPreset,
3459  #ifdef __WXMSW__
3460                                    aspellDataPath,
3461                                    aspellDictPath,
3462  #endif
3463 					               type,
3464 	                               ( success ) ? false : true,
3465 	                               stylePosition,
3466 	                               styleSize ) );
3467 
3468 	if ( sd->ShowModal() == wxID_OK )
3469 	{
3470 		std::string bufferUtf8 = sd->getEditedString();
3471 		if ( bufferUtf8.empty() )
3472 			messagePane ( _ ( "Edited document empty" ), CONST_STOP );
3473 		else
3474 			doc->SetTextRaw ( bufferUtf8.c_str() );
3475 	}
3476 
3477 	// update presets if report has been created (even if followed by cancel)
3478 	if (type == ID_TYPE_STYLE)
3479 	{
3480 		ruleSetPreset = sd->getRuleSetPreset();
3481 		filterPreset = sd->getFilterPreset();
3482 	}
3483 	else
3484 		dictionaryPreset = sd->getRuleSetPreset();
3485 
3486 #ifdef __WXMSW__
3487 	stylePosition = sd->getPosition();
3488 	styleSize = sd->getSize();
3489 #endif
3490 }
3491 
OnPreviousDocument(wxCommandEvent & WXUNUSED (event))3492 void MyFrame::OnPreviousDocument ( wxCommandEvent& WXUNUSED ( event ) )
3493 {
3494 	if ( !getActiveDocument() )
3495 		return;
3496 
3497 	statusProgress ( wxEmptyString );
3498 	closeMessagePane();
3499 
3500 	int currentSelection = mainBook->GetSelection();
3501 	if ( currentSelection < 1 )
3502 		return;
3503 	mainBook->SetSelection ( --currentSelection );
3504 	XmlDoc *doc = getActiveDocument();
3505 	if ( doc )
3506 		doc->SetFocus();
3507 }
3508 
OnNextDocument(wxCommandEvent & WXUNUSED (event))3509 void MyFrame::OnNextDocument ( wxCommandEvent& WXUNUSED ( event ) )
3510 {
3511 	if ( !getActiveDocument() )
3512 		return;
3513 
3514 	statusProgress ( wxEmptyString );
3515 	closeMessagePane();
3516 
3517 	int currentSelection = mainBook->GetSelection();
3518 	int maxSelection = mainBook->GetPageCount();
3519 	if ( currentSelection >= ( maxSelection - 1 ) )
3520 		return;
3521 	mainBook->SetSelection ( ++currentSelection );
3522 	XmlDoc *doc = getActiveDocument();
3523 	if ( doc )
3524 		doc->SetFocus();
3525 }
3526 
OnSave(wxCommandEvent & event)3527 void MyFrame::OnSave ( wxCommandEvent& event )
3528 {
3529 	save();
3530 }
3531 
save()3532 void MyFrame::save()
3533 {
3534 	XmlDoc *doc;
3535 	if ( ( doc = getActiveDocument() ) == NULL )
3536 		return;
3537 
3538 	if ( doc->getDirectory().empty() )
3539 	{
3540 		wxCommandEvent event;
3541 		OnSaveAs ( event );
3542 		return;
3543 	}
3544 
3545 	wxString fileName = doc->getFullFileName();
3546 	if ( !saveFile ( doc, fileName, true ) )
3547 	{} // handle messages in saveFile
3548 }
3549 
OnReload(wxCommandEvent & event)3550 void MyFrame::OnReload ( wxCommandEvent& event )
3551 {
3552 	reloadTab();
3553 }
3554 
reloadTab()3555 void MyFrame::reloadTab()
3556 {
3557 	XmlDoc *doc;
3558 	if ( ( doc = getActiveDocument() ) == NULL )
3559 		return;
3560 	wxString fileName = doc->getFullFileName();
3561 
3562 	if ( closeActiveDocument() )
3563 		openFile ( fileName );
3564 }
3565 
OnSaveAs(wxCommandEvent & event)3566 void MyFrame::OnSaveAs ( wxCommandEvent& event )
3567 {
3568 	saveAs();
3569 }
3570 
saveAs()3571 void MyFrame::saveAs()
3572 {
3573 	XmlDoc *doc;
3574 	if ( ( doc = getActiveDocument() ) == NULL )
3575 		return;
3576 
3577 	wxString defaultFile, defaultDir;
3578 	defaultFile = doc->getShortFileName();
3579 	defaultDir = doc->getDirectory();
3580 	if ( defaultDir.empty() )
3581 		defaultDir = mLastDir;
3582 
3583 	boost::scoped_ptr<wxFileDialog> fd ( new wxFileDialog (
3584 	                                this,
3585 	                                _ ( "Save As" ),
3586 	                                defaultDir,
3587 	                                defaultFile,
3588 	                                FILE_FILTER,
3589 #if wxCHECK_VERSION(2,9,0)
3590 	                                wxFD_SAVE | wxFD_OVERWRITE_PROMPT ) );
3591 #else
3592 	                                wxSAVE | wxOVERWRITE_PROMPT ) );
3593 #endif
3594 	if ( fd->ShowModal() == wxID_CANCEL )
3595 		return;
3596 
3597 	wxString path = fd->GetPath();
3598 
3599 	if (
3600 	    openFileSet.count ( path ) &&
3601 	    path != doc->getFullFileName() )
3602 	{
3603 		wxString message;
3604 		message.Printf ( _ ( "%s is already open" ), path.c_str() );
3605 		messagePane ( message, CONST_STOP );
3606 		return;
3607 	}
3608 
3609 	wxString name = fd->GetFilename();
3610 	wxString directory;
3611 	wxFileName::SplitPath ( path, &directory, NULL, NULL );
3612 	if ( path == _T ( "" ) )
3613 		return;
3614 
3615 	if ( !saveFile ( doc, path, false ) )
3616 		return;
3617 
3618 	// if already named, remove from set of open files
3619 	openFileSet.erase ( doc->getFullFileName() );
3620 
3621 	doc->setFullFileName ( path );
3622 
3623 	history.AddFileToHistory ( path ); // update history
3624 	updateFileMenu();
3625 
3626 	int selection = mainBook->GetSelection();
3627 	if ( selection != -1 )
3628 		mainBook->SetPageText ( selection, name );
3629 
3630 	wxString title = showFullPathOnFrame ? path : name;
3631 	title += _T ( " - " );
3632 	title += _ ( "XML Copy Editor" );
3633 	SetTitle ( title );
3634 }
3635 
OnUpdateCloseAll(wxUpdateUIEvent & event)3636 void MyFrame::OnUpdateCloseAll ( wxUpdateUIEvent& event )
3637 {
3638 	event.Enable ( mainBook->GetPageCount() > 1 );
3639 }
3640 
OnUpdateReload(wxUpdateUIEvent & event)3641 void MyFrame::OnUpdateReload ( wxUpdateUIEvent& event )
3642 {
3643 	XmlDoc *doc;
3644 	if ( ( doc = getActiveDocument() ) == NULL )
3645 	{
3646 		event.Enable ( false );
3647 		return;
3648 	}
3649 	event.Enable ( !doc->getDirectory().empty() );
3650 }
3651 
OnUpdateCutCopy(wxUpdateUIEvent & event)3652 void MyFrame::OnUpdateCutCopy ( wxUpdateUIEvent& event )
3653 {
3654 	event.Enable ( getActiveDocument() != NULL );
3655 }
3656 
OnUpdateLocationPaneVisible(wxUpdateUIEvent & event)3657 void MyFrame::OnUpdateLocationPaneVisible ( wxUpdateUIEvent& event )
3658 {
3659 	if ( !viewMenu )
3660 		return;
3661 	wxAuiPaneInfo info = manager.GetPane ( locationPanel );
3662 	event.Check ( info.IsShown() );
3663 }
3664 
OnUpdateSavedOnly(wxUpdateUIEvent & event)3665 void MyFrame::OnUpdateSavedOnly ( wxUpdateUIEvent& event )
3666 {
3667 	XmlDoc *doc;
3668 	if ( ( doc = getActiveDocument() ) == NULL )
3669 	{
3670 		event.Enable ( false );
3671 		return;
3672 	}
3673 	event.Enable ( !doc->getDirectory().empty() );
3674 }
3675 
OnUpdateDocRange(wxUpdateUIEvent & event)3676 void MyFrame::OnUpdateDocRange ( wxUpdateUIEvent& event )
3677 {
3678 	event.Enable ( getActiveDocument() != NULL );
3679 }
3680 
OnUpdateReplaceRange(wxUpdateUIEvent & event)3681 void MyFrame::OnUpdateReplaceRange ( wxUpdateUIEvent& event )
3682 {
3683 	event.Enable ( getActiveDocument() != NULL );
3684 }
3685 
OnUpdateFindAgain(wxUpdateUIEvent & event)3686 void MyFrame::OnUpdateFindAgain ( wxUpdateUIEvent& event )
3687 {
3688 	if ( !getActiveDocument() || findData.GetFindString().empty() )
3689 	{
3690 		event.Enable ( false );
3691 		return;
3692 	}
3693 	event.Enable ( true );
3694 }
3695 
OnUpdateUndo(wxUpdateUIEvent & event)3696 void MyFrame::OnUpdateUndo ( wxUpdateUIEvent& event )
3697 {
3698 	XmlDoc *doc;
3699 	if ( ( doc = getActiveDocument() ) == NULL )
3700 	{
3701 		event.Enable ( false );
3702 		return;
3703 	}
3704 #ifdef __WXMSW__
3705 	event.Enable((doc->CanUndo()) ? true : false);
3706 #else
3707 	event.Enable ( ( doc->GetModify() ) ? true : false );
3708 #endif
3709 }
3710 
OnUpdateRedo(wxUpdateUIEvent & event)3711 void MyFrame::OnUpdateRedo ( wxUpdateUIEvent& event )
3712 {
3713 	XmlDoc *doc;
3714 	if ( ( doc = getActiveDocument() ) == NULL )
3715 	{
3716 		event.Enable ( false );
3717 		return;
3718 	}
3719 	event.Enable ( doc->CanRedo() );
3720 }
3721 
OnUpdatePaste(wxUpdateUIEvent & event)3722 void MyFrame::OnUpdatePaste ( wxUpdateUIEvent& event )
3723 {
3724 	event.Enable ( getActiveDocument() != NULL );
3725 }
3726 
OnUpdateToggleComment(wxUpdateUIEvent & event)3727 void MyFrame::OnUpdateToggleComment ( wxUpdateUIEvent& event )
3728 {
3729 	XmlDoc *doc = getActiveDocument();
3730 	if ( !doc )
3731 	{
3732 		event.Enable ( false );
3733 		return;
3734 	}
3735 
3736 	int from = doc->GetSelectionStart();
3737 	int to = doc->GetSelectionEnd();
3738 	event.Enable ( from != to || doc->getType() == FILE_TYPE_XML );
3739 }
3740 
OnUpdatePreviousDocument(wxUpdateUIEvent & event)3741 void MyFrame::OnUpdatePreviousDocument ( wxUpdateUIEvent& event )
3742 {
3743 	if ( !getActiveDocument() )
3744 	{
3745 		event.Enable ( false );
3746 		return;
3747 	}
3748 	int currentDocument = mainBook->GetSelection();
3749 	event.Enable ( ( currentDocument < 1 ) ? false : true );
3750 }
3751 
OnUpdateNextDocument(wxUpdateUIEvent & event)3752 void MyFrame::OnUpdateNextDocument ( wxUpdateUIEvent& event )
3753 {
3754 	if ( !getActiveDocument() )
3755 	{
3756 		event.Enable ( false );
3757 		return;
3758 	}
3759 	int currentDocument = mainBook->GetSelection();
3760 	int maxDocument = mainBook->GetPageCount();
3761 	event.Enable ( ( currentDocument >= ( maxDocument - 1 ) ) ? false : true );
3762 }
3763 
OnUpdateCloseMessagePane(wxUpdateUIEvent & event)3764 void MyFrame::OnUpdateCloseMessagePane ( wxUpdateUIEvent& event )
3765 {
3766 	wxAuiPaneInfo &info = manager.GetPane ( htmlReport );
3767 	event.Enable ( info.IsShown() );
3768 }
3769 
OnUpdateCloseFindReplacePane(wxUpdateUIEvent & event)3770 void MyFrame::OnUpdateCloseFindReplacePane ( wxUpdateUIEvent& event )
3771 {
3772 	wxAuiPaneInfo &info = manager.GetPane ( findReplacePanel );
3773 	event.Enable ( info.IsShown() );
3774 }
3775 
OnUpdateCloseCommandPane(wxUpdateUIEvent & event)3776 void MyFrame::OnUpdateCloseCommandPane ( wxUpdateUIEvent& event )
3777 {
3778 	wxAuiPaneInfo &info = manager.GetPane ( commandPanel );
3779 	event.Enable ( info.IsShown() );
3780 }
3781 
OnValidateDTD(wxCommandEvent & event)3782 void MyFrame::OnValidateDTD ( wxCommandEvent& event )
3783 {
3784 	statusProgress ( wxEmptyString );
3785 
3786 	// fetch document contents
3787 	XmlDoc *doc;
3788 	if ( ( doc = getActiveDocument() ) == NULL )
3789 		return;
3790 
3791 
3792 	doc->clearErrorIndicators();
3793 	statusProgress ( _ ( "DTD Validation in progress..." ) );
3794 
3795 	boost::scoped_ptr<WrapLibxml> wl ( new WrapLibxml ( libxmlNetAccess ) );
3796 	wxString fname = doc->getFullFileName();
3797 	if ( !wl->validate ( doc->myGetTextRaw(), fname ) )
3798 	{
3799 		wxString wideError = wl->getLastError();
3800 		statusProgress ( wxEmptyString );
3801 		messagePane ( wideError, CONST_WARNING );
3802 
3803 		std::pair<int, int> posPair = wl->getErrorPosition();
3804 		-- ( posPair.first );
3805 		int cursorPos =
3806 		    doc->PositionFromLine ( posPair.first );
3807 		doc->SetSelection ( cursorPos, cursorPos );
3808 
3809 		// shallow validate all
3810 		doc->backgroundValidate(); // has to come first as it deletes all indicators
3811 		doc->setErrorIndicator ( posPair.first, posPair.second );
3812 
3813 		return;
3814 	}
3815 	statusProgress ( wxEmptyString );
3816 	documentOk ( _ ( "valid" ) );
3817 }
3818 
OnValidateRelaxNG(wxCommandEvent & event)3819 void MyFrame::OnValidateRelaxNG ( wxCommandEvent& event )
3820 {
3821 	statusProgress ( wxEmptyString );
3822 
3823 	XmlDoc *doc;
3824 	if ( ( doc = getActiveDocument() ) == NULL )
3825 		return;
3826 
3827 	wxString fileName = doc->getFullFileName();
3828 
3829 	wxString defaultFile, defaultDir;
3830 	defaultFile = doc->getFullFileName();
3831 	defaultDir = doc->getDirectory();
3832 	if ( defaultDir.empty() )
3833 		defaultDir = mLastDir;
3834 
3835 	AssociateDialog ad (
3836 	    this,
3837 	    _ ( "Select RELAX NG grammar" ),
3838 	    _ ( "Choose a file:" ),
3839 	    _ ( "RELAX NG grammar" ),
3840 	    _T ( "*.*" ),
3841 	    lastRelaxNGSchema,
3842 	    &mLastDir );
3843 	if ( ad.ShowModal() != wxID_OK )
3844 		return;
3845 
3846 	const wxString &url = lastRelaxNGSchema = ad.getUrl();
3847 	if ( url.empty() )
3848 	{
3849 		statusProgress ( wxEmptyString );
3850 		return;
3851 	}
3852 
3853 	validateRelaxNG ( doc, url, fileName );
3854 }
3855 
validateRelaxNG(XmlDoc * doc,const wxString & schemaUrl,wxString & fileName)3856 void MyFrame::validateRelaxNG (
3857     XmlDoc *doc,
3858     const wxString& schemaUrl,
3859     wxString& fileName ) // not const: may change if empty/document modified
3860 {
3861 	statusProgress ( wxEmptyString );
3862 
3863 	if ( !doc )
3864 		return;
3865 
3866 	doc->clearErrorIndicators();
3867 	statusProgress ( _ ( "RELAX NG validation in progress..." ) );
3868 
3869 	boost::scoped_ptr<WrapLibxml> wl ( new WrapLibxml ( libxmlNetAccess ) );
3870 	if ( !wl->validateRelaxNG ( schemaUrl, doc->myGetTextRaw(), fileName ) )
3871 	{
3872 		wxString wideError = wl->getLastError();
3873 		statusProgress ( wxEmptyString );
3874 
3875 		std::pair<int, int> posPair = wl->getErrorPosition();
3876 		-- ( posPair.first );
3877 
3878 		int cursorPos =
3879 		    doc->PositionFromLine ( posPair.first );
3880 		doc->SetSelection ( cursorPos, cursorPos );
3881 		doc->setErrorIndicator ( posPair.first, posPair.second );
3882 		messagePane ( wideError, CONST_WARNING );
3883 		doc->SetFocus();
3884 		return;
3885 	}
3886 
3887 	statusProgress ( wxEmptyString );
3888 	documentOk ( _ ( "valid" ) );
3889 	doc->SetFocus();
3890 }
3891 
OnValidatePreset(wxCommandEvent & event)3892 void MyFrame::OnValidatePreset ( wxCommandEvent& event )
3893 {
3894 	XmlDoc *doc;
3895 	if ( ( doc = getActiveDocument() ) == NULL )
3896 		return;
3897 
3898 	wxString fileName = doc->getFullFileName();
3899 
3900 	int id = event.GetId();
3901 	const wxString &schemaUrl = validationPresetMap[id];
3902 	if ( schemaUrl.empty() )
3903 		return;
3904 	validateRelaxNG ( doc, schemaUrl, fileName );
3905 }
3906 
OnValidateSchema(wxCommandEvent & event)3907 void MyFrame::OnValidateSchema ( wxCommandEvent& event )
3908 {
3909 	statusProgress ( wxEmptyString );
3910 
3911 	XmlDoc *doc;
3912 	if ( ( doc = getActiveDocument() ) == NULL )
3913 		return;
3914 
3915 	// branch: if no XML Schema found, use LibXML DTD parser instead
3916 	// so the catalog is read - switch when Xerces-C implements
3917 	// XMLCatalogResolver
3918 #if 0
3919 	{
3920 		std::string rawBuffer;
3921 		getRawText ( doc, rawBuffer );
3922 		XmlSchemaLocator xsl ( "UTF-8" );
3923 		xsl.parse ( rawBuffer.c_str() );
3924 		if ( ( xsl.getSchemaLocation() ).empty() )
3925 		{
3926 			OnValidateDTD ( event );
3927 			return;
3928 		}
3929 	}
3930 #endif
3931 
3932 	statusProgress ( _ ( "Validation in progress..." ) );
3933 	doc->clearErrorIndicators();
3934 
3935 	wxString fileName = doc->getFullFileName();
3936 	std::string utf8Buffer = doc->myGetTextRaw();
3937 	boost::scoped_ptr<WrapXerces> validator ( new WrapXerces() );
3938 	int severity;
3939 	wxString message;
3940 	if ( validator->validateMemory ( utf8Buffer.c_str(), utf8Buffer.size(),
3941 			fileName ) )
3942 	{
3943 		message.Printf ( _ ( "%s is valid" ),
3944 		                 doc->getShortFileName().c_str() );
3945 		if ( validator->getLastError().empty() )
3946 			severity = CONST_INFO;
3947 		else
3948 		{
3949 			severity = CONST_WARNING;
3950 			message << _T ( "[br][br]" );
3951 		}
3952 	}
3953 	else
3954 	{
3955 		severity = CONST_STOP;
3956 	}
3957 	statusProgress ( wxEmptyString );
3958 	message << validator->getLastError();
3959 	messagePane ( message, severity );
3960 
3961 	if ( severity != CONST_INFO )
3962 	{
3963 		std::pair<int, int> posPair = validator->getErrorPosition();
3964 		int cursorPos =
3965 		    doc->PositionFromLine ( posPair.first - 1 );
3966 		doc->SetSelection ( cursorPos, cursorPos );
3967 		doc->setErrorIndicator ( posPair.first - 1, 0 );
3968 	}
3969 }
3970 
OnCreateSchema(wxCommandEvent & event)3971 void MyFrame::OnCreateSchema ( wxCommandEvent& event )
3972 {
3973 	statusProgress ( wxEmptyString );
3974 
3975 	XmlDoc *doc = getActiveDocument();
3976 	if ( doc == NULL )
3977 		return;
3978 
3979 	std::string rawBufferUtf8;
3980 	getRawText ( doc, rawBufferUtf8 );
3981 
3982 	const static wxString types[] = { _ ( "W3C Schema" ), _ ( "DTD" ) };
3983 	const static wxString message = _ ( "Please choose a shema type");
3984 	wxSingleChoiceDialog dlg ( this, message, _ ( "Schema type" ),
3985 			( int ) sizeof ( types ) / sizeof ( types[0] ), types );
3986 	int ret = dlg.ShowModal();
3987 	if ( ret == wxID_CANCEL ) return;
3988 
3989 	Grammar::GrammarType type = ( dlg.GetSelection() == 0 ) ?
3990 			Grammar::SchemaGrammarType : Grammar::DTDGrammarType;
3991 	XmlSchemaGenerator gen;
3992 	const wxString &schema = gen.generate(type, doc->getFullFileName(),
3993 	    rawBufferUtf8.c_str(), rawBufferUtf8.size(), _T ( "UTF-8" ) );
3994 	if (schema.IsEmpty()) {
3995 		messagePane ( gen.getLastError(), CONST_WARNING );
3996 		return;
3997 	}
3998 	newDocument ( schema );
3999 }
4000 
OnDtd2Schema(wxCommandEvent & event)4001 void MyFrame::OnDtd2Schema ( wxCommandEvent& event )
4002 {
4003 	closeMessagePane();
4004 
4005 #if wxCHECK_VERSION(2,9,0)
4006 	long style = wxFD_OPEN | wxFD_FILE_MUST_EXIST;
4007 #else
4008 	long style = wxOPEN | wxFILE_MUST_EXIST;
4009 #endif
4010 	wxFileDialog fd ( this, _ ( "Please select a DTD file" ), wxEmptyString,
4011 	    wxEmptyString, _T ( "DTD files (*.dtd)|*.dtd|All files (*.*)|*.*" ),
4012 	    style );
4013 	if (fd.ShowModal() != wxID_OK)
4014 		return;
4015 
4016 	statusProgress ( _ ( "Converting..." ) );
4017 
4018 	Dtd2Schema dtd2xsd;
4019 	const wxString &schema = dtd2xsd.convert ( fd.GetPath() );
4020 	const wxString &error = dtd2xsd.getErrors();
4021 	if ( !error.empty() )
4022 		messagePane ( error, CONST_STOP );
4023 	if ( !schema.empty() )
4024 	{
4025 		statusProgress ( _ ( "Creating document view..." ) );
4026 		newDocument ( schema );
4027 	}
4028 
4029 	statusProgress ( wxEmptyString );
4030 }
4031 
OnXPath(wxCommandEvent & event)4032 void MyFrame::OnXPath ( wxCommandEvent& event )
4033 {
4034 	statusProgress ( wxEmptyString );
4035 	closeMessagePane();
4036 
4037 	XmlDoc *doc;
4038 	if ( ( doc = getActiveDocument() ) == NULL )
4039 		return;
4040 
4041 	boost::scoped_ptr<wxTextEntryDialog> dlg ( new wxTextEntryDialog (
4042 	                                      this,
4043 	                                      _ ( "Enter XPath:" ),
4044 	                                      _ ( "Evaluate XPath" ),
4045 	                                      xpathExpression ) );
4046 
4047 	int ret = dlg->ShowModal();
4048 	if ( ret == wxID_CANCEL )
4049 		return;
4050 	xpathExpression = dlg->GetValue();
4051 
4052 	// fetch document contents
4053 	std::string utf8Buffer;
4054 	getRawText ( doc, utf8Buffer );
4055 
4056 	boost::scoped_ptr<WrapLibxml> wl ( new WrapLibxml ( libxmlNetAccess ) );
4057 	bool success = wl->xpath ( xpathExpression, utf8Buffer,
4058 			doc->getFullFileName() );
4059 
4060 	if ( !success )
4061 	{
4062 		wxString wideError = wl->getLastError();
4063 		if ( !wideError.empty() )
4064 			wideError.Prepend ( _T ( ": " ) );
4065 		wideError.Prepend ( _ ( "Cannot evaluate XPath" ) );
4066 
4067 		messagePane ( wideError, CONST_WARNING );
4068 		return;
4069 	}
4070 
4071 	statusProgress ( wxEmptyString );
4072 	std::string buffer = wl->getOutput();
4073 
4074 	if ( buffer.empty() )
4075 	{
4076 		messagePane ( _ ( "No matching nodes found" ), CONST_WARNING );
4077 		return;
4078 	}
4079 	newDocument ( buffer );
4080 	statusProgress ( wxEmptyString );
4081 }
4082 
OnXslt(wxCommandEvent & event)4083 void MyFrame::OnXslt ( wxCommandEvent& event )
4084 {
4085 	statusProgress ( wxEmptyString );
4086 	closeMessagePane();
4087 
4088 	// fetch document contents
4089 	XmlDoc *doc;
4090 	if ( ( doc = getActiveDocument() ) == NULL )
4091 		return;
4092 
4093 	std::string rawBufferUtf8 = doc->myGetTextRaw();
4094 
4095 	wxString path;
4096 	int id = event.GetId();
4097 	if ( id == ID_XSLT )
4098 	{
4099 		XslLocator xl ( "UTF-8" );
4100 		xl.parse ( rawBufferUtf8 );
4101 		std::string location = xl.getXslLocation();
4102 
4103 		path = wxString ( location.c_str(), wxConvUTF8, location.size() );
4104 
4105 		path = PathResolver::run ( path, doc->getFullFileName() );
4106 
4107 		if ( !wxFileExists ( path ) )
4108 		{
4109 			if ( !path.empty() )
4110 			{
4111 				wxString message;
4112 				message.Printf ( _ ( "Cannot open stylesheet %s" ), path.c_str() );
4113 				messagePane ( message, CONST_WARNING );
4114 			}
4115 
4116 			wxString defaultFile, defaultDir;
4117 			defaultFile = doc->getFullFileName();
4118 			defaultDir = doc->getDirectory();
4119 			if ( defaultDir.empty() )
4120 				defaultDir = mLastDir;
4121 
4122 			AssociateDialog ad (
4123 			    this,
4124 			    _ ( "Select stylesheet" ),
4125 			    _ ( "Choose a file:" ),
4126 			    _ ( "XSLT stylesheet" ),
4127 			    _T ( "*.xsl;*.xslt" ),
4128 			    lastXslStylesheet,
4129 			    &mLastDir );
4130 			if ( ad.ShowModal() != wxID_OK )
4131 				return;
4132 
4133 			path = lastXslStylesheet = ad.getUrl();
4134 
4135 
4136 			if ( path.empty() ) // Cancel selected
4137 			{
4138 				statusProgress ( wxEmptyString );
4139 				return;
4140 			}
4141 		}
4142 	}
4143 	else
4144 	{
4145 		wxString sep;
4146 		sep.Append ( wxFileName::GetPathSeparator() );
4147 		switch ( id )
4148 		{
4149 			case ID_XSLT_TEI_FO:
4150 				path = applicationDir + sep + _T ( "tei" ) + sep + _T ( "fo" ) + sep +
4151 				       _T ( "tei.xsl" );
4152 				break;
4153 			case ID_XSLT_TEI_HTML:
4154 				path = applicationDir + sep + _T ( "tei" ) + sep + _T ( "html" ) + sep +
4155 				       _T ( "tei.xsl" );
4156 				break;
4157 			case ID_XSLT_TEI_XHTML:
4158 				path = applicationDir + sep + _T ( "tei" ) + sep + _T ( "xhtml" ) + sep +
4159 				       _T ( "tei.xsl" );
4160 				break;
4161 			case ID_XSLT_TEI_LATEX:
4162 				path = applicationDir + sep + _T ( "tei" ) + sep + _T ( "latex" ) + sep +
4163 				       _T ( "tei.xsl" );
4164 				break;
4165 			case ID_XSLT_DOCBOOK_FO:
4166 				path = applicationDir + sep + _T ( "docbook" ) + sep + _T ( "fo" ) + sep +
4167 				       _T ( "docbook.xsl" );
4168 				break;
4169 			case ID_XSLT_DOCBOOK_HTML:
4170 				path = applicationDir + sep + _T ( "docbook" ) + sep + _T ( "html" ) + sep +
4171 				       _T ( "docbook.xsl" );
4172 				break;
4173 			case ID_XSLT_DOCBOOK_XHTML:
4174 				path = applicationDir + sep + _T ( "docbook" ) + sep + _T ( "xhtml" ) + sep +
4175 				       _T ( "docbook.xsl" );
4176 				break;
4177 			default:
4178 				break;
4179 		}
4180 	}
4181 	statusProgress ( _ ( "XSL transformation in progress..." ) );
4182 
4183 	boost::scoped_ptr<WrapLibxml> wl ( new WrapLibxml ( libxmlNetAccess ) );
4184 	wxString fileName = doc->getFullFileName();
4185 	if ( !wl->xslt ( path, rawBufferUtf8, fileName ) )
4186 	{
4187 		wxString wideError = wl->getLastError();
4188 		wideError.Prepend ( _ ( "Cannot transform: " ) );
4189 		statusProgress ( wxEmptyString );
4190 		messagePane ( wideError, CONST_WARNING );
4191 		return;
4192 	}
4193 	std::string buffer = wl->getOutput();
4194 	if ( buffer.empty() )
4195 	{
4196 		messagePane ( _ ( "Output document empty" ), CONST_WARNING );
4197 		return;
4198 	}
4199 	statusProgress ( wxEmptyString );
4200 	newDocument ( buffer );
4201 }
4202 
OnPrettyPrint(wxCommandEvent & event)4203 void MyFrame::OnPrettyPrint ( wxCommandEvent& event )
4204 {
4205 	statusProgress ( wxEmptyString );
4206 	closeMessagePane();
4207 
4208 	// fetch document contents
4209 	XmlDoc *doc;
4210 	if ( ( doc = getActiveDocument() ) == NULL )
4211 		return;
4212 
4213 	int line = doc->LineFromPosition ( doc->GetCurrentPos() );
4214 
4215 	std::string rawBufferUtf8;
4216 	getRawText ( doc, rawBufferUtf8 );
4217 
4218 	std::string encoding = XmlEncodingHandler::get ( rawBufferUtf8 );
4219 
4220 	statusProgress ( _ ( "Pretty-printing in progress..." ) );
4221 
4222 	wxString fileName = doc->getFullFileName();
4223 	boost::scoped_ptr<WrapLibxml> wl ( new WrapLibxml ( libxmlNetAccess ) );
4224 	for ( int i = 0; i < 2; i++ ) // perform two iterations
4225 	{
4226 
4227 		if ( !wl->parse ( rawBufferUtf8, fileName, true ) )
4228 		{
4229 			wxString wideError = wl->getLastError();
4230 			wideError.Prepend ( _ ( "Cannot pretty-print: " ) );
4231 			statusProgress ( wxEmptyString );
4232 			messagePane ( wideError, CONST_WARNING );
4233 			return;
4234 		}
4235 		rawBufferUtf8 = wl->getOutput();
4236 	}
4237 
4238 	statusProgress ( wxEmptyString );
4239 	if ( rawBufferUtf8.empty() )
4240 		messagePane (
4241 		    _ ( "Pretty-print unsuccessful: output document empty" ),
4242 		    CONST_STOP );
4243 	else
4244 	{
4245 		if ( encoding != "UTF-8" && !encoding.empty() )
4246 		{
4247 			XmlEncodingHandler::set ( rawBufferUtf8, encoding );
4248 		}
4249 		doc->SetTextRaw ( rawBufferUtf8.c_str() );
4250 		statusProgress ( wxEmptyString );
4251 	}
4252 
4253 	doc->setValidationRequired ( true );
4254 	doc->GotoLine ( line );
4255 	doc->SetFocus();
4256 }
4257 
OnEncoding(wxCommandEvent & event)4258 void MyFrame::OnEncoding ( wxCommandEvent& event )
4259 {
4260 	statusProgress ( wxEmptyString );
4261 	closeMessagePane();
4262 
4263 	// fetch document contents
4264 	XmlDoc *doc;
4265 	if ( ( doc = getActiveDocument() ) == NULL )
4266 		return;
4267 
4268 	const static wxString encodings[] = {
4269 		_T ( "UTF-8" ), _T ( "UTF-16" ), _T ( "UTF-16LE" ),
4270 		_T ( "UTF-16BE" ), _T ( "ISO-8859-1" ), _T ( "US-ASCII" )
4271 	};
4272 	wxSingleChoiceDialog scd (
4273 	    this, _ ( "Choose an encoding:" ), _ ( "Encoding" ),
4274 	    sizeof ( encodings ) / sizeof ( encodings[0] ), encodings );
4275 	if ( scd.ShowModal() == wxID_CANCEL )
4276 		return;
4277 
4278 	int res;
4279 	wxMemoryBuffer output;
4280 	boost::scoped_ptr<WrapLibxml> wl ( new WrapLibxml ( libxmlNetAccess ) );
4281 	res = wl->saveEncoding ( doc->myGetTextRaw(), doc->getFullFileName(),
4282 			wxEmptyString, &output, scd.GetStringSelection() );
4283 	if ( res == -1 )
4284 	{
4285 		wxString wideError = wl->getLastError();
4286 		wideError.Prepend ( _ ( "Cannot set encoding: " ) );
4287 		messagePane ( wideError, CONST_STOP );
4288 		return;
4289 	}
4290 
4291 	boost::scoped_ptr<XmlUtf8Reader> xur ( new XmlUtf8Reader (
4292 	                                       false,
4293 	                                       expandInternalEntities,
4294 	                                       output.GetDataLen() ) );
4295 	if ( !xur->parse ( ( const char * ) output.GetData(), output.GetDataLen() ) )
4296 	{
4297 		messagePane ( _ ( "Cannot set encoding (cannot parse temporary file)" ),
4298 		              CONST_STOP );
4299 		return;
4300 	}
4301 
4302 	doc->SetTextRaw ( xur->getBuffer().c_str() );
4303 	doc->setValidationRequired ( true );
4304 	doc->SetFocus();
4305 }
4306 
OnHome(wxCommandEvent & event)4307 void MyFrame::OnHome ( wxCommandEvent& event )
4308 {
4309 	wxLaunchDefaultBrowser ( _T ( "http://xml-copy-editor.sourceforge.net" ) );
4310 }
4311 
OnDownloadSource(wxCommandEvent & event)4312 void MyFrame::OnDownloadSource ( wxCommandEvent& event )
4313 {
4314 	wxLaunchDefaultBrowser ( _T ( "http://sourceforge.net/p/xml-copy-editor/code/" ) );
4315 }
4316 
OnToolbarVisible(wxCommandEvent & event)4317 void MyFrame::OnToolbarVisible ( wxCommandEvent& event )
4318 {
4319 	if ( !viewMenu )
4320 		return;
4321 	toolbarVisible = ( toolbarVisible ) ? false : true;
4322 	viewMenu->Check ( ID_TOOLBAR_VISIBLE, toolbarVisible );
4323 	showTopBars ( toolbarVisible );
4324 	manager.Update();
4325 }
4326 
OnWrapWords(wxCommandEvent & event)4327 void MyFrame::OnWrapWords ( wxCommandEvent& event )
4328 {
4329 	if ( !viewMenu )
4330 		return;
4331 
4332 	bool wrapWords;
4333 	wrapWords = ( properties.wrap ) ? false : true;
4334 
4335 	viewMenu->Check ( ID_WRAP_WORDS, wrapWords );
4336 	properties.wrap = wrapWords;
4337 
4338 	// update all documents
4339 	int pageCount = mainBook->GetPageCount();
4340 	XmlDoc *currentDoc;
4341 	for ( int i = 0; i < pageCount; ++i )
4342 	{
4343 		currentDoc = ( XmlDoc * ) mainBook->GetPage ( i );
4344 		if ( !currentDoc )
4345 			break;
4346 		currentDoc->SetWrapMode ( wrapWords );
4347 	}
4348 }
4349 
OnLocationPaneVisible(wxCommandEvent & event)4350 void MyFrame::OnLocationPaneVisible ( wxCommandEvent& event )
4351 {
4352 	wxAuiPaneInfo info = manager.GetPane ( locationPanel );
4353 	bool visible = ( info.IsShown() ) ? false : true;
4354 	manager.GetPane ( locationPanel ).Show ( visible );
4355 	manager.Update();
4356 
4357 	XmlDoc *doc;
4358 	if ( ( doc = getActiveDocument() ) == NULL )
4359 		return;
4360 	doc->SetFocus();
4361 }
4362 
OnProtectTags(wxCommandEvent & event)4363 void MyFrame::OnProtectTags ( wxCommandEvent& event )
4364 {
4365 	if ( !xmlMenu )
4366 		return;
4367 	protectTags = ( protectTags ) ? false : true;
4368 	if ( xmlMenu )
4369 		xmlMenu->Check ( ID_PROTECT_TAGS, protectTags );
4370 	if ( toolBar )
4371 		toolBar->ToggleTool ( ID_PROTECT_TAGS, protectTags );
4372 
4373 	XmlDoc *doc;
4374 	if ( ( doc = getActiveDocument() ) == NULL )
4375 		return;
4376 
4377 	if ( protectTags )
4378 		doc->adjustCursor(); // apply to all open docs?
4379 
4380 	doc->SetFocus();
4381 }
4382 
OnVisibilityState(wxCommandEvent & event)4383 void MyFrame::OnVisibilityState ( wxCommandEvent& event )
4384 {
4385 
4386 	int id;
4387 	id = event.GetId();
4388 	switch ( id )
4389 	{
4390 		case ID_SHOW_TAGS:
4391 			visibilityState = SHOW_TAGS;
4392 			//GetStatusBar()->SetStatusText(wxEmptyString, STATUS_PARENT);
4393 			break;
4394 		case ID_HIDE_ATTRIBUTES:
4395 			visibilityState = HIDE_ATTRIBUTES;
4396 			//GetStatusBar()->SetStatusText(wxEmptyString, STATUS_PARENT);
4397 			break;
4398 		case ID_HIDE_TAGS:
4399 			visibilityState = HIDE_TAGS;
4400 			break;
4401 		default:
4402 			visibilityState = SHOW_TAGS;
4403 			break;
4404 	}
4405 	if ( viewMenu )
4406 		viewMenu->Check ( id, true );
4407 
4408 	// iterate over all open documents
4409 	int pageCount = mainBook->GetPageCount();
4410 	XmlDoc *currentDoc;
4411 	for ( int i = 0; i < pageCount; ++i )
4412 	{
4413 		currentDoc = ( XmlDoc * ) mainBook->GetPage ( i );
4414 		if ( !currentDoc )
4415 			break;
4416 		currentDoc->applyVisibilityState ( visibilityState );
4417 	}
4418 
4419 	if ( visibilityState == HIDE_ATTRIBUTES || visibilityState == HIDE_TAGS )
4420 	{
4421 		if ( properties.protectHiddenElements && !protectTags )
4422 		{
4423 			wxCommandEvent e;
4424 			OnProtectTags ( e );
4425 		}
4426 	}
4427 
4428 	// fetch current document
4429 	XmlDoc *doc;
4430 	if ( ( doc = getActiveDocument() ) == NULL )
4431 		return;
4432 
4433 	// set focus for current document
4434 	doc->SetFocus();
4435 }
4436 
OnFeedback(wxCommandEvent & event)4437 void MyFrame::OnFeedback ( wxCommandEvent& event )
4438 {
4439 	wxString forumUrl =
4440 	    _T ( "https://sourceforge.net/p/xml-copy-editor/discussion/475215/" );
4441 	wxLaunchDefaultBrowser ( forumUrl );
4442 }
4443 
findAgain(wxString s,int flags)4444 void MyFrame::findAgain ( wxString s, int flags )
4445 {
4446 	findReplacePanel->flagNotFound ( false );
4447 
4448 	if ( s.empty() )
4449 		return;
4450 
4451 	statusProgress ( wxEmptyString );
4452 	XmlDoc *doc;
4453 	if ( ( doc = getActiveDocument() ) == NULL )
4454 		return;
4455 
4456 	// update regex parameter to keep global replace in sync
4457 	findRegex = findReplacePanel->getRegex();
4458 
4459 	int newLocation;
4460 	int myFlags = 0;
4461 	if ( flags & wxFR_WHOLEWORD )
4462 		myFlags |= wxSTC_FIND_WHOLEWORD;
4463 	if ( flags & wxFR_MATCHCASE )
4464 		myFlags |= wxSTC_FIND_MATCHCASE;
4465 	if ( findReplacePanel->getRegex() )
4466 		myFlags |= wxSTC_FIND_REGEXP;
4467 
4468 	//doc->SetYCaretPolicy(wxSTC_CARET_SLOP | wxSTC_CARET_STRICT, 10);
4469 
4470 	if ( flags & wxFR_DOWN ) // find next
4471 	{
4472 		doc->SetTargetStart ( findReplacePanel->getIncrementalFind()
4473 				? doc->GetSelectionStart()  : doc->GetSelectionEnd() );
4474 		doc->SetTargetEnd ( doc->GetLength() );
4475 		doc->SetSearchFlags ( myFlags );
4476 		newLocation = doc->SearchInTarget ( s );
4477 
4478 		// try once more from top
4479 		if ( newLocation == -1 )
4480 		{
4481 			doc->SetTargetStart ( 0 );
4482 			doc->SetTargetEnd ( doc->GetLength() );
4483 			newLocation = doc->SearchInTarget ( s );
4484 		}
4485 	}
4486 	else // find previous
4487 	{
4488 		doc->SetCurrentPos (
4489 		    ( doc->GetSelectionStart() ) ? doc->GetSelectionStart() - 1 : 0 );
4490 		doc->SearchAnchor();
4491 		newLocation = doc->SearchPrev ( myFlags, s );
4492 	}
4493 
4494 	//doc->SetYCaretPolicy(wxSTC_CARET_SLOP, 0);
4495 
4496 
4497 	if ( newLocation == -1 )
4498 	{
4499 		findReplacePanel->flagNotFound ( true );
4500 		wxString err;
4501 		err.Printf ( _ ( "Cannot find '%s'" ), s.c_str() );
4502 		doc->SetSelectionEnd ( doc->GetSelectionStart() );
4503 
4504 		statusProgress ( err );
4505 
4506 		// must clear target to prevent replace affecting whole document
4507 		doc->SetTargetStart ( 0 );
4508 		doc->SetTargetEnd ( 0 );
4509 
4510 		return;
4511 	}
4512 
4513 	doc->SetSelection ( doc->GetTargetStart(), doc->GetTargetEnd() );
4514 	doc->EnsureCaretVisible();
4515 }
4516 
closeActiveDocument()4517 bool MyFrame::closeActiveDocument()
4518 {
4519 	statusProgress ( wxEmptyString );
4520 	closeMessagePane();
4521 
4522 	int selection = mainBook->GetSelection();
4523 	if ( selection == -1 || !mainBook->GetPageCount() ) // GetPageCount needed for wxAuiNotebook
4524 		return false;
4525 
4526 	locationPanel->update ( NULL, wxEmptyString );
4527 	insertChildPanel->update ( NULL, wxEmptyString );
4528 	insertSiblingPanel->update ( NULL, wxEmptyString );
4529 
4530 	    // workaround -- wxAuiNotebook: send virtual close event? DeletePage doesn't generate one
4531 	    wxAuiNotebookEvent e;
4532 	    e.SetSelection ( selection );
4533 	    OnPageClosing ( e );
4534 	    if ( deletePageVetoed )
4535 	        return false;
4536 
4537 	    mainBook->DeletePage ( selection ); // check this is still correct
4538 	    return true;
4539 
4540 	// apparently fixed betw. 2.8.0 and 2.8.6, so from v. 1.1.0.3, BUT this is once more:
4541 	// 1.1.0.5: reverted to above workaround - no confirmation dialog?
4542 	// watch memory usage for DeletePage call
4543 	//mainBook->DeletePage ( selection );
4544 	//return ( !deletePageVetoed );
4545 }
4546 
saveFile(XmlDoc * doc,wxString & fileName,bool checkLastModified)4547 bool MyFrame::saveFile ( XmlDoc *doc, wxString& fileName, bool checkLastModified )
4548 {
4549 	if ( !doc )
4550 		return false;
4551 
4552 	statusProgress ( wxEmptyString );
4553 
4554 	if ( checkLastModified )
4555 	{
4556 		wxFileName fn ( fileName );
4557 		if ( fn.IsOk() )
4558 		{
4559 			wxDateTime myLastModified = fn.GetModificationTime();
4560 			if ( !myLastModified.IsEqualTo ( doc->getLastModified() ) )
4561 			{
4562 				int choice = wxMessageBox (
4563 				                 _ ( "File has been modified by another application.\nDo you want to proceed?" ),
4564 				                 _ ( "Confirmation" ),
4565 				                 wxICON_QUESTION | wxYES_NO | wxCANCEL );
4566 				if ( choice != wxYES )
4567 					return false;
4568 			}
4569 		}
4570 	}
4571 
4572 	int bytes = 0;
4573 	std::string utf8Buffer, encoding, fileNameLocal;
4574 	wxString wideEncoding;
4575 	bool isXml = true;
4576 	try
4577 	{
4578 		getRawText ( doc, utf8Buffer );
4579 		XmlEncodingSpy es ( "UTF-8" );
4580 		es.parse ( utf8Buffer );
4581 		encoding = es.getEncoding();
4582 		wideEncoding = wxString ( encoding.c_str(), wxConvUTF8 );
4583 
4584 		fileNameLocal = fileName.mb_str ( wxConvLocal );
4585 
4586 		closeMessagePane();
4587 		bool success;
4588 		success = true;
4589 		if ( getFileType ( fileName ) != FILE_TYPE_XML )
4590 		{
4591 			isXml = false;
4592 		}
4593 
4594 		// raw file conditions
4595 		if ( doc->getType() == FILE_TYPE_BINARY )
4596 		{
4597 			success = saveRawUtf8 ( fileNameLocal, utf8Buffer, true, isXml );
4598 			if ( success )
4599 				bytes = utf8Buffer.size();
4600 			else
4601 			{
4602 				wxString message;
4603 				message.Printf ( _ ( "Cannot save %s" ), fileName.c_str() );
4604 				messagePane ( message, CONST_STOP );
4605 				return false;
4606 			}
4607 
4608 		}
4609 		else if ( !isXml && encoding.empty() )
4610 		{
4611 			success = saveRawUtf8 ( fileNameLocal, utf8Buffer, true, isXml );
4612 			if ( success )
4613 				bytes = utf8Buffer.size();
4614 			else
4615 			{
4616 				wxString message;
4617 				message.Printf ( _ ( "Cannot save %s" ), fileName.c_str() );
4618 				messagePane ( message, CONST_STOP );
4619 				return false;
4620 			}
4621 		}
4622 		else if ( encoding == "UTF-8" )
4623 		{
4624 			WrapExpat we ( "UTF-8" );
4625 
4626 			if ( !we.parse ( utf8Buffer ) )
4627 			{
4628 				//if ( we->isEncodingError() )
4629 				//	;
4630 				messagePane ( we.getLastError(), CONST_WARNING );
4631 			}
4632 			success = saveRawUtf8 ( fileNameLocal, utf8Buffer, true, isXml );
4633 			if ( success )
4634 				bytes = utf8Buffer.size();
4635 			else
4636 			{
4637 				wxString message;
4638 				message.Printf ( _ ( "Cannot save %s" ), fileName.c_str() );
4639 				messagePane ( message, CONST_STOP );
4640 				return false;
4641 			}
4642 		}
4643 		else
4644 		{
4645 			// IF Unicode, use iconv to convert buffer
4646 			if ( encoding == "UTF-16" || encoding == "UTF-16LE" ||
4647 			        encoding == "UTF-16BE" || encoding == "UTF-32" || encoding == "UTF-32LE" ||
4648 			        encoding == "UTF-32BE" )
4649 			{
4650 				iconv_t cd = iconv_open ( encoding.c_str(), "UTF-8" );
4651 				if ( cd == ( iconv_t )-1 )
4652 				{
4653 					success = saveRawUtf8 ( fileNameLocal, utf8Buffer, false, isXml );
4654 					if ( success )
4655 					{
4656 						bytes = utf8Buffer.size();
4657 						wxString message;
4658 						message.Printf (
4659 						    _ ( "%s saved in default encoding UTF-8: unknown encoding %s" ),
4660 						    fileName.c_str(),
4661 						    wideEncoding.c_str() );
4662 						messagePane ( message, CONST_WARNING );
4663 					}
4664 					else
4665 					{
4666 						wxString message;
4667 						message.Printf ( _ ( "Cannot save %s" ), fileName.c_str() );
4668 						messagePane ( message, CONST_STOP );
4669 						return false;
4670 					}
4671 				}
4672 				else
4673 				{
4674 					size_t utf8BufferLen = utf8Buffer.size();
4675 
4676 					size_t iconvBufferLen, iconvBufferLeft, utf8BufferLeft;
4677 					int iconvLenMultiplier = 4; // worst case scenario
4678 					if ( encoding == "UTF-16" ||
4679 					        encoding == "UTF-16BE" ||
4680 					        encoding == "UTF-16LE" )
4681 					{
4682 						iconvLenMultiplier = 2;
4683 					}
4684 					else if ( encoding == "UTF-32" ||
4685 					          encoding == "UTF-32BE" ||
4686 					          encoding == "UTF-32LE" )
4687 					{
4688 						iconvLenMultiplier = 4;
4689 					}
4690 
4691 					iconvBufferLen = iconvBufferLeft =
4692 					                     utf8BufferLen * iconvLenMultiplier + 4; // worst case scenario
4693 
4694 					char *finalBuffer;
4695 					char *iconvBuffer;
4696 
4697 					utf8BufferLeft = utf8BufferLen;
4698 					iconvBuffer = new char[iconvBufferLen];
4699 					finalBuffer = iconvBuffer; // iconvBuffer will be incremented by iconv
4700 					size_t nconv;
4701 
4702 					char *utf8BufferPtr = ( char * ) utf8Buffer.c_str();
4703 
4704 					nconv = reinterpret_cast < universal_iconv & > ( iconv ) (
4705 					            cd,
4706 					            &utf8BufferPtr,
4707 					            &utf8BufferLeft,
4708 					            &iconvBuffer,
4709 					            &iconvBufferLeft );
4710 
4711 					iconv_close ( cd );
4712 
4713 					if ( nconv == ( size_t )-1 ) // conversion failed
4714 					{
4715 						delete[] finalBuffer;
4716 						success = saveRawUtf8 ( fileNameLocal, utf8Buffer, false, isXml );
4717 						if ( success )
4718 						{
4719 							bytes = utf8Buffer.size();
4720 							wxString message;
4721 							message.Printf (
4722 							    _ ( "%s saved in default encoding UTF-8: conversion to %s failed" ),
4723 							    fileName.c_str(),
4724 							    wideEncoding.c_str() );
4725 							messagePane ( message, CONST_WARNING );
4726 						}
4727 						else
4728 						{
4729 							wxString message;
4730 							message.Printf ( _ ( "Cannot save %s" ), fileName.c_str() );
4731 							messagePane ( message, CONST_STOP );
4732 							return false;
4733 						}
4734 					}
4735 					else
4736 					{
4737 						size_t finalBufferLen = iconvBufferLen - iconvBufferLeft;
4738 
4739 						std::ofstream ofs ( fileNameLocal.c_str(), std::ios::out | std::ios::binary );
4740 						if ( !ofs )
4741 						{
4742 							delete[] finalBuffer;
4743 							wxString message;
4744 							message.Printf ( _ ( "Cannot save %s" ), fileName.c_str() );
4745 							messagePane ( message, CONST_STOP );
4746 							return false;
4747 						}
4748 
4749 						// iconv adds boms for UTF-16 & UTF-32 automatically
4750 
4751 						ofs.write ( finalBuffer, finalBufferLen );
4752 						ofs.close();
4753 						delete[] finalBuffer;
4754 						bytes = finalBufferLen;
4755 					}
4756 				}
4757 			}
4758 			else // all other encodings handled by Libxml
4759 			{
4760 				boost::scoped_ptr<WrapLibxml> wl ( new WrapLibxml ( libxmlNetAccess ) );
4761 				int result = wl->saveEncoding ( utf8Buffer,
4762 						doc->getFullFileName(), fileName, NULL, wideEncoding );
4763 				if ( result == -1 )
4764 				{
4765 					success = saveRawUtf8 ( fileNameLocal, utf8Buffer, false, isXml );
4766 					if ( success )
4767 					{
4768 						wxString wideError = wl->getLastError();
4769 						bytes = utf8Buffer.size();
4770 						wxString msg;
4771 						if ( wideError.empty() )
4772 							wideError = _ ( "unknown error" );
4773 
4774 						msg.Printf ( _ ( "Cannot save document in %s: %s (saved in default encoding UTF-8)" ),
4775 						             wideEncoding.c_str(), wideError.c_str() );
4776 						messagePane ( msg, CONST_INFO );
4777 					}
4778 					else
4779 					{
4780 						wxString message;
4781 						message.Printf ( _ ( "Cannot save %s" ), fileName.c_str() );
4782 						messagePane ( message, CONST_STOP );
4783 						return false;
4784 					}
4785 				}
4786 				else
4787 					bytes = result;
4788 			}
4789 		}
4790 	} // try
4791 	catch ( std::bad_alloc& )
4792 	{
4793 		if ( encoding != "UTF-8" )
4794 		{
4795 			int answer = wxMessageBox (
4796 			                 _ ( "Out of memory: attempt to save in default encoding UTF-8?" ),
4797 			                 _ ( "Out of memory" ),
4798 			                 wxYES_NO | wxCANCEL | wxICON_QUESTION,
4799 			                 this );
4800 			if ( answer == wxCANCEL || answer == wxNO )
4801 				return false;
4802 
4803 			bool success = saveRawUtf8 ( fileNameLocal, utf8Buffer, true, isXml );
4804 			if ( success )
4805 			{
4806 				bytes = utf8Buffer.size();
4807 				wxString message;
4808 				message.Printf (
4809 				    _ ( "%s saved in default encoding UTF-8" ),
4810 				    fileName.c_str() );
4811 				messagePane ( message, CONST_INFO );
4812 			}
4813 			else
4814 			{
4815 				wxString message;
4816 				message.Printf ( _ ( "Cannot save %s" ), fileName.c_str() );
4817 				messagePane ( message, CONST_STOP );
4818 				return false;
4819 			}
4820 		}
4821 	}
4822 
4823 	doc->SetFocus();
4824 	doc->SetSavePoint();
4825 
4826 	if ( properties.validateAsYouType && isXml )
4827 	{
4828 		doc->clearErrorIndicators();
4829 		//doc->backgroundValidate ( utf8Buffer.c_str(), doc->getFullFileName().mb_str(wxConvUTF8), utf8Buffer.size() );
4830 		doc->backgroundValidate();
4831 	}
4832 
4833 	if ( !unlimitedUndo )
4834 		doc->EmptyUndoBuffer();
4835 	wxFileName fn ( fileName );
4836 	if ( fn.IsOk() )
4837 		doc->setLastModified ( fn.GetModificationTime() );
4838 	openFileSet.insert ( fileName );
4839 	displaySavedStatus ( bytes );
4840 	return true;
4841 }
4842 
saveRawUtf8(const std::string & fileNameLocal,std::string & bufferUtf8,bool ignoreEncoding,bool isXml)4843 bool MyFrame::saveRawUtf8 (
4844     const std::string& fileNameLocal,
4845     std::string& bufferUtf8,
4846     bool ignoreEncoding,
4847     bool isXml )
4848 {
4849 	ofstream ofs ( fileNameLocal.c_str(), std::ios::out | std::ios::binary );
4850 	if ( !ofs )
4851 		return false;
4852 
4853 	if ( !ignoreEncoding && isXml )
4854 		XmlEncodingHandler::setUtf8 ( bufferUtf8, true );
4855 
4856 	if ( saveBom && isXml )
4857 	{
4858 		static const char bom[4] = "\xEF\xBB\xBF";
4859 		ofs.write ( bom, 3 );
4860 	}
4861 	ofs.write ( bufferUtf8.c_str(), bufferUtf8.size() );
4862 	ofs.close();
4863 	return true;
4864 }
4865 
displaySavedStatus(int bytes)4866 void MyFrame::displaySavedStatus ( int bytes )
4867 {
4868 	wxString unit;
4869 	float result = 0;
4870 	if ( bytes > 1000000 )
4871 	{
4872 		result = bytes / 1000000;
4873 		unit = _ ( "MB" );
4874 	}
4875 	else if ( bytes > 1000 )
4876 	{
4877 		result = bytes / 1000;
4878 		unit = _ ( "kB" );
4879 	}
4880 	else if ( bytes >= 0 )
4881 	{
4882 		result = bytes;
4883 		unit = wxPLURAL ( "byte", "bytes", bytes );
4884 	}
4885 	else
4886 		return;
4887 
4888 	wxString msg;
4889 
4890 	msg.Printf (
4891 	    _ ( "%g %s saved" ),
4892 	    result,
4893 	    unit.c_str() );
4894 	statusProgress ( msg );
4895 }
4896 
getHandleCommandLineFlag()4897 bool MyFrame::getHandleCommandLineFlag()
4898 {
4899 	return handleCommandLineFlag;
4900 }
4901 
getMenuBar()4902 wxMenuBar *MyFrame::getMenuBar()
4903 {
4904 	fileMenu = new wxMenu; // use class-wide data member
4905 	updateFileMenu ( false );
4906 
4907 	// edit menu
4908 	wxMenu *editMenu = new wxMenu;
4909 
4910 	wxMenuItem *undoItem =
4911 	    new wxMenuItem ( editMenu, wxID_UNDO, _ ( "&Undo\tCtrl+Z" ), _ ( "Undo" ) );
4912 	undoItem->SetBitmap ( undo16Bitmap );
4913 
4914 	wxMenuItem *redoItem =
4915 	    new wxMenuItem ( editMenu, wxID_REDO, _ ( "&Redo\tCtrl+Y" ), _ ( "Redo" ) );
4916 	redoItem->SetBitmap ( redo16Bitmap );
4917 
4918 	wxMenuItem *cutItem =
4919 	    new wxMenuItem ( editMenu, wxID_CUT, _ ( "&Cut\tCtrl+X" ), _ ( "Cut" ) );
4920 	cutItem->SetBitmap ( cutBitmap );
4921 
4922 	wxMenuItem *copyItem =
4923 	    new wxMenuItem ( editMenu, wxID_COPY, _ ( "C&opy\tCtrl+C" ), _ ( "Copy" ) );
4924 	copyItem->SetBitmap ( copyBitmap );
4925 
4926 	wxMenuItem *pasteItem =
4927 	    new wxMenuItem ( editMenu, wxID_PASTE, _ ( "&Paste\tCtrl+V" ), _ ( "Paste" ) );
4928 	pasteItem->SetBitmap ( pasteBitmap );
4929 
4930 	wxMenuItem *pasteNewDocumentItem =
4931 	    new wxMenuItem (
4932 	    editMenu,
4933 	    ID_PASTE_NEW_DOCUMENT,
4934 	    _ ( "P&aste As New Document" ),
4935 	    _ ( "Paste As New Document" ) );
4936 	pasteNewDocumentItem->SetBitmap ( wxNullBitmap );
4937 
4938 	wxMenuItem *findItem =
4939 	    new wxMenuItem ( editMenu, ID_FIND, _ ( "&Find...\tCtrl+F" ), _ ( "Find..." ) );
4940 	findItem->SetBitmap ( searchBitmap );
4941 
4942 	wxMenuItem *findAgainItem =
4943 	    new wxMenuItem ( editMenu, ID_FIND_AGAIN, _ ( "F&ind Again\tF3" ), _ ( "Find Again" ) );
4944 	findAgainItem->SetBitmap ( wxNullBitmap );
4945 
4946 	wxMenuItem *replaceItem =
4947 	    new wxMenuItem ( editMenu, ID_REPLACE, _ ( "&Replace...\tCtrl+R" ), _ ( "Replace..." ) );
4948 	replaceItem->SetBitmap ( wxNullBitmap );
4949 
4950 	wxMenuItem *globalReplaceItem =
4951 	    new wxMenuItem (
4952 	    editMenu,
4953 	    ID_GLOBAL_REPLACE,
4954 	    _ ( "&Global Replace...\tCtrl+Shift+R" ),
4955 	    _ ( "Global Replace..." ) );
4956 	globalReplaceItem->SetBitmap ( wxNullBitmap );
4957 
4958 	wxMenuItem *gotoItem =
4959 	    new wxMenuItem ( editMenu, ID_GOTO, _ ( "G&o To...\tCtrl+G" ), _ ( "Go To..." ) );
4960 	gotoItem->SetBitmap ( wxNullBitmap );
4961 
4962 	wxMenuItem *commentItem =
4963 	    new wxMenuItem ( editMenu, ID_TOGGLE_COMMENT, _ ( "&Toggle Comment\tCtrl+/" ), _ ( "Toggle Comment" ) );
4964 	commentItem->SetBitmap ( wxNullBitmap );
4965 
4966 	editMenu->Append ( undoItem );
4967 	editMenu->Append ( redoItem );
4968 	editMenu->AppendSeparator();
4969 	editMenu->Append ( cutItem );
4970 	editMenu->Append ( copyItem );
4971 	editMenu->Append ( pasteItem );
4972 	editMenu->Append ( pasteNewDocumentItem );
4973 	editMenu->AppendSeparator();
4974 	editMenu->Append ( findItem );
4975 	editMenu->Append ( findAgainItem );
4976 	editMenu->Append ( replaceItem );
4977 	editMenu->Append ( globalReplaceItem );
4978 	editMenu->Append ( gotoItem );
4979 	editMenu->AppendSeparator();
4980 	editMenu->Append ( commentItem );
4981 
4982 #ifndef __WXMSW__
4983 	wxMenuItem *preferencesItem =
4984 	    new wxMenuItem ( editMenu, ID_OPTIONS, _ ( "Pr&eferences..." ), _ ( "Preferences..." ) );
4985 	editMenu->AppendSeparator();
4986 	editMenu->Append ( preferencesItem );
4987 #endif
4988 
4989 	// font size menu
4990 	wxMenu *fontSizeMenu = new wxMenu;
4991 	fontSizeMenu->Append (
4992 	    ID_FONT_LARGER, _ ( "Increase\tCtrl+U" ), _ ( "Increase" ) );
4993 	fontSizeMenu->Append (
4994 	    ID_FONT_SMALLER, _ ( "Decrease\tCtrl+D" ), _ ( "Decrease" ) );
4995 	fontSizeMenu->AppendSeparator();
4996 	fontSizeMenu->Append ( ID_FONT_NORMAL, _ ( "Normal\tCtrl+0" ), _ ( "Normal" ) );
4997 
4998 	// color scheme menu
4999 	colorSchemeMenu = new wxMenu;
5000 	colorSchemeMenu->AppendRadioItem (
5001 	    ID_COLOR_SCHEME_DEFAULT, _ ( "&Default" ), _ ( "Default" ) );
5002 	colorSchemeMenu->AppendRadioItem (
5003 	    ID_COLOR_SCHEME_REDUCED_GLARE,
5004 	    _ ( "&Blue background, white text" ),
5005 	    _ ( "Blue background, white text" ) );
5006 	colorSchemeMenu->AppendRadioItem (
5007 	    ID_COLOR_SCHEME_DEFAULT_BACKGROUND,
5008 	    _ ( "&Light" ),
5009 	    _ ( "Light" ) );
5010 	colorSchemeMenu->AppendRadioItem (
5011 	    ID_COLOR_SCHEME_NONE,
5012 	    _ ( "&None" ),
5013 	    _ ( "None" ) );
5014 
5015 	switch ( properties.colorScheme )
5016 	{
5017 		case COLOR_SCHEME_DEFAULT:
5018 			colorSchemeMenu->Check ( ID_COLOR_SCHEME_DEFAULT, true );
5019 			break;
5020 		case COLOR_SCHEME_DEFAULT_BACKGROUND:
5021 			colorSchemeMenu->Check ( ID_COLOR_SCHEME_DEFAULT_BACKGROUND, true );
5022 			break;
5023 		case COLOR_SCHEME_REDUCED_GLARE:
5024 			colorSchemeMenu->Check ( ID_COLOR_SCHEME_REDUCED_GLARE, true );
5025 			break;
5026 		case COLOR_SCHEME_NONE:
5027 			colorSchemeMenu->Check ( ID_COLOR_SCHEME_NONE, true );
5028 			break;
5029 		default:
5030 			break;
5031 	}
5032 
5033 	 /* WAIT FOR AUI LIBRARY TO SUPPORT THIS - currently always splits left
5034 	wxMenu *splitTabMenu = new wxMenu;
5035 	splitTabMenu->Append ( ID_SPLIT_TAB_TOP, _ ( "&Top" ), _ ( "Top" ));
5036 	splitTabMenu->Append ( ID_SPLIT_TAB_RIGHT, _ ( "&Right" ), _ ( "Right" ));
5037 	splitTabMenu->Append ( ID_SPLIT_TAB_BOTTOM, _ ( "&Bottom" ), _ ( "Bottom" ));
5038 	splitTabMenu->Append ( ID_SPLIT_TAB_LEFT, _ ( "&Left" ), _ ( "Left" ));
5039 	 */
5040 
5041 	viewMenu = new wxMenu; // use class-wide data member
5042 	viewMenu->Append ( ID_PREVIOUS_DOCUMENT, _ ( "&Previous Document\tCtrl+PgUp" ), _ ( "Previous Document" ) );
5043 	viewMenu->Append ( ID_NEXT_DOCUMENT, _ ( "&Next Document\tCtrl+PgDn" ), _ ( "Next Document" ) );
5044 
5045 	//viewMenu->Append ( wxID_ANY, _ ( "&Split Tab" ), splitTabMenu );
5046 
5047 	viewMenu->Append ( ID_BROWSER, _ ( "&Browser\tCtrl+B" ), _ ( "Browser" ) );
5048 	viewMenu->AppendSeparator();
5049 	viewMenu->AppendRadioItem (
5050 	    ID_SHOW_TAGS,
5051 	    _ ( "&Show Tags and Attributes\tCtrl+T" ), _ ( "Show Tags and Attributes" ) );
5052 	viewMenu->AppendRadioItem (
5053 	    ID_HIDE_ATTRIBUTES,
5054 	    _ ( "&Hide Attributes Only\tCtrl+Shift+A" ), _ ( "Hide Attributes Only" ) );
5055 	viewMenu->AppendRadioItem (
5056 	    ID_HIDE_TAGS,
5057 	    _ ( "H&ide Tags and Attributes\tCtrl+Shift+T" ), _ ( "Hide Tags and Attributes" ) );
5058 
5059 	switch ( visibilityState )
5060 	{
5061 		case SHOW_TAGS:
5062 			viewMenu->Check ( ID_SHOW_TAGS, true );
5063 			break;
5064 		case HIDE_TAGS:
5065 			viewMenu->Check ( ID_HIDE_TAGS, true );
5066 			break;
5067 		case HIDE_ATTRIBUTES:
5068 			viewMenu->Check ( ID_HIDE_ATTRIBUTES, true );
5069 			break;
5070 		default:
5071 			viewMenu->Check ( ID_SHOW_TAGS, true );
5072 			break;
5073 	}
5074 	viewMenu->AppendSeparator();
5075 	viewMenu->Append (
5076 	    ID_TOGGLE_FOLD, _ ( "&Toggle Fold\tCtrl+Alt+T" ), _ ( "Toggle Fold" ) );
5077 	viewMenu->Append (
5078 	    ID_FOLD_ALL, _ ( "&Fold Tags\tCtrl+Shift+F" ), _ ( "Fold Tags" ) );
5079 	viewMenu->Append (
5080 	    ID_UNFOLD_ALL, _ ( "&Unfold Tags\tCtrl+Shift+U" ), _T ( "Unfold Tags" ) );
5081 	viewMenu->AppendSeparator();
5082 	viewMenu->AppendCheckItem (
5083 	    ID_WRAP_WORDS, _ ( "&Wrap Words" ), _T ( "Wrap Words" ) );
5084 	viewMenu->Check ( ID_WRAP_WORDS, properties.wrap );
5085 	viewMenu->Append ( wxID_ANY, _ ( "&Color Scheme" ), colorSchemeMenu );
5086 	viewMenu->Append ( wxID_ANY, _ ( "&Text Size" ), fontSizeMenu );
5087 	viewMenu->AppendSeparator();
5088 
5089 	viewMenu->AppendCheckItem (
5090 	    ID_LOCATION_PANE_VISIBLE,
5091 	    _ ( "S&how Current Element Pane" ),
5092 	    _ ( "Show Current Element Pane" ) );
5093 	viewMenu->Check ( ID_LOCATION_PANE_VISIBLE, false );
5094 #ifndef __WXOSX__
5095 	viewMenu->AppendCheckItem (
5096 	    ID_TOOLBAR_VISIBLE, _ ( "Sh&ow Toolbar" ), _ ( "Show Toolbar" ) );
5097 	viewMenu->Check ( ID_TOOLBAR_VISIBLE, toolbarVisible );
5098 #endif
5099 	viewMenu->Append ( ID_CLOSE_MESSAGE_PANE,
5100 	    _ ( "C&lose Message Pane\tAlt+C" ), _ ( "Close Message Pane" ) );
5101 	viewMenu->Append ( ID_CLOSE_FIND_REPLACE_PANE,
5102 	    _ ( "Close Find/&Replace Pane" ), _ ( "Close Find/Replace Pane" ) );
5103 	viewMenu->Append ( ID_CLOSE_COMMAND_PANE,
5104 	    _ ( "Close Co&mmand Pane" ), _ ( "Close Command Pane" ) );
5105 
5106 	// insert menu
5107 	wxMenu *insertMenu = new wxMenu;
5108 	insertMenu->Append ( ID_INSERT_CHILD, _ ( "&Element...\tCtrl+I" ), _ ( "Element..." ) );
5109 	insertMenu->Append ( ID_INSERT_SIBLING, _ ( "&Sibling...\tCtrl+Shift+I" ), _ ( "Sibling..." ) );
5110 	insertMenu->Append ( ID_INSERT_ENTITY, _ ( "&Entity...\tCtrl+E" ), _ ( "Entity..." ) );
5111 	insertMenu->AppendSeparator();
5112 	insertMenu->Append ( ID_INSERT_TWIN, _ ( "&Twin\tCtrl+Enter" ), _ ( "Twin" ) );
5113 	insertMenu->AppendSeparator();
5114 	insertMenu->Append ( ID_INSERT_SYMBOL, _ ( "S&ymbol..." ), _ ( "Symbol..." ) );
5115 
5116 	// validation menu
5117 	wxMenu *validationMenu = new wxMenu;
5118 	/*
5119 	    validationMenu->Append ( ID_VALIDATE_DTD, _ ( "&DTD\tF4" ), _ ( "DTD" ) );
5120 	*/
5121 	validationMenu->Append (
5122 	    ID_VALIDATE_W3C_SCHEMA, _ ( "&DTD/XML Schema\tF5" ), _ ( "DTD/XML Schema" ) );
5123 	validationMenu->AppendSeparator();
5124 	validationMenu->Append (
5125 	    ID_VALIDATE_RELAX_NG, _ ( "&RELAX NG...\tF6" ), _ ( "RELAX NG..." ) );
5126 
5127 	wxMenu *associateMenu = new wxMenu;
5128 	associateMenu->Append ( ID_ASSOCIATE_DTD_PUBLIC, _ ( "&Public DTD..." ), _ ( "Public DTD..." ) );
5129 	associateMenu->Append ( ID_ASSOCIATE_DTD_SYSTEM, _ ( "&System DTD..." ), _ ( "System DTD..." ) );
5130 	associateMenu->Append ( ID_ASSOCIATE_W3C_SCHEMA, _ ( "&XML Schema..." ), _ ( "XML Schema..." ) );
5131 	associateMenu->Append ( ID_ASSOCIATE_XSL, _ ( "XS&LT stylesheet..." ), _ ( "XSLT stylesheet..." ) );
5132 
5133 	if ( wxDirExists ( rngDir ) )
5134 	{
5135 		wxString rngMask, rngFile, rngUrl, displayName, shortcutString;
5136 		rngMask = rngDir + wxFileName::GetPathSeparator() + _T ( "*.rng" );
5137 		rngFile = wxFindFirstFile ( rngMask, wxFILE );
5138 
5139 		int id = ID_VALIDATE_PRESET1;
5140 
5141 		while ( id <= ID_VALIDATE_PRESET9 && !rngFile.empty() )
5142 		{
5143 			rngUrl = WrapLibxml::FileNameToURL ( rngFile );
5144 			validationPresetMap.insert ( make_pair ( id, rngUrl ) );
5145 			wxFileName::SplitPath ( rngFile, NULL, NULL, &displayName, NULL );
5146 			displayName.Replace ( _T ( ".rng" ), _T ( "" ) );
5147 			shortcutString.Printf ( _ ( "\tCtrl+%i" ), ( id - ID_VALIDATE_PRESET1 ) + 1 );
5148 
5149 			validationMenu->Append ( id, displayName + shortcutString, displayName );
5150 
5151 			id++;
5152 			rngFile = wxFindNextFile();
5153 		}
5154 	}
5155 
5156 	// xsl menu
5157 	/*
5158 	wxMenu *xslMenu = new wxMenu;
5159 	xslMenu->Append ( ID_XSLT, _ ( "&XSL Transform...\tF8" ),
5160 	                  _ ( "XSL Transform..." ) );
5161 	xslMenu->AppendSeparator();
5162 	xslMenu->Append (
5163 	    ID_XSLT_DOCBOOK_HTML,
5164 	    _ ( "&DocBook to HTML\tAlt+1" ), _ ( "DocBook to HTML" ) );
5165 	xslMenu->Append (
5166 	    ID_XSLT_DOCBOOK_XHTML,
5167 	    _ ( "&DocBook to XHTML\tAlt+2" ), _ ( "DocBook to XHTML" ) );
5168 	xslMenu->Append (
5169 	    ID_XSLT_DOCBOOK_FO,
5170 	    _ ( "D&ocBook to XSL-FO\tAlt+3" ), _ ( "DocBook to XSL-FO" ) );
5171 	xslMenu->Append (
5172 	    ID_XSLT_TEI_HTML,
5173 	    _ ( "&TEI to HTML\tAlt+4" ), _ ( "TEI to HTML" ) );
5174 	xslMenu->Append (
5175 	    ID_XSLT_TEI_LATEX,
5176 	    _ ( "T&EI to LaTeX\tAlt+5" ), _ ( "TEI to LaTeX" ) );
5177 	xslMenu->Append (
5178 	    ID_XSLT_TEI_XHTML,
5179 	    _ ( "TE&I to XHTML\tAlt+6" ), _ ( "TEI to XHTML" ) );
5180 	xslMenu->Append (
5181 	    ID_XSLT_TEI_FO,
5182 	    _ ( "TEI to &XSL-FO\tAlt+7" ), _ ( "TEI to XSL-FO" ) );
5183 	*/
5184 
5185 	// xml menu
5186 	xmlMenu = new wxMenu; // use class-wide data member
5187 	xmlMenu->Append (
5188 	    ID_CHECK_WELLFORMED,
5189 	    _ ( "&Check Well-formedness\tF2" ), _ ( "Check Well-formedness" ) );
5190 	xmlMenu->Append (
5191 	    wxID_ANY,
5192 	    _ ( "&Validate" ),
5193 	    validationMenu );
5194 	xmlMenu->Append ( ID_CREATE_SCHEMA, _ ( "Create &Schema...\tF10" ),
5195 	    _ ( "Create schema..." ) );
5196 	xmlMenu->Append ( ID_DTD_TO_SCHEMA, _ ( "DTD -> Schema..." ),
5197 	    _ ( "DTD -> Schema..." ) );
5198 	xmlMenu->AppendSeparator();
5199 	xmlMenu->Append (
5200 	    wxID_ANY,
5201 	    _ ( "&Associate" ),
5202 	    associateMenu );
5203 	xmlMenu->AppendSeparator();
5204 	xmlMenu->Append ( ID_XSLT, _ ( "&XSL Transform...\tF8" ),
5205 	                  _ ( "XSL Transform..." ) );
5206 	xmlMenu->Append (
5207 	    ID_XPATH,
5208 	    _ ( "&Evaluate XPath...\tF9" ),
5209 	    _ ( "Evaluate XPath..." ) );
5210 	xmlMenu->Append (
5211 	    ID_COPY_XPATH,
5212 	    _ ( "Copy &The Current XPath" ),
5213 	    _ ( "Copy The Current XPath" ) );
5214 
5215 	xmlMenu->AppendSeparator();
5216 	xmlMenu->Append (
5217 	    ID_PRETTYPRINT,
5218 	    _ ( "&Pretty-print\tF11" ), _ ( "Pretty-print" ) );
5219 	xmlMenu->AppendSeparator();
5220 	xmlMenu->AppendCheckItem (
5221 	    ID_PROTECT_TAGS,
5222 	    _ ( "&Lock Tags\tCtrl+L" ),
5223 	    _ ( "Lock Tags" ) );
5224 	xmlMenu->Check ( ID_PROTECT_TAGS, protectTags );
5225 	xmlMenu->AppendSeparator();
5226 	xmlMenu->Append (
5227 	    ID_ENCODING,
5228 	    _ ( "E&ncoding..." ), _ ( "Encoding..." ) );
5229 
5230 	// tools menu
5231 	wxMenu *toolsMenu = new wxMenu;
5232 
5233 	wxMenuItem *spellingItem =
5234 	    new wxMenuItem (
5235 	    toolsMenu,
5236 	    ID_SPELL,
5237 	    _ ( "&Spelling...\tF7" ),
5238 	    _ ( "Spelling..." ) );
5239 	spellingItem->SetBitmap ( spelling16Bitmap );
5240 
5241 	wxMenuItem *styleItem =
5242 	    new wxMenuItem (
5243 	    toolsMenu,
5244 	    ID_STYLE,
5245 	    _ ( "&Style...\tShift+F7" ),
5246 	    _ ( "Style..." ) );
5247 	styleItem->SetBitmap ( wxNullBitmap );
5248 
5249 	wxMenuItem *wordCountItem =
5250 	    new wxMenuItem (
5251 	    toolsMenu,
5252 	    ID_WORD_COUNT,
5253 	    _ ( "&Word Count" ),
5254 	    _ ( "Word Count" ) );
5255 	wordCountItem->SetBitmap ( wxNullBitmap );
5256 
5257 
5258 	wxMenuItem *commandItem =
5259 	    new wxMenuItem (
5260 	    toolsMenu,
5261 	    ID_COMMAND,
5262 	    _ ( "&Command\tCtrl+Alt+C" ),
5263 	    _ ( "Command" ) );
5264 	commandItem->SetBitmap ( wxNullBitmap );
5265 
5266 	toolsMenu->Append ( spellingItem );
5267 	toolsMenu->Append ( styleItem );
5268 	toolsMenu->Append ( wordCountItem );
5269 	toolsMenu->AppendSeparator();
5270 	toolsMenu->Append ( commandItem );
5271 
5272 #ifdef __WXMSW__
5273 	toolsMenu->AppendSeparator();
5274 	wxMenuItem *optionsItem =
5275 	    new wxMenuItem (
5276 	    toolsMenu,
5277 	    ID_OPTIONS,
5278 	    _ ( "&Options..." ),
5279 	    _ ( "Options..." ) );
5280 	optionsItem->SetBitmap ( wxNullBitmap );
5281 	toolsMenu->Append ( optionsItem );
5282 #endif
5283 
5284 	// help menu
5285 	wxMenu *helpMenu = new wxMenu;
5286 
5287 	wxMenuItem *helpItem =
5288 	    new wxMenuItem ( helpMenu, wxID_HELP,
5289 	                     _ ( "&XML Copy Editor Help\tF1" ), _ ( "Help" ) );
5290 	helpItem->SetBitmap ( helpBitmap );
5291 
5292 
5293 	wxMenuItem *homeItem =
5294 	    new wxMenuItem ( helpMenu, ID_HOME,
5295 	                     _ ( "&Home Page" ), _ ( "Home Page" ) );
5296 	homeItem->SetBitmap ( wxNullBitmap );
5297 	wxMenuItem *feedbackItem =
5298 	    new wxMenuItem ( helpMenu, ID_FEEDBACK, _ ( "&Forum" ), _ ( "Forum" ) );
5299 	feedbackItem->SetBitmap ( wxNullBitmap );
5300 	wxMenuItem *aboutItem =
5301 	    new wxMenuItem ( helpMenu, wxID_ABOUT,
5302 	                     _ ( "&About XML Copy Editor" ), _ ( "About" ) );
5303 	aboutItem->SetBitmap ( wxNullBitmap );
5304 	wxMenuItem *downloadSourceItem =
5305 	    new wxMenuItem ( helpMenu, ID_DOWNLOAD_SOURCE,
5306 	                     _ ( "&Browse Source" ), _ ( "Browse Source" ) );
5307 	downloadSourceItem->SetBitmap ( wxNullBitmap );
5308 	helpMenu->Append ( helpItem );
5309 
5310 	helpMenu->AppendSeparator();
5311 	helpMenu->Append ( homeItem );
5312 	helpMenu->Append ( feedbackItem );
5313 	helpMenu->Append ( downloadSourceItem );
5314 	helpMenu->AppendSeparator();
5315 	helpMenu->Append ( aboutItem );
5316 
5317 	wxMenuBar *menuBar = new wxMenuBar ( wxMB_DOCKABLE );
5318 	menuBar->Append ( fileMenu, _ ( "&File" ) );
5319 	menuBar->Append ( editMenu, _ ( "&Edit" ) );
5320 	menuBar->Append ( viewMenu, _ ( "&View" ) );
5321 	menuBar->Append ( insertMenu, _ ( "&Insert" ) );
5322 	menuBar->Append ( xmlMenu, _ ( "&XML" ) );
5323 	menuBar->Append ( toolsMenu, _ ( "&Tools" ) );
5324 	menuBar->Append ( helpMenu, _ ( "&Help" ) );
5325 	return menuBar;
5326 }
5327 
updateFileMenu(bool deleteExisting)5328 void MyFrame::updateFileMenu ( bool deleteExisting )
5329 {
5330 	if ( deleteExisting )
5331 	{
5332 		wxMenuItemList list = fileMenu->GetMenuItems();
5333 		size_t count = list.size();
5334 		for ( size_t i = 0; i < count; ++i )
5335 			fileMenu->Delete ( list[i] );
5336 	}
5337 
5338 	wxMenuItem *newItem =
5339 	    new wxMenuItem ( fileMenu, wxID_NEW, _ ( "&New...\tCtrl+N" ), _ ( "New..." ) );
5340 	newItem->SetBitmap ( new16Bitmap );
5341 	wxMenuItem *openItem =
5342 	    new wxMenuItem ( fileMenu, wxID_OPEN, _ ( "&Open...\tCtrl+O" ), _ ( "Open..." ) );
5343 	openItem->SetBitmap ( open16Bitmap );
5344 	wxMenuItem *openLargeFileItem =
5345 	    new wxMenuItem ( fileMenu, ID_OPEN_LARGE_FILE,
5346 	                     _ ( "O&pen Large Document...\tCtrl+Shift+O" ), _ ( "Open Large Document..." ) );
5347 	openLargeFileItem->SetBitmap ( wxNullBitmap );
5348 
5349 	wxMenuItem *closeItem =
5350 	    new wxMenuItem ( fileMenu, wxID_CLOSE, _ ( "&Close\tCtrl+W" ), _ ( "Close" ) );
5351 	closeItem->SetBitmap ( wxNullBitmap );
5352 	wxMenuItem *closeAllItem =
5353 	    new wxMenuItem ( fileMenu, wxID_CLOSE_ALL, _ ( "C&lose All" ), _ ( "Close All" ) );
5354 	closeAllItem->SetBitmap ( wxNullBitmap );
5355 	wxMenuItem *saveItem =
5356 	    new wxMenuItem ( fileMenu, wxID_SAVE, _ ( "&Save\tCtrl+S" ), _ ( "Save" ) );
5357 	saveItem->SetBitmap ( save16Bitmap );
5358 	wxMenuItem *saveAsItem =
5359 	    new wxMenuItem ( fileMenu, wxID_SAVEAS, _ ( "S&ave As...\tF12" ), _ ( "Save As..." ) );
5360 	saveAsItem->SetBitmap ( wxNullBitmap );
5361 #ifdef __WXMSW__
5362 	wxMenuItem *exportItem =
5363         new wxMenuItem ( fileMenu, ID_EXPORT, _ ( "&DAISY Export..." ), _ ( "DAISY Export..." ) );
5364     exportItem->SetBitmap ( wxNullBitmap );
5365 #endif
5366 	wxMenuItem *reloadItem =
5367 	    new wxMenuItem ( fileMenu, ID_RELOAD, _ ( "&Reload" ), _ ( "Reload" ) );
5368 	reloadItem->SetBitmap ( wxNullBitmap );
5369 	wxMenuItem *revertItem =
5370 	    new wxMenuItem ( fileMenu, wxID_REVERT, _ ( "&Revert" ), _ ( "Revert" ) );
5371 	revertItem->SetBitmap ( wxNullBitmap );
5372 	wxMenuItem *printSetupItem =
5373 	    new wxMenuItem ( fileMenu, ID_PRINT_SETUP, _ ( "Pa&ge Setup..." ), _ ( "Page Setup..." ) );
5374 	printSetupItem->SetBitmap ( wxNullBitmap );
5375 	wxMenuItem *printPreviewItem =
5376 	    new wxMenuItem ( fileMenu, ID_PRINT_PREVIEW, _ ( "Pr&int Preview..." ), _ ( "Print Preview..." ) );
5377 	printPreviewItem->SetBitmap ( printPreviewBitmap );
5378 	wxMenuItem *printItem =
5379 	    new wxMenuItem ( fileMenu, ID_PRINT, _ ( "Pri&nt...\tCtrl+P" ), _ ( "Print..." ) );
5380 	printItem->SetBitmap ( print16Bitmap );
5381 	wxMenuItem *importMSWordItem =
5382 	    new wxMenuItem (
5383 	    fileMenu, ID_IMPORT_MSWORD, _ ( "I&mport Microsoft Word Document..." ) );
5384 	importMSWordItem->SetBitmap ( wxNullBitmap );
5385 	wxMenuItem *exportMSWordItem =
5386 	    new wxMenuItem (
5387 	    fileMenu, ID_EXPORT_MSWORD, _ ( "Expor&t Microsoft Word Document..." ) );
5388 	exportMSWordItem->SetBitmap ( wxNullBitmap );
5389 
5390 	wxMenuItem *exitItem =
5391 	    new wxMenuItem ( fileMenu, wxID_EXIT, _ ( "E&xit" ), _ ( "Exit" ) );
5392 	exitItem->SetBitmap ( wxNullBitmap );
5393 
5394 	fileMenu->Append ( newItem );
5395 	fileMenu->Append ( openItem );
5396 	fileMenu->Append ( openLargeFileItem );
5397 	fileMenu->AppendSeparator();
5398 	fileMenu->Append ( closeItem );
5399 	fileMenu->Append ( closeAllItem );
5400 	fileMenu->Append ( saveItem );
5401 	fileMenu->Append ( saveAsItem );
5402     fileMenu->AppendSeparator();
5403 	fileMenu->Append ( reloadItem );
5404 	fileMenu->Append ( revertItem );
5405 	fileMenu->AppendSeparator();
5406 	fileMenu->Append ( printSetupItem );
5407 	fileMenu->Append ( printPreviewItem );
5408 	fileMenu->Append ( printItem );
5409 #ifdef __WXMSW__
5410 	fileMenu->AppendSeparator();
5411 	fileMenu->Append ( exportItem );
5412 	fileMenu->Append ( importMSWordItem );
5413 	fileMenu->Append ( exportMSWordItem );
5414 #endif
5415 	history.AddFilesToMenu ( fileMenu );
5416 
5417 	fileMenu->AppendSeparator();
5418 	fileMenu->Append ( exitItem );
5419 }
5420 
getToolBar()5421 wxToolBar *MyFrame::getToolBar()
5422 {
5423 	wxToolBar *toolBar = new wxToolBar (
5424 	    this,
5425 	    ID_TOOLBAR,
5426 	    wxDefaultPosition,
5427 	    wxDefaultSize,
5428 	    wxTB_FLAT |
5429 	    wxTB_HORIZONTAL |
5430 	    wxTB_DOCKABLE );
5431 	int w, h;
5432 	w = saveBitmap.GetWidth(), h = saveBitmap.GetHeight();
5433 	toolBar->SetToolBitmapSize ( wxSize ( w, h ) );
5434 
5435 	toolBar->AddTool (
5436 	    wxID_NEW,
5437 	    _ ( "New" ),
5438 	    newBitmap,
5439 	    _ ( "New" ) );
5440 	toolBar->AddTool (
5441 	    wxID_OPEN,
5442 	    _ ( "Open" ),
5443 	    openBitmap,
5444 	    _ ( "Open" ) );
5445 	toolBar->AddTool (
5446 	    wxID_SAVE,
5447 	    _ ( "Save" ),
5448 	    saveBitmap,
5449 	    wxNullBitmap,
5450 	    wxITEM_NORMAL,
5451 	    _ ( "Save" ) );
5452 #ifndef __WXOSX__
5453 	toolBar->AddTool (
5454 	    ID_PRINT,
5455 	    _ ( "Print" ),
5456 	    printBitmap,
5457 	    wxNullBitmap,
5458 	    wxITEM_NORMAL,
5459 	    _ ( "Print" ) );
5460 	toolBar->AddTool (
5461 	    ID_CHECK_WELLFORMED,
5462 	    _ ( "Check Well-formedness" ),
5463 	    checkWellformedBitmap,
5464 	    wxNullBitmap,
5465 	    wxITEM_NORMAL,
5466 	    _ ( "Check Well-formedness" ) );
5467 	toolBar->AddTool (
5468 	    ID_VALIDATE_W3C_SCHEMA,
5469 	    _ ( "Validate" ),
5470 	    checkValidBitmap,
5471 	    wxNullBitmap,
5472 	    wxITEM_NORMAL,
5473 	    _ ( "Validate" ) );
5474 	toolBar->AddTool (
5475 	    ID_BROWSER,
5476 	    _ ( "Browser" ),
5477 	    internetBitmap,
5478 	    wxNullBitmap,
5479 	    wxITEM_NORMAL,
5480 	    _ ( "Browser" ) );
5481 	toolBar->AddTool (
5482 	    ID_SPELL,
5483 	    _ ( "Spelling" ),
5484 	    spellingBitmap,
5485 	    wxNullBitmap,
5486 	    wxITEM_NORMAL,
5487 	    _ ( "Spelling" ) );
5488 	toolBar->AddCheckTool (
5489 	    ID_PROTECT_TAGS,
5490 	    _ ( "Lock Tags" ),
5491 	    hyperlinkBitmap,
5492 	    wxNullBitmap,
5493 	    _ ( "Lock Tags" ) );
5494 	toolBar->ToggleTool (
5495 	    ID_PROTECT_TAGS, protectTags );
5496 #endif
5497 
5498 	toolBar->Realize();
5499 	return toolBar;
5500 }
5501 
getActiveDocument()5502 XmlDoc *MyFrame::getActiveDocument()
5503 {
5504 	if ( !mainBook->GetPageCount() )
5505 		return NULL;
5506 	return ( XmlDoc * ) mainBook->GetPage ( mainBook->GetSelection() );
5507 }
5508 
addSafeSeparator(wxToolBar * toolBar)5509 void MyFrame::addSafeSeparator ( wxToolBar *toolBar )
5510 {
5511 	wxStaticText *staticControl = new wxStaticText (
5512 	    toolBar,
5513 	    wxID_ANY,
5514 	    _T ( "  " ) );
5515 	toolBar->AddControl ( staticControl );
5516 }
5517 
statusProgress(const wxString & s)5518 void MyFrame::statusProgress ( const wxString& s )
5519 {
5520 	wxStatusBar *status = GetStatusBar();
5521 	if ( !status )
5522 		return;
5523 	status->SetStatusText ( s, 0 );
5524 }
5525 
messagePane(const wxString & s,int iconType,bool forcePane)5526 void MyFrame::messagePane ( const wxString& s, int iconType, bool forcePane )
5527 {
5528 	statusProgress ( wxEmptyString );
5529 	wxString paneTitle;
5530 	switch ( iconType )
5531 	{
5532 		case ( CONST_INFO ) :
5533 			paneTitle = _ ( "Information" );
5534 			break;
5535 		case ( CONST_WARNING ) :
5536 			paneTitle = _ ( "Warning" );
5537 			break;
5538 		case ( CONST_STOP ) :
5539 			paneTitle = _ ( "Stopped" );
5540 			break;
5541 		case ( CONST_QUESTION ) :
5542 			paneTitle = _ ( "Question" );
5543 			break;
5544 		default:
5545 			paneTitle = _ ( "Message" );
5546 			break;
5547 	}
5548 
5549 	wxAuiPaneInfo &info = manager.GetPane ( htmlReport );
5550 	if ( !info.IsShown() )
5551 	{
5552 		info.Show ( true );
5553 	}
5554 
5555 	info.Caption ( paneTitle );
5556 
5557 	wxString htmlString = s;
5558 	htmlString.Replace ( _T ( "&" ), _T ( "&amp;" ), true );
5559 	htmlString.Replace ( _T ( "<" ), _T ( "&lt;" ), true );
5560 	htmlString.Replace ( _T ( ">" ), _T ( "&gt;" ), true );
5561 
5562 	// have to use <br> on Ubuntu
5563 	htmlString.Replace ( _T("[br]"), _T("<br>"), true );
5564 	htmlString.Replace ( _T("[br/]"), _T("<br/>"), true );
5565 	htmlString.Replace ( _T("[b]"), _T("<b>"), true );
5566 	htmlString.Replace ( _T("[/b]"), _T("</b>"), true );
5567 	htmlString.Replace ( _T("[i]"), _T("<i>"), true );
5568 	htmlString.Replace ( _T("[/i]"), _T("</i>"), true );
5569 
5570 	wxString htmlBuffer;
5571 	htmlBuffer += _T ( "<html><body><table><tr><td width=\"5%\"><img src=\"" );
5572 	switch ( iconType )
5573 	{
5574 		case ( CONST_INFO ) :
5575 			htmlBuffer += pngDir;
5576 			htmlBuffer += _T ( "stock_dialog-info-32.png" );
5577 			break;
5578 		case ( CONST_WARNING ) :
5579 						htmlBuffer += pngDir;
5580 			htmlBuffer += _T ( "stock_dialog-warning-32.png" );
5581 			break;
5582 		case ( CONST_STOP ) :
5583 						htmlBuffer += pngDir;
5584 			htmlBuffer += _T ( "stock_dialog-stop-32.png" );
5585 			break;
5586 		case ( CONST_QUESTION ) :
5587 						htmlBuffer += pngDir;
5588 			htmlBuffer += _T ( "stock_dialog-question-32.png" );
5589 			break;
5590 		default:
5591 			break;
5592 	}
5593 	htmlBuffer += _T ( "\"></td><td width=\"95%\">" );
5594 	htmlBuffer += htmlString;
5595 	htmlBuffer += _T ( "</td></tr></table></body></html>" );
5596 
5597 	wxString file;
5598 	XmlDoc *doc = getActiveDocument();
5599 	if ( doc )
5600 		file = doc->getFullFileName();
5601 	htmlReport->setLastFile ( file );
5602 	htmlReport->SetPage ( htmlBuffer );
5603 
5604 	manager.Update();
5605 }
5606 
documentOk(const wxString & status)5607 void MyFrame::documentOk ( const wxString& status )
5608 {
5609 	XmlDoc *doc;
5610 	if ( ( doc = getActiveDocument() ) == NULL )
5611 		return;
5612 	wxString message;
5613 	message.Printf ( _ ( "%s is %s" ),
5614 	                 doc->getShortFileName().c_str(),
5615 	                 status.c_str() );
5616 	messagePane ( message, CONST_INFO );
5617 }
5618 
applyEditorProperties(bool zoomOnly)5619 void MyFrame::applyEditorProperties ( bool zoomOnly )
5620 {
5621 	XmlDoc *doc;
5622 	size_t documentCount = mainBook->GetPageCount();
5623 	for ( size_t i = 0; i < documentCount; i++ )
5624 	{
5625 		doc = ( XmlDoc * ) mainBook->GetPage ( i );
5626 		if ( doc )
5627 		{
5628 			doc->applyProperties ( properties, zoomOnly );
5629 			if ( !properties.validateAsYouType )
5630 				doc->clearErrorIndicators();
5631 		}
5632 	}
5633 }
5634 
modifiedMessage()5635 void MyFrame::modifiedMessage()
5636 {
5637 	messagePane (
5638 	    _ ( "Document has been modified: save or discard changes" ),
5639 	    CONST_STOP );
5640 }
5641 
xmliseWideTextNode(wxString & s)5642 void MyFrame::xmliseWideTextNode ( wxString& s )
5643 {
5644 	s.Replace ( _T ( "&" ), _T ( "&amp;" ), true );
5645 	s.Replace ( _T ( "<" ), _T ( "&lt;" ), true );
5646 	s.Replace ( _T ( ">" ), _T ( "&gt;" ), true );
5647 }
5648 
getFileType(const wxString & fileName)5649 int MyFrame::getFileType ( const wxString& fileName )
5650 {
5651 	wxString extension;
5652 	wxFileName::SplitPath ( fileName, NULL/*Path*/, NULL/*Name*/, &extension );
5653 	if ( extension.size() != 3 )
5654 		return FILE_TYPE_XML;
5655 
5656 	extension.MakeLower();
5657 
5658 	if ( extension == _T ( "dtd" ) || extension == _T ( "ent" ) )
5659 		return FILE_TYPE_DTD;
5660 	else if ( extension == _T ( "css" ) )
5661 		return FILE_TYPE_CSS;
5662 	else if ( extension == _T ( "php" ) )
5663 		return FILE_TYPE_PHP;
5664 	else if ( extension == _T ( "exe" ) )
5665 		return FILE_TYPE_BINARY;
5666 	else if ( extension == _T ( "rnc" ) )
5667 		return FILE_TYPE_RNC;
5668 	return FILE_TYPE_XML;
5669 }
5670 
getNotebookStyleMask()5671 long MyFrame::getNotebookStyleMask()
5672 {
5673 	/*
5674 	if (notebookStyleMenu->IsChecked(ID_NOTEBOOK_STYLE_FLAT))
5675 	  return wxFNB_FANCY_TABS | wxFNB_MOUSE_MIDDLE_CLOSES_TABS | wxFNB_X_ON_TAB;
5676 	else if (notebookStyleMenu->IsChecked(ID_NOTEBOOK_STYLE_VC8))
5677 	  return wxFNB_BACKGROUND_GRADIENT | wxFNB_VC8 | wxFNB_MOUSE_MIDDLE_CLOSES_TABS |
5678 	    wxFNB_X_ON_TAB | wxFNB_DROPDOWN_TABS_LIST | wxFNB_NO_NAV_BUTTONS;
5679 	else
5680 	  return wxFNB_BACKGROUND_GRADIENT | wxFNB_VC8 | wxFNB_MOUSE_MIDDLE_CLOSES_TABS | wxFNB_COLORFUL_TABS |
5681 	    wxFNB_X_ON_TAB | wxFNB_DROPDOWN_TABS_LIST | wxFNB_NO_NAV_BUTTONS;
5682 	  //wxFNB_BACKGROUND_GRADIENT | wxFNB_VC8 | wxFNB_MOUSE_MIDDLE_CLOSES_TABS | wxFNB_COLORFUL_TABS;
5683 	*/
5684 	return 0;
5685 }
5686 
isSpecialFileType(const wxString & fileName)5687 bool MyFrame::isSpecialFileType ( const wxString& fileName )
5688 {
5689 	std::string fileNameLocal, fileNameLocalLC;
5690 	fileNameLocal = fileName.mb_str ( wxConvLocal );
5691 	fileNameLocalLC = CaseHandler::lowerCase ( fileNameLocal );
5692 
5693 	return (
5694 	           fileNameLocalLC.find ( ".dtd" ) != std::string::npos ||
5695 	           fileNameLocalLC.find ( ".css" ) != std::string::npos ||
5696 	           fileNameLocalLC.find ( ".php" ) != std::string::npos );
5697 }
5698 
encodingMessage()5699 void MyFrame::encodingMessage()
5700 {
5701 	wxString msg = _ ( "Encoding should be one of " );
5702 	msg += ENCODING_INFO;
5703 	messagePane ( msg, CONST_STOP );
5704 }
5705 
updatePaths()5706 void MyFrame::updatePaths()
5707 {
5708 	wxString sep = wxFileName::GetPathSeparator();
5709 	ruleSetDir = applicationDir + sep + _T ( "rulesets" );
5710 	filterDir = applicationDir + sep + _T ( "filters" );
5711 	templateDir = applicationDir + sep + _T ( "templates" ) + sep;
5712 	binDir = applicationDir + sep + _T ( "bin" ) + sep;
5713 	helpDir = applicationDir + sep + _T ( "help" ) + sep;
5714 	rngDir = applicationDir + sep + _T ( "rng" ) + sep;
5715 	htmlDir = applicationDir + sep + _T ( "html" ) + sep;
5716 	pngDir = applicationDir + sep + _T ( "png" ) + sep;
5717 	xpmDir = applicationDir + sep + _T ( "xpm" ) + sep;
5718 	daisyDir = applicationDir + sep + _T ( "daisy" ) + sep;
5719 	catalogPath =
5720 	    applicationDir + sep + _T ( "catalog" ) + sep + _T ( "catalog" );
5721 	xslDtdPath =
5722 	    applicationDir + sep + _T ( "dtd" ) + sep + _T ( "xslt10.dtd" );
5723 	rssDtdPath =
5724 	    applicationDir + sep + _T ( "dtd" ) + sep + _T ( "rss2.dtd" );
5725 	xtmDtdPath =
5726 	    applicationDir + sep + _T ( "dtd" ) + sep + _T ( "xtm1.dtd" );
5727 	lzxDtdPath =
5728 	    applicationDir + sep + _T ( "dtd" ) + sep + _T ( "lzx.dtd" );
5729 	xliffDtdPath =
5730 	    applicationDir + sep + _T ( "dtd" ) + sep + _T ( "xliff.dtd" );
5731 	aspellDataPath = applicationDir + sep +
5732         _T ( "aspell" ) + sep + _T ( "data" );
5733 	aspellDictPath = applicationDir + sep +
5734         _T ( "aspell" ) + sep + _T ( "dict" );
5735 }
5736 
OnAssociate(wxCommandEvent & event)5737 void MyFrame::OnAssociate ( wxCommandEvent& event )
5738 {
5739 	XmlDoc *doc;
5740 	if ( ( doc = getActiveDocument() ) == NULL )
5741 		return;
5742 
5743 	XmlTextInfo info ( doc->getFullFileName() );
5744 	info.parse ( doc->myGetTextRaw() );
5745 
5746 	wxString title, label, type, extension, path, defaulturl, defaultaux;
5747 	wxString auxiliaryLabel;
5748 	int id = event.GetId();
5749 	switch ( id )
5750 	{
5751 		case ID_ASSOCIATE_DTD_PUBLIC:
5752 			type = _ ( "Public DTD" );
5753 			extension = _T ( "*.dtd" );
5754 			defaulturl = lastDtdPublic;
5755 			defaultaux = info.mDtdFile.empty()
5756 					? lastDtdPublicAux : info.mDtdFile;
5757 			break;
5758 		case ID_ASSOCIATE_DTD_SYSTEM:
5759 			type = _ ( "System DTD" );
5760 			extension = _T ( "*.dtd" );
5761 			defaulturl = info.mDtdFile.empty() ? lastDtdSystem : info.mDtdFile;
5762 			defaultaux = _T ( "" );
5763 			break;
5764 		case ID_ASSOCIATE_W3C_SCHEMA:
5765 			type = _ ( "XML Schema" );
5766 			extension = _T ( "*.xsd" );
5767 			defaulturl = info.mXsdFile.empty() ? lastSchema : info.mXsdFile;
5768 			defaultaux = _T ( "" );
5769 			break;
5770 		case ID_ASSOCIATE_XSL:
5771 			type = _ ( "XSLT stylesheet" );
5772 			extension = _T ( "*.xsl;*.xslt" );
5773 			defaulturl = info.mXslFile.empty()
5774 					? lastXslStylesheet : info.mXslFile;
5775 			defaultaux = _T ( "" );
5776 			break;
5777 		default:
5778 			return;
5779 	}
5780 
5781 	std::string utf8Buffer;
5782 	getRawText ( doc, utf8Buffer );
5783 	std::string origEncoding = XmlEncodingHandler::get ( utf8Buffer );
5784 	WrapExpat wellformedparser ( "UTF-8" );
5785 	if ( !wellformedparser.parse ( utf8Buffer ) )
5786 	{
5787 		wxString message;
5788 		message.Printf (
5789 		    _ ( "Cannot associate %s: %s" ),
5790 		    type.c_str(),
5791 		    wellformedparser.getLastError().c_str() );
5792 		messagePane ( message, CONST_STOP );
5793 		return;
5794 	}
5795 
5796 	title.Printf ( _ ( "Associate %s" ), type.c_str() );
5797 	label = _ ( "Choose a file:" );
5798 
5799 	bool auxiliaryBox =
5800 	    ( id == ID_ASSOCIATE_DTD_PUBLIC );
5801 	//(id == ID_ASSOCIATE_W3C_SCHEMA_NS || id == ID_ASSOCIATE_DTD_PUBLIC);
5802 	if ( auxiliaryBox )
5803 	{
5804 		auxiliaryLabel = _ ( "Choose a public identifier:" );
5805 		/*
5806 		      (id == ID_ASSOCIATE_DTD_PUBLIC) ? _("Choose a public identifier:") :
5807 		        _("Choose a namespace:");
5808 		*/
5809 	}
5810 
5811 	AssociateDialog ad (
5812 	    this,
5813 	    title,
5814 	    label,
5815 	    type,
5816 	    extension,
5817 	    defaulturl,
5818 	    &mLastDir,
5819 	    auxiliaryBox,
5820 	    auxiliaryLabel,
5821 	    defaultaux );
5822 	if ( ad.ShowModal() != wxID_OK )
5823 		return;
5824 
5825 	path = ad.getUrl();
5826 
5827 	wxString aux, schemaPathMemory;
5828 
5829 	if ( auxiliaryBox )
5830 	{
5831 		aux = ad.getAux();
5832 	}
5833 
5834 	std::string modifiedBuffer;
5835 
5836 	// remember choice
5837 	switch ( id )
5838 	{
5839 		case ID_ASSOCIATE_W3C_SCHEMA:
5840 			lastSchema = path;
5841 			break;
5842 		case ID_ASSOCIATE_DTD_PUBLIC:
5843 			lastDtdPublic = path;
5844 			lastDtdPublicAux = aux;
5845 			break;
5846 		case ID_ASSOCIATE_DTD_SYSTEM:
5847 			lastDtdSystem = path;
5848 			break;
5849 		case ID_ASSOCIATE_XSL:
5850 			lastXslStylesheet = path;
5851 			break;
5852 		default:
5853 			break;
5854 	}
5855 
5856 	if ( id == ID_ASSOCIATE_W3C_SCHEMA )
5857 	{
5858 		XmlAssociateXsd parser ( path, "UTF-8" );
5859 		if ( !parser.parse ( utf8Buffer ) )
5860 			return;
5861 		modifiedBuffer = parser.getBuffer();
5862 	}
5863 	else if ( id == ID_ASSOCIATE_DTD_SYSTEM || id == ID_ASSOCIATE_DTD_PUBLIC )
5864 	{
5865 		XmlAssociateDtd parser ( info, path, aux, "UTF-8" );
5866 		if ( !parser.parse ( utf8Buffer ) )
5867 			return;
5868 		modifiedBuffer = parser.getBuffer();
5869 	}
5870 	else if ( id == ID_ASSOCIATE_XSL )
5871 	{
5872 		XmlAssociateXsl parser( info, path, "UTF-8" );
5873 		if ( !parser.parse ( utf8Buffer ) )
5874 			return;
5875 		modifiedBuffer = parser.getBuffer();
5876 	}
5877 	else
5878 		return;
5879 
5880 	XmlEncodingHandler::set ( modifiedBuffer, origEncoding );
5881 	doc->SetTextRaw ( modifiedBuffer.c_str() );
5882 	doc->SetFocus();
5883 }
5884 
openRememberedTabs()5885 void MyFrame::openRememberedTabs()
5886 {
5887 	wxStringTokenizer files ( openTabsOnClose, _T ( "|" ) );
5888 	while ( files.HasMoreTokens() )
5889 	{
5890 		wxString file = files.GetNextToken();
5891 		if ( file.IsEmpty() || !openFile ( file ) )
5892 			continue; //break; // Ignore errors
5893 	}
5894 
5895 	XmlDoc *doc;
5896 	if ( ( doc = getActiveDocument() ) != NULL )
5897 		doc->SetFocus();
5898 }
5899 
getRawText(XmlDoc * doc,std::string & buffer)5900 void MyFrame::getRawText ( XmlDoc *doc, std::string& buffer )
5901 {
5902 	if ( !doc )
5903 	{
5904 		buffer = "";
5905 		return;
5906 	}
5907 	buffer = doc->myGetTextRaw();
5908 }
5909 
OnWordCount(wxCommandEvent & event)5910 void MyFrame::OnWordCount ( wxCommandEvent& event )
5911 {
5912 	XmlDoc *doc;
5913 	if ( ( doc = getActiveDocument() ) == NULL )
5914 		return;
5915 
5916 	std::string rawBufferUtf8;
5917 	getRawText ( doc, rawBufferUtf8 );
5918 
5919 	XmlWordCount xwc ( "UTF-8" );
5920 	wxString msg;
5921 	if ( !xwc.parse ( rawBufferUtf8 ) )
5922 	{
5923 		statusProgress ( wxEmptyString );
5924 		msg.Printf ( _ ( "Cannot count words: %s" ), xwc.getLastError().c_str() );
5925 		messagePane ( msg, CONST_STOP );
5926 		return;
5927 	}
5928 
5929 	int count = xwc.getWordCount();
5930 
5931 	msg.Printf (
5932 	    wxPLURAL ( "%s contains %i word", "%s contains %i words", count ),
5933 	    doc->getShortFileName().c_str(), count );
5934 
5935 	messagePane ( msg, CONST_INFO, true );
5936 	doc->SetFocus();
5937 }
5938 
removeUtf8Bom(std::string & buffer)5939 void MyFrame::removeUtf8Bom ( std::string& buffer )
5940 {
5941 	if ( buffer.size() > 3 &&
5942 	        ( unsigned char ) buffer[0] == 0xEF &&
5943 	        ( unsigned char ) buffer[1] == 0xBB &&
5944 	        ( unsigned char ) buffer[2] == 0xBF )
5945 	{
5946 		buffer.erase ( 0, 3 );
5947 	}
5948 }
5949 
loadBitmaps()5950 void MyFrame::loadBitmaps()
5951 {
5952 #ifdef __WXMSW__
5953 	// toolbar icons
5954 	newBitmap = wxBITMAP ( stock_new );
5955 	openBitmap = wxBITMAP ( stock_open );
5956 	saveBitmap = wxBITMAP ( stock_save );
5957 	printBitmap = wxBITMAP ( stock_print );
5958 	spellingBitmap = wxBITMAP ( stock_spellcheck );
5959 	internetBitmap = wxBITMAP ( stock_internet );
5960 	hyperlinkBitmap = wxBITMAP ( stock_hyperlink );
5961 	filtersBitmap = wxBITMAP ( stock_filters );
5962 	checkWellformedBitmap = wxBITMAP ( stock_calc-accept );
5963 	checkValidBitmap = wxBITMAP ( stock_calc-accept-green );
5964 
5965 	// menu icons
5966 	new16Bitmap = wxBITMAP ( stock_new_16 );
5967 	open16Bitmap = wxBITMAP ( stock_open_16 );
5968 	save16Bitmap = wxBITMAP ( stock_save_16 );
5969 	printPreviewBitmap = wxBITMAP ( stock_print_preview_16 );
5970 	print16Bitmap = wxBITMAP ( stock_print_16 );
5971 	undo16Bitmap = wxBITMAP ( stock_undo_16 );
5972 	redo16Bitmap = wxBITMAP ( stock_redo_16 );
5973 	cutBitmap = wxBITMAP ( stock_cut_16 );
5974 	copyBitmap = wxBITMAP ( stock_copy_16 );
5975 	pasteBitmap = wxBITMAP ( stock_paste_16 );
5976 	findBitmap = wxBITMAP ( stock_search_16 );
5977 	spelling16Bitmap = wxBITMAP ( stock_spellcheck_16 );
5978 	helpBitmap = wxBITMAP ( stock_help_16 );
5979 /*
5980 #elif __WXOSX__
5981 	// toolbar icons
5982 	newBitmap.LoadFile ( xpmDir + _T ( "stock_new.xpm" ), wxBITMAP_TYPE_XPM );
5983 	openBitmap.LoadFile ( xpmDir + _T ( "stock_open.xpm" ), wxBITMAP_TYPE_XPM );
5984 	saveBitmap.LoadFile ( xpmDir + _T ( "stock_save.xpm" ), wxBITMAP_TYPE_XPM );
5985 
5986         // menu icons
5987         new16Bitmap = wxNullBitmap;
5988         open16Bitmap = wxNullBitmap;
5989         save16Bitmap = wxNullBitmap;
5990         printPreviewBitmap = wxNullBitmap;
5991         print16Bitmap = wxNullBitmap;
5992         undo16Bitmap = wxNullBitmap;
5993         redo16Bitmap = wxNullBitmap;
5994         cutBitmap = wxNullBitmap;
5995         copyBitmap = wxNullBitmap;
5996         pasteBitmap = wxNullBitmap;
5997         findBitmap = wxNullBitmap;
5998         spelling16Bitmap = wxNullBitmap;
5999         helpBitmap = wxNullBitmap;
6000 */
6001 #else
6002 	// toolbar icons
6003 	newBitmap = wxArtProvider::GetBitmap ( wxART_NEW, wxART_TOOLBAR );
6004 	openBitmap = wxArtProvider::GetBitmap ( wxART_FILE_OPEN, wxART_TOOLBAR );
6005 	saveBitmap = wxArtProvider::GetBitmap ( wxART_FILE_SAVE, wxART_TOOLBAR );
6006 #ifndef __WXOSX__
6007 	printBitmap = wxArtProvider::GetBitmap ( wxART_PRINT, wxART_TOOLBAR );
6008 	spellingBitmap = wxArtProvider::GetBitmap ( _T ( "gtk-spell-check" ), wxART_TOOLBAR );
6009 
6010 	// no stock icons for the following
6011 	internetBitmap.LoadFile ( pngDir + _T ( "stock_internet.png" ), wxBITMAP_TYPE_PNG );
6012 	hyperlinkBitmap.LoadFile ( pngDir + _T ( "stock_hyperlink.png" ), wxBITMAP_TYPE_PNG );
6013 	checkWellformedBitmap.LoadFile ( pngDir + _T ( "stock_calc-accept.png" ), wxBITMAP_TYPE_PNG );
6014 	checkValidBitmap.LoadFile ( pngDir + _T ( "stock_calc-accept-green.png" ), wxBITMAP_TYPE_PNG );
6015 #endif
6016 
6017 	// menu icons
6018 	new16Bitmap = wxNullBitmap;
6019 	open16Bitmap = wxNullBitmap;
6020 	save16Bitmap = wxNullBitmap;
6021 	printPreviewBitmap = wxNullBitmap;
6022 	print16Bitmap = wxNullBitmap;
6023 	undo16Bitmap = wxNullBitmap;
6024 	redo16Bitmap = wxNullBitmap;
6025 	cutBitmap = wxNullBitmap;
6026 	copyBitmap = wxNullBitmap;
6027 	pasteBitmap = wxNullBitmap;
6028 	findBitmap = wxNullBitmap;
6029 	spelling16Bitmap = wxNullBitmap;
6030 	helpBitmap = wxNullBitmap;
6031 #endif
6032 }
6033 
6034 #ifdef __WXMSW__
OnDropFiles(wxDropFilesEvent & event)6035 void MyFrame::OnDropFiles ( wxDropFilesEvent& event )
6036 {
6037 	int no = event.GetNumberOfFiles();
6038 	wxString *iterator = event.GetFiles();
6039 
6040 	if ( !no || !iterator )
6041 		return;
6042 
6043 	for ( int i = 0; i < no; i++, iterator++ )
6044 	{
6045 		if ( !openFile ( *iterator ) )
6046 			break;
6047 	}
6048 }
6049 #endif
6050 
OnPromptGenerated(wxNotifyEvent & event)6051 void MyFrame::OnPromptGenerated ( wxNotifyEvent &event )
6052 {
6053 	XmlDoc *doc = this->getActiveDocument();
6054 	locationPanel->update ( doc, lastParent );
6055 	insertChildPanel->update ( doc, lastParent, wxEmptyString, true );
6056 	insertSiblingPanel->update ( doc, lastParent, wxEmptyString, true );
6057 	insertEntityPanel->update ( doc, wxEmptyString, wxEmptyString, true );
6058 }
6059 
OnCopyXPath(wxCommandEvent & event)6060 void MyFrame::OnCopyXPath ( wxCommandEvent &event )
6061 {
6062 	XmlDoc *doc = getActiveDocument();
6063 	if ( !doc )
6064 		return;
6065 
6066 	wxBusyCursor cursor;
6067 
6068 	wxString xpath = doc->getCurrentXPath();
6069 	// Write the XPath to the clipboard
6070 	if ( xpath.IsEmpty() )
6071 	{
6072 		messagePane ( _("The current XPath is empty."), CONST_WARNING );
6073 	}
6074 	else if ( wxTheClipboard->Open() )
6075 	{
6076 		// This data objects are held by the clipboard,
6077 		// so do not delete them in the app.
6078 		wxTheClipboard->SetData ( new wxTextDataObject ( xpath ) );
6079 		wxTheClipboard->Close();
6080 
6081 		wxString message = wxString::Format
6082 					( _("The current XPath has been copied to the clipboard:[br][b]%s[/b]")
6083 					, xpath.c_str()
6084 					);
6085 		messagePane ( message, CONST_INFO );
6086 	}
6087 	else
6088 	{
6089 		wxString message = wxString::Format
6090 				( _("Failed to copy the current XPath to the clipboard:[br][b]%s[/b]")
6091 				, xpath.c_str()
6092 				);
6093 		messagePane ( message, CONST_STOP );
6094 		htmlReport->SetFocus(); // This is needed to make Ctrl + C work
6095 	}
6096 }
6097 
OnUpdateCopyXPath(wxUpdateUIEvent & event)6098 void MyFrame::OnUpdateCopyXPath ( wxUpdateUIEvent& event )
6099 {
6100 	event.Enable ( getActiveDocument() );
6101 }
6102 
getAuxPath(const wxString & fileName)6103 wxString MyFrame::getAuxPath ( const wxString& fileName )
6104 {
6105 	if ( fileName.Find ( _T ( ".xsl" ) ) != wxNOT_FOUND ||
6106 	        fileName.Find ( _T ( ".XSL" ) ) != wxNOT_FOUND )
6107 		return xslDtdPath;
6108 	else if ( fileName.Find ( _T ( ".rss" ) ) != wxNOT_FOUND ||
6109 	          fileName.Find ( _T ( ".RSS" ) ) != wxNOT_FOUND )
6110 		return rssDtdPath;
6111 	else if ( fileName.Find ( _T ( ".xtm" ) ) != wxNOT_FOUND ||
6112 	          fileName.Find ( _T ( ".xtmm" ) ) != wxNOT_FOUND ||
6113 	          fileName.Find ( _T ( ".XTM" ) ) != wxNOT_FOUND ||
6114 	          fileName.Find ( _T ( ".XTMM" ) ) != wxNOT_FOUND )
6115 		return xtmDtdPath;
6116 	else if ( fileName.Find ( _T ( ".lzx" ) ) != wxNOT_FOUND ||
6117 	          fileName.Find ( _T ( ".LZX" ) ) != wxNOT_FOUND )
6118 		return lzxDtdPath;
6119 	else if ( fileName.Find ( _T ( ".xlf" ) ) != wxNOT_FOUND ||
6120 	          fileName.Find ( _T ( ".XLF" ) ) != wxNOT_FOUND )
6121 		return xliffDtdPath;
6122 	return wxEmptyString;
6123 }
6124 
OnActivateApp(wxActivateEvent & event)6125 void MyFrame::OnActivateApp ( wxActivateEvent& event )
6126 {
6127 	event.Skip();
6128 	if ( !mainBook || !event.GetActive() )
6129 		return;
6130 	restoreFocusToNotebook = true;
6131 }
6132 
OnIconize(wxIconizeEvent & event)6133 void MyFrame::OnIconize ( wxIconizeEvent& event )
6134 {
6135 	event.Skip();
6136 #if wxCHECK_VERSION(2,9,0)
6137 	if (event.IsIconized())
6138 #else
6139 	if ( event.Iconized() )
6140 #endif
6141 		return;
6142 	restoreFocusToNotebook = true;
6143 	manager.Update();
6144 }
6145 
OnKeyPressed(wxKeyEvent & event)6146 void MyFrame::OnKeyPressed ( wxKeyEvent& event )
6147 {
6148 	event.Skip();
6149 }
6150 
setStrictScrolling(bool b)6151 void MyFrame::setStrictScrolling ( bool b )
6152 {
6153 	XmlDoc *doc;
6154 	doc = getActiveDocument();
6155 	if ( !doc )
6156 		return;
6157 	doc->SetYCaretPolicy ( ( b ) ? ( wxSTC_CARET_STRICT | wxSTC_CARET_SLOP ) : wxSTC_CARET_EVEN,
6158 	                       ( b ) ? 10 : 0 );
6159 }
6160 
addToFileQueue(wxString & fileName)6161 void MyFrame::addToFileQueue ( wxString& fileName )
6162 {
6163      fileQueue.push_back ( fileName );
6164 }
6165 
validatePaths()6166 void MyFrame::validatePaths()
6167 {
6168 	int invalid = 0;
6169 	wxString msg;
6170 
6171 	// Warning: Don't put a space between 'CHECK' and '('
6172 #define CHECK( check, path ) \
6173 	if ( !( check ) ( path ) )\
6174 	{\
6175 		invalid++;\
6176 		msg << wxTextFile::GetEOL() << path;\
6177 	}
6178 	CHECK ( wxDirExists, ruleSetDir );
6179 	//CHECK ( wxDirExists, filterDir );
6180 	CHECK ( wxDirExists, templateDir );
6181 	//CHECK ( wxDirExists, binDir );
6182 	CHECK ( wxDirExists, helpDir );
6183 	CHECK ( wxDirExists, rngDir );
6184 	//CHECK ( wxDirExists, htmlDir );
6185 	CHECK ( wxDirExists, pngDir );
6186 	//CHECK ( wxDirExists, daisyDir );
6187 	CHECK ( wxFileExists, catalogPath );
6188 	CHECK ( wxFileExists, xslDtdPath );
6189 	CHECK ( wxFileExists, rssDtdPath );
6190 	CHECK ( wxFileExists, xtmDtdPath );
6191 	CHECK ( wxFileExists, lzxDtdPath );
6192 	CHECK ( wxFileExists, xliffDtdPath );
6193 #ifdef __WXMSW__
6194 	CHECK ( wxDirExists, aspellDataPath );
6195 	CHECK ( wxDirExists, aspellDictPath );
6196 #endif // __WXMSW__
6197 #undef CHECK
6198 
6199 	if ( !invalid )
6200 		return;
6201 
6202 	msg = wxPLURAL ( "Invalid path: ", "Invalid paths: ", invalid ) + msg;
6203 	msg << wxTextFile::GetEOL()
6204 		<< wxTextFile::GetEOL()
6205 #ifdef __WXMSW__
6206 		<< _ ( "To change the application directory setting, click "
6207 			"Tools menu -> Options... after XML Copy Editor starts up." );
6208 #else
6209 		<< _ ( "To change the application directory setting, click "
6210 			"Edit menu -> Preferences... after XML Copy Editor starts up." );
6211 #endif
6212 	wxMessageBox ( msg, GetTitle(), wxOK | wxICON_ERROR, this );
6213 }
6214