1 /* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */
2
3 /* AbiSource
4 *
5 * Copyright (C) 2009 Firat Kiyak <firatkiyak@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301 USA.
21 */
22
23 // Class definition include
24 #include <OXMLi_ListenerState_Numbering.h>
25
26 // Internal includes
27 #include <OXML_Document.h>
28 #include <OXML_FontManager.h>
29 #include <OXML_Types.h>
30 #include <OXML_List.h>
31
32 // AbiWord includes
33 #include <ut_assert.h>
34 #include <ut_misc.h>
35
36 // External includes
37 #include <string>
38
OXMLi_ListenerState_Numbering()39 OXMLi_ListenerState_Numbering::OXMLi_ListenerState_Numbering():
40 OXMLi_ListenerState(),
41 m_currentList(NULL),
42 m_currentNumId(""),
43 m_parentListId("")
44 {
45
46 }
47
startElement(OXMLi_StartElementRequest * rqst)48 void OXMLi_ListenerState_Numbering::startElement (OXMLi_StartElementRequest * rqst)
49 {
50 if (
51 nameMatches(rqst->pName, NS_W_KEY, "numbering") ||
52 nameMatches(rqst->pName, NS_W_KEY, "multiLevelType") ||
53 nameMatches(rqst->pName, NS_W_KEY, "name") ||
54 nameMatches(rqst->pName, NS_W_KEY, "nsid") ||
55 nameMatches(rqst->pName, NS_W_KEY, "numStyleLink") ||
56 nameMatches(rqst->pName, NS_W_KEY, "styleLink") ||
57 nameMatches(rqst->pName, NS_W_KEY, "tmpl") ||
58 nameMatches(rqst->pName, NS_W_KEY, "isLgl") ||
59 nameMatches(rqst->pName, NS_W_KEY, "legacy") ||
60 nameMatches(rqst->pName, NS_W_KEY, "lvlJc") ||
61 nameMatches(rqst->pName, NS_W_KEY, "lvlPicBulletId") ||
62 nameMatches(rqst->pName, NS_W_KEY, "lvlRestart") ||
63 nameMatches(rqst->pName, NS_W_KEY, "suff")
64 )
65 {
66 //TODO: add functionality here
67 rqst->handled = true;
68 }
69 else if(nameMatches(rqst->pName, NS_W_KEY, "abstractNum"))
70 {
71 const gchar* abstractNumId = attrMatches(NS_W_KEY, "abstractNumId", rqst->ppAtts);
72 if(abstractNumId)
73 {
74 m_parentListId = std::string("1");
75 m_parentListId += abstractNumId;
76 }
77 rqst->handled = true;
78 }
79 else if(nameMatches(rqst->pName, NS_W_KEY, "lvl"))
80 {
81 const gchar* ilvl = attrMatches(NS_W_KEY, "ilvl", rqst->ppAtts);
82 if(ilvl)
83 {
84 handleLevel(ilvl);
85 }
86 rqst->handled = true;
87 }
88 else if(nameMatches(rqst->pName, NS_W_KEY, "start"))
89 {
90 const gchar* val = attrMatches(NS_W_KEY, "val", rqst->ppAtts);
91 if(val && m_currentList)
92 {
93 m_currentList->setStartValue(atoi(val));
94 }
95 rqst->handled = true;
96 }
97 else if(nameMatches(rqst->pName, NS_W_KEY, "numFmt"))
98 {
99 const gchar* val = attrMatches(NS_W_KEY, "val", rqst->ppAtts);
100 if(val)
101 {
102 handleFormattingType(val);
103 }
104 rqst->handled = true;
105 }
106 else if(nameMatches(rqst->pName, NS_W_KEY, "lvlText"))
107 {
108 const gchar* val = attrMatches(NS_W_KEY, "val", rqst->ppAtts);
109 if(val && m_currentList)
110 {
111 std::string delim(val);
112 m_currentList->setDelim(delim);
113 }
114 rqst->handled = true;
115 }
116 else if(nameMatches(rqst->pName, NS_W_KEY, "num"))
117 {
118 const gchar* numId = attrMatches(NS_W_KEY, "numId", rqst->ppAtts);
119 if(numId)
120 {
121 m_currentNumId = std::string(numId);
122 }
123 rqst->handled = true;
124 }
125 else if(nameMatches(rqst->pName, NS_W_KEY, "abstractNumId"))
126 {
127 const gchar* val = attrMatches(NS_W_KEY, "val", rqst->ppAtts);
128 if(val && !m_currentNumId.empty())
129 {
130 std::string abstractNumId("1"); //starts at 10 instead of zero
131 abstractNumId += val;
132 OXML_Document* doc = OXML_Document::getInstance();
133 if(doc)
134 doc->setMappedNumberingId(m_currentNumId, abstractNumId);
135 }
136 rqst->handled = true;
137 }
138 else if(nameMatches(rqst->pName, NS_W_KEY, "pPr"))
139 {
140 //insert a dummy paragraph element to stack
141 //so that we can collect the properties from common listener
142 OXML_SharedElement dummy(new OXML_Element_Paragraph(""));
143 rqst->stck->push(dummy);
144 rqst->handled = true;
145 }
146 else if(nameMatches(rqst->pName, NS_W_KEY, "rPr"))
147 {
148 OXML_SharedElement dummy(new OXML_Element_Run(""));
149 rqst->stck->push(dummy);
150 rqst->handled = true;
151 }
152 }
153
endElement(OXMLi_EndElementRequest * rqst)154 void OXMLi_ListenerState_Numbering::endElement (OXMLi_EndElementRequest * rqst)
155 {
156 if (
157 nameMatches(rqst->pName, NS_W_KEY, "numbering") ||
158 nameMatches(rqst->pName, NS_W_KEY, "abstractNum") ||
159 nameMatches(rqst->pName, NS_W_KEY, "multiLevelType") ||
160 nameMatches(rqst->pName, NS_W_KEY, "name") ||
161 nameMatches(rqst->pName, NS_W_KEY, "nsid") ||
162 nameMatches(rqst->pName, NS_W_KEY, "numStyleLink") ||
163 nameMatches(rqst->pName, NS_W_KEY, "styleLink") ||
164 nameMatches(rqst->pName, NS_W_KEY, "tmpl") ||
165 nameMatches(rqst->pName, NS_W_KEY, "isLgl") ||
166 nameMatches(rqst->pName, NS_W_KEY, "legacy") ||
167 nameMatches(rqst->pName, NS_W_KEY, "lvlJc") ||
168 nameMatches(rqst->pName, NS_W_KEY, "lvlPicBulletId") ||
169 nameMatches(rqst->pName, NS_W_KEY, "lvlRestart") ||
170 nameMatches(rqst->pName, NS_W_KEY, "lvlText") ||
171 nameMatches(rqst->pName, NS_W_KEY, "numFmt") ||
172 nameMatches(rqst->pName, NS_W_KEY, "start") ||
173 nameMatches(rqst->pName, NS_W_KEY, "suff") ||
174 nameMatches(rqst->pName, NS_W_KEY, "abstractNumId")
175 )
176 {
177 //TODO: add functionality here
178 rqst->handled = true;
179 }
180 else if(nameMatches(rqst->pName, NS_W_KEY, "lvl"))
181 {
182 OXML_Document * doc = OXML_Document::getInstance();
183 if(!doc)
184 {
185 doc = OXML_Document::getNewInstance();
186 }
187 OXML_SharedList sharedList(m_currentList);
188 doc->addList(sharedList);
189 m_currentList = NULL;
190 rqst->handled = true;
191 }
192 else if(nameMatches(rqst->pName, NS_W_KEY, "num"))
193 {
194 m_currentNumId.clear(); //set it to empty string
195 rqst->handled = true;
196 }
197 else if(nameMatches(rqst->pName, NS_W_KEY, "pPr") ||
198 nameMatches(rqst->pName, NS_W_KEY, "rPr"))
199 {
200 if(rqst->stck->empty())
201 {
202 rqst->handled = false;
203 rqst->valid = false;
204 return;
205 }
206 OXML_SharedElement dummy = rqst->stck->top();
207
208 if(m_currentList)
209 {
210 m_currentList->setAttributes(dummy->getAttributes());
211 m_currentList->setProperties(dummy->getProperties());
212 }
213 rqst->stck->pop(); //remove the dummy element
214 rqst->handled = true;
215 }
216 }
217
charData(OXMLi_CharDataRequest *)218 void OXMLi_ListenerState_Numbering::charData (OXMLi_CharDataRequest * /*rqst*/)
219 {
220 //don't do anything here
221 }
222
223
224 //private helper functions
225
226
227 /**
228 * Handles the new level tag in the form <lvl ilvl="3">
229 */
handleLevel(const gchar * ilvl)230 void OXMLi_ListenerState_Numbering::handleLevel(const gchar* ilvl)
231 {
232 m_currentList = new OXML_List();
233 m_currentList->setLevel(atoi(ilvl)+1); //levels start with index 1
234 //create a new list with the list id and parent id
235 //all lists are encoded as id=parentId+ilvl
236 std::string listId(m_parentListId);
237 listId += ilvl;
238 m_currentList->setId(atoi(listId.c_str()));
239 if(!strcmp(ilvl, "0"))
240 {
241 //this is the first level
242 m_currentList->setParentId(0); //no parent
243 }
244 else
245 {
246 std::string parentListId(m_parentListId);
247 parentListId += ('0'+(atoi(ilvl)-1));
248 m_currentList->setParentId(atoi(parentListId.c_str())); //has parent (ilvl-1)
249 }
250 }
251
handleFormattingType(const gchar * val)252 void OXMLi_ListenerState_Numbering::handleFormattingType(const gchar* val)
253 {
254 if(!m_currentList)
255 return;
256
257 if(!strcmp(val, "decimal"))
258 m_currentList->setType(NUMBERED_LIST);
259 else if(!strcmp(val, "lowerLetter"))
260 m_currentList->setType(LOWERCASE_LIST);
261 else if(!strcmp(val, "upperLetter"))
262 m_currentList->setType(UPPERCASE_LIST);
263 else if(!strcmp(val, "lowerRoman"))
264 m_currentList->setType(LOWERROMAN_LIST);
265 else if(!strcmp(val, "upperRoman"))
266 m_currentList->setType(UPPERROMAN_LIST);
267 else if(!strcmp(val, "aravicAbjad"))
268 m_currentList->setType(ARABICNUMBERED_LIST);
269 else if(!strcmp(val, "hebrew1"))
270 m_currentList->setType(HEBREW_LIST);
271 else //default
272 m_currentList->setType(BULLETED_LIST);
273 //TODO: add more types here
274 }
275
276