1 /*
2  * Copyright 2014 Zane U. Ji.
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 "xmltextinfo.h"
22 
XmlTextInfo(const wxString & path,const char * encoding)23 XmlTextInfo::XmlTextInfo
24 	( const wxString &path
25 	, const char *encoding /*= NULL*/
26 	)
27 	: WrapExpat ( encoding )
28 {
29 	XML_SetUserData ( p, this );
30 	XML_SetBase ( p, path.utf8_str() );
31 	XML_SetDoctypeDeclHandler ( p, startdoctypehandler, NULL );
32 	XML_SetProcessingInstructionHandler ( p, processinghandler );
33 	XML_SetElementHandler ( p, start, NULL );
34 	XML_SetDefaultHandlerExpand ( p, defaulthandler );
35 }
36 
~XmlTextInfo()37 XmlTextInfo::~XmlTextInfo()
38 {
39 }
40 
startdoctypehandler(void * data,const XML_Char * doctypeName,const XML_Char * sysid,const XML_Char * pubid,int has_internal_subset)41 void XMLCALL XmlTextInfo::startdoctypehandler
42 	( void *data
43 	, const XML_Char *doctypeName
44 	, const XML_Char *sysid
45 	, const XML_Char *pubid
46 	, int has_internal_subset
47 	)
48 {
49 	XmlTextInfo *pThis = (XmlTextInfo *)data;
50 
51 	pThis->mDocTypeName = wxString::FromUTF8 ( doctypeName );
52 }
53 
processinghandler(void * data,const XML_Char * target,const XML_Char * datastring)54 void XMLCALL XmlTextInfo::processinghandler
55 	( void *data
56 	, const XML_Char *target
57 	, const XML_Char *datastring
58 	)
59 {
60 	XmlTextInfo *pThis = (XmlTextInfo *)data;
61 
62 	if ( strcmp ( target, "xml-stylesheet" ) )
63 		return;
64 
65 	char *href = strstr ( ( char * ) datastring, "href" );
66 	if ( !href )
67 		return;
68 	href += strlen ( "href" );
69 
70 	char ch = '"'; // Is '' or "" used?
71 	char *start = strchr ( href, ch);
72 	char *p = strchr ( href, '\'');
73 	if ( start == NULL
74 		|| ( p != NULL && start > p ) )
75 	{
76 		start = p;
77 		ch = '\'';
78 	}
79 	if ( !start++ )
80 		return;
81 	while ( isspace ( *start ) )
82 		start++;
83 
84 	char *end = strchr ( start, ch);
85 	if ( !end )
86 		return;
87 	while ( isspace ( end[-1] ) )
88 		end--;
89 
90 	pThis->mXslFile = wxString::FromUTF8 ( start, end - start );
91 }
92 
start(void * data,const XML_Char * el,const XML_Char ** attr)93 void XMLCALL XmlTextInfo::start
94 	( void *data
95 	, const XML_Char *el
96 	, const XML_Char **attr
97 	)
98 {
99 	XmlTextInfo *pThis = (XmlTextInfo *)data;
100 
101 	for ( ; *attr; attr += 2 )
102 	{
103 		if ( strstr ( *attr, ":noNamespaceSchemaLocation" ) )
104 		{
105 			pThis->mXsdFile = wxString::FromUTF8 ( attr[1] );
106 			break;
107 		}
108 		if ( strstr ( *attr, ":schemaLocation" ) )
109 		{ // TODO: Support multiple schemas
110 			std::string str ( attr[1] );
111 			char *p = strtok ( ( char * ) str.c_str(), " \t\r\n" );
112 			if ( !p )
113 				continue;
114 			p = strtok ( NULL, " \t\r\n" );
115 			if ( !p )
116 				continue;
117 			pThis->mXsdFile = wxString::FromUTF8 ( p );
118 			break;
119 		}
120 	}
121 
122 	pThis->mDocTypeName = wxString::FromUTF8 ( el );
123 
124 	XML_SetElementHandler ( pThis->p, NULL, NULL );
125 }
126 
defaulthandler(void * data,const XML_Char * s,int len)127 void XMLCALL XmlTextInfo::defaulthandler
128 	( void *data
129 	, const XML_Char *s
130 	, int len
131 	)
132 {
133 	XmlTextInfo *pThis = (XmlTextInfo *)data;
134 	const char *p = s;
135 	const char *end = s + len;
136 	while ( p < end && *p != '\r' )
137 		p++;
138 	if ( p < end )
139 	{
140 		if ( p + 1 < end && p[1] == '\n' )
141 			pThis->mEOL = _T ( "\r\n" );
142 		else
143 			pThis->mEOL = _T ( "\n" );
144 		XML_SetDefaultHandlerExpand ( pThis->p, NULL );
145 		return;
146 	}
147 
148 	p = s;
149 	while ( p < end && *p != '\r')
150 		p++;
151 	if ( p < end )
152 	{
153 		pThis->mEOL = _T ( "\n" );
154 		XML_SetDefaultHandlerExpand ( pThis->p, NULL );
155 	}
156 }
157