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, ¶meter, ¶mUsed,
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