1 /* -*- c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- */
2 /* AbiWord
3  * Copyright (C) 2004 Hubert Figuiere
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301 USA.
19  */
20 
21 
22 /* This file implements RTF parsing routines */
23 
24 #include "ut_debugmsg.h"
25 
26 #include "ie_imp_RTF.h"
27 #include "ie_imp_RTFParse.h"
28 #include "ie_imp_RTFKeywords.h"
29 
30 
31 bool
tokenError(IE_Imp_RTF *)32 IE_Imp_RTFGroupParser::tokenError(IE_Imp_RTF * /*ie*/)
33 {
34 //	UT_ASSERT_NOT_REACHED();
35 	UT_DEBUGMSG(("tokenError() reached\n"));
36 	return true;
37 }
38 
39 
40 bool
tokenKeyword(IE_Imp_RTF *,RTF_KEYWORD_ID,UT_sint32,bool)41 IE_Imp_RTFGroupParser::tokenKeyword(IE_Imp_RTF * /*ie*/, RTF_KEYWORD_ID /*kwID*/,
42 									UT_sint32 /*param*/, bool /*paramUsed*/)
43 {
44 	return true;
45 }
46 
47 bool
tokenOpenBrace(IE_Imp_RTF *)48 IE_Imp_RTFGroupParser::tokenOpenBrace(IE_Imp_RTF * /*ie*/)
49 {
50 	m_nested++;
51 	return true;
52 }
53 
54 
55 bool
tokenCloseBrace(IE_Imp_RTF *)56 IE_Imp_RTFGroupParser::tokenCloseBrace(IE_Imp_RTF * /*ie*/)
57 {
58 	m_nested--;
59 	return true;
60 }
61 
62 
63 bool
tokenData(IE_Imp_RTF *,UT_UTF8String &)64 IE_Imp_RTFGroupParser::tokenData(IE_Imp_RTF * /*ie*/, UT_UTF8String & /*data*/)
65 {
66 	return true;
67 }
68 
69 
70 bool
finalizeParse(void)71 IE_Imp_RTFGroupParser::finalizeParse(void)
72 {
73 	return true;
74 }
75 
76 
77 bool IE_Imp_RTF::keywordSorted = false;
78 
kwsortcomparator(const void * v1,const void * v2)79 static int kwsortcomparator(const void *v1, const void *v2)
80 {
81 	return strcmp(((const _rtf_keyword *)v1)->keyword,
82 				  ((const _rtf_keyword *)v2)->keyword);
83 }
84 
85 
_initialKeywordSort(void)86 void IE_Imp_RTF::_initialKeywordSort(void)
87 {
88 	UT_DEBUGMSG(("RTF: initial sorting of keywords..."));
89 	qsort (const_cast<_rtf_keyword*>(rtfKeywords),
90 		   sizeof (rtfKeywords) / sizeof(_rtf_keyword) ,
91 		   sizeof(_rtf_keyword), &kwsortcomparator);
92 	IE_Imp_RTF::keywordSorted = true;
93 	UT_DEBUGMSG(("done.\n"));
94 }
95 
96 
97 // Pushes the current state RTF state onto the state stack
98 //
PushRTFState(void)99 bool IE_Imp_RTF::PushRTFState(void)
100 {
101 	xxx_UT_DEBUGMSG(("Push RTF state \n"));
102 	// Create a new object to store the state in
103 	RTFStateStore* pState = new RTFStateStore;
104 	if (pState == NULL)	{
105 	    UT_DEBUGMSG(("PushRTFState(): no state\n"));
106 	    return false;
107 	}
108 	*pState = m_currentRTFState;
109 	m_stateStack.push(pState);
110 
111 	// Reset the current state
112 	m_currentRTFState.m_internalState = RTFStateStore::risNorm;
113 	return true;
114 }
115 
116 
117 
118 // Pops the state off the top of the RTF stack and set the current state to it.
119 //
PopRTFState(void)120 bool IE_Imp_RTF::PopRTFState(void)
121 {
122 	xxx_UT_DEBUGMSG(("Pop RTF state depth %d \n",m_stateStack.getDepth()));
123 	RTFStateStore* pState = NULL;
124 	m_stateStack.pop(reinterpret_cast<void**>(&pState));
125 
126 	if (pState != NULL)	{
127 		bool ok = FlushStoredChars();
128 		m_currentRTFState = *pState;
129 		delete pState;
130 
131 		m_currentRTFState.m_unicodeInAlternate = 0;
132 		return ok;
133 	}
134 	else {
135 		UT_DEBUGMSG(("RTF ERROR: pState is NULL! Will try to recover."));
136 		return false;
137 	}
138 }
139 
140 
141 /*!
142   This is the standard keyword parser
143 
144   \param parser the IE_Imp_RTFGroupParser subclass that will do the
145   real syntaxic parsing.
146 */
147 bool
StandardKeywordParser(IE_Imp_RTFGroupParser * parser)148 IE_Imp_RTF::StandardKeywordParser(IE_Imp_RTFGroupParser *parser)
149 {
150 	RTFTokenType tokenType;
151 	unsigned char keyword[MAX_KEYWORD_LEN];
152 	UT_sint32 parameter = 0;
153 	bool paramUsed = false;
154 	RTF_KEYWORD_ID keywordID;
155 	bool finalBrace = false;
156 
157 	do
158 	{
159 		tokenType = NextToken (keyword, &parameter, &paramUsed,
160 							   MAX_KEYWORD_LEN,false);
161 		switch (tokenType)
162 		{
163 		case RTF_TOKEN_ERROR:
164 			return parser->tokenError(this);
165 			break;
166 		case RTF_TOKEN_KEYWORD:
167 		{
168 			xxx_UT_DEBUGMSG(("IE_Imp_RTF::StandardKeywordParser() %s\n", keyword));
169 			keywordID = KeywordToID(reinterpret_cast<char *>(keyword));
170 			parser->tokenKeyword(this, keywordID, parameter, paramUsed);
171 			break;
172 		}
173 		case RTF_TOKEN_OPEN_BRACE:
174 			UT_DEBUGMSG(("Nesting %d ++ <%p>\n", parser->nested(), parser));
175 			parser->tokenOpenBrace(this);
176 			break;
177 		case RTF_TOKEN_CLOSE_BRACE:
178 			parser->tokenCloseBrace(this);
179 			UT_DEBUGMSG(("Nesting %d -- <%p>\n", parser->nested(), parser));
180 			// oh oh we catched the last brace from the group
181 			if (parser->nested() == 0) {
182 				finalBrace = true;
183 			}
184 			break;
185 		case RTF_TOKEN_DATA:	//Ignore data
186 		{
187 			SkipBackChar(*keyword);
188 			UT_UTF8String data;
189 			HandlePCData(data);
190 			parser->tokenData(this, data);
191 			break;
192 		}
193 		default:
194 			break;
195 		}
196 	} while (!finalBrace);
197 
198 	/*
199 	   we must put it back into the flow because we are only supposed to
200 	   handle the content of the group.
201 	 */
202 	SkipBackChar('}');
203 	return parser->finalizeParse();
204 }
205 
206 
207 
208 
209 /*!
210   Comparator for keyword bsearch
211 */
kwcompar(const void * v1,const void * v2)212 static int kwcompar(const void * v1, const void* v2)
213 {
214 	const char *kw = (const char *)v1;
215 	const _rtf_keyword *kwelem = (const _rtf_keyword *)v2;
216 	return strcmp(kw, kwelem->keyword);
217 }
218 
219 /*!
220   Return the keyword ID for the given keyword
221 
222 
223 */
KeywordToID(const char * keyword)224 RTF_KEYWORD_ID IE_Imp_RTF::KeywordToID(const char * keyword)
225 {
226 	const _rtf_keyword *kwelem  = (_rtf_keyword *)bsearch (keyword,
227 					   rtfKeywords,
228 					   sizeof(rtfKeywords) / sizeof(rtfKeywords[0]),
229 					   sizeof(rtfKeywords[0]), &kwcompar);
230 	if (kwelem) {
231 		return kwelem->id;
232 	}
233 	return RTF_UNKNOWN_KEYWORD;
234 }
235 
236 
237 
238