OSDN Git Service

Version: 0.4
[fontmanager/fontmanager.git] / fontsconf.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Takumi Asaki
4 ** All rights reserved.
5 ** Contact: Takumi Asaki (takumi.asaki@gmail.com)
6 **
7 ** This file is part of the fontmanager application.
8 **
9 ** You may use this file under the terms of the BSD license as follows:
10 **
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
13 ** met:
14 **   * Redistributions of source code must retain the above copyright
15 **     notice, this list of conditions and the following disclaimer.
16 **   * Redistributions in binary form must reproduce the above copyright
17 **     notice, this list of conditions and the following disclaimer in
18 **     the documentation and/or other materials provided with the
19 **     distribution.
20 **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
21 **     the names of its contributors may be used to endorse or promote
22 **     products derived from this software without specific prior written
23 **     permission.
24 **
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 **
37 ****************************************************************************/
38
39 #include "fontsconf.h"
40
41 #include "fontconfigdefs.h"
42 #include "fontsconfelement.h"
43
44 #include <QFile>
45 #include <QXmlStreamReader>
46
47 #include <QDebug>
48
49 enum FCState {
50     Initialized, Ready, InvalidConfig, UnknownState
51 };
52
53 static inline QString boolString(bool val)
54 {
55     return val ? TRUE_DEF : FALSE_DEF;
56 }
57
58 FontsConf::FontsConf(QObject *parent) :
59     QObject(parent), mModified(false), mHasUnknownConfig(false)
60 {
61     initFontsConf();
62 }
63
64 bool FontsConf::isEmpty() const
65 {
66     return !mElements || (mElements->count() == 0);
67 }
68
69 bool FontsConf::modified() const
70 {
71     return mModified;
72 }
73
74 bool FontsConf::hasUnknownConfig() const
75 {
76     return mHasUnknownConfig;
77 }
78
79 void FontsConf::initFontsConf()
80 {
81     if (mElements)
82         mModified = true;
83     FontsConfElementPointer rootElem(new FontsConfElement(FONTCONFIG_DEF, this));
84     mElements = rootElem;
85 }
86
87 bool FontsConf::parse(const QByteArray &buf)
88 {
89     if (buf.isEmpty())
90         return true;
91
92     QXmlStreamReader xml(buf);
93
94     FCState state = Initialized;
95
96     bool hasUnknownConfig = false;
97
98     FontsConfElementPointer elem;
99     while (!xml.atEnd()) {
100         QXmlStreamReader::TokenType token = xml.readNext();
101         if (token == QXmlStreamReader::DTD) {
102             if (xml.dtdName() != FONTCONFIG_DEF || xml.dtdSystemId() != "fonts.dtd") {
103                 state = InvalidConfig;
104             }
105         } else if (token == QXmlStreamReader::StartElement) {
106             QString elemName(xml.name().toString());
107             switch (state) {
108             case Initialized:
109                 if (elemName == FONTCONFIG_DEF) {
110                     state = Ready;
111                     elem = FontsConfElementPointer(new FontsConfElement(elemName, this));
112                     bool check = elem->parse(xml);
113                     if (!check)
114                         state = UnknownState;
115                 } else
116                     state = InvalidConfig;
117                 break;
118
119             default:
120                 ;
121             }
122         } else if (token == QXmlStreamReader::EndElement) {
123             QString elemName(xml.name().toString());
124         }
125
126         if (state == InvalidConfig)
127             qDebug("Invalid Config!!!");
128
129         if (state == InvalidConfig)
130             break;
131         else if (state == UnknownState)
132             hasUnknownConfig = true;
133     }
134
135     if (xml.error() != QXmlStreamReader::NoError)
136         state = InvalidConfig;
137
138     if (state == Ready) {
139         mElements = elem;
140         mModified = false;
141         mHasUnknownConfig = hasUnknownConfig;
142     }
143
144     return !(state == InvalidConfig);
145 }
146
147 QStringList FontsConf::preferFamily() const
148 {
149     if (!mElements)
150         return QStringList();
151
152     QStringList familyList;
153
154     int index = 0;
155     while ((index = mElements->indexOf(ALIAS_DEF, index)) >= 0) {
156         FontsConfElementPointer aliasElem = mElements->childElementAt(index++);
157         FontsConfElementPointer familyElem = aliasElem->childElementOf(FAMILY_DEF);
158         if (!familyElem || familyElem->text().isEmpty())
159             continue;
160         familyList << familyElem->text();
161     }
162     //    familyList.removeDuplicates();
163     return familyList;
164 }
165
166 QStringList FontsConf::aliasFamilyFor(const QString &family, const QString &mode) const
167 {
168     int index = 0;
169     while ((index = mElements->indexOf(ALIAS_DEF, index)) >= 0) {
170         FontsConfElementPointer aliasElem = mElements->childElementAt(index++);
171         FontsConfElementPointer familyElem = aliasElem->childElementOf(FAMILY_DEF);
172         if (!familyElem)
173             continue;
174         if (familyElem->text() != family)
175             continue;
176         FontsConfElementPointer targetElem = aliasElem->childElementOf(mode);
177         if (!targetElem)
178             return QStringList();
179         QStringList familyList = textElementList(targetElem, FAMILY_DEF);
180         return familyList;
181     }
182
183     return QStringList();
184 }
185
186 void FontsConf::appendAliasFamilyFor(const QString &family, const QString &mode, const QString &value)
187 {
188     int index = 0;
189     while ((index = mElements->indexOf(ALIAS_DEF, index)) >= 0) {
190         FontsConfElementPointer aliasElem = mElements->childElementAt(index++);
191         bool check = appendFamilyToAlias(aliasElem, family, mode, value);
192         if (check)
193             return;
194     }
195
196     FontsConfElementPointer aliasElem = aliasElementFor(family);
197     mElements->addChildElement(aliasElem);
198     bool check = appendFamilyToAlias(aliasElem, family, mode, value);
199     Q_ASSERT(check);
200 }
201
202 void FontsConf::removeAliasFamilyFor(const QString &family, const QString &mode, const QString &value)
203 {
204     int index = 0;
205     while ((index = mElements->indexOf(ALIAS_DEF, index)) >= 0) {
206         FontsConfElementPointer aliasElem = mElements->childElementAt(index++);
207
208         FontsConfElementPointer familyElem = aliasElem->childElementOf(FAMILY_DEF);
209         if (!familyElem || familyElem->text() != family)
210             continue;
211
212         FontsConfElementPointer targetElem = aliasElem->childElementOf(mode);
213         if (!targetElem || targetElem->count() == 0)
214             continue;
215
216         int findex = 0;
217         while ((findex = targetElem->indexOf(FAMILY_DEF, findex)) >= 0) {
218             if (targetElem->childElementAt(findex)->text() == value) {
219                 targetElem->removeAt(findex);
220                 mModified = true;
221                 continue;
222             }
223             findex++;
224         }
225
226         if (targetElem->count() == 0) {
227             aliasElem->removeOne(targetElem);
228             if (aliasElem->count() == 1) {
229                 mElements->removeOne(aliasElem);
230             }
231         }
232     }
233 }
234
235 QStringList FontsConf::preferFamilyFor(const QString &family) const
236 {
237     return aliasFamilyFor(family, PREFER_DEF);
238 }
239
240 void FontsConf::appendPreferFamilyFor(const QString &family, const QString &value)
241 {
242     appendAliasFamilyFor(family, PREFER_DEF, value);
243 }
244
245 void FontsConf::removePreferFamilyFor(const QString &family, const QString &value)
246 {
247     removeAliasFamilyFor(family, PREFER_DEF, value);
248 }
249
250 QStringList FontsConf::acceptFamilyFor(const QString &family) const
251 {
252     return aliasFamilyFor(family, ACCEPT_DEF);
253 }
254
255 void FontsConf::appendAcceptFamilyFor(const QString &family, const QString &value)
256 {
257     appendAliasFamilyFor(family, ACCEPT_DEF, value);
258 }
259
260 void FontsConf::removeAcceptFamilyFor(const QString &family, const QString &value)
261 {
262     removeAliasFamilyFor(family, ACCEPT_DEF, value);
263 }
264
265 QStringList FontsConf::matchFamilyFor(const QString &config, bool val) const
266 {
267     int index = 0;
268     while ((index = mElements->indexOf(MATCH_DEF, index)) >= 0) {
269         FontsConfElementPointer matchElem = mElements->childElementAt(index++);
270
271         bool check = isMatchElementFor(matchElem, config, QString(), boolString(val));
272         if (!check)
273             continue;
274
275         FontsConfElementPointer testElem = matchElem->childElementOf(TEST_DEF);
276         if (!testElem)
277             continue;
278
279         QStringList familyList = textElementList(testElem, STRING_DEF);
280         return familyList;
281     }
282
283     return QStringList();
284 }
285
286 QString FontsConf::matchEditValueFor(const QString &config, const QString &family) const
287 {
288     int index = 0;
289     while ((index = mElements->indexOf(MATCH_DEF, index)) >= 0) {
290         FontsConfElementPointer matchElem = mElements->childElementAt(index++);
291
292         bool check = isMatchElementFor(matchElem, config, family);
293         if (!check)
294             continue;
295
296         FontsConfElementPointer editElem = matchElem->childElementOf(EDIT_DEF);
297         if (!editElem)
298             continue;
299
300         FontsConfElementPointer boolElem = editElem->childElementOf(BOOL_DEF);
301         if (!boolElem)
302             continue;
303
304         return boolElem->text();
305     }
306
307     return QString();
308 }
309
310 void FontsConf::setMatchEditValueFor(const QString &config, const QString &family, bool val)
311 {
312     FontsConfElementPointer matchElem;
313     int index = 0;
314     while ((index = mElements->indexOf(MATCH_DEF, index)) >= 0) {
315         FontsConfElementPointer elem = mElements->childElementAt(index++);
316         bool check = isMatchElementFor(elem, config, QString(), boolString(val));
317         if (check) {
318             matchElem = elem;
319             break;
320         }
321     }
322
323     if (!matchElem) {
324         matchElem = matchElementFor(config, val);
325         mElements->addChildElement(matchElem);
326         mModified = true;
327     }
328
329     FontsConfElementPointer testElem = matchElem->childElementOf(TEST_DEF);
330     QStringList familyList = textElementList(testElem, STRING_DEF);
331     if (familyList.contains(family))
332         return;
333
334     FontsConfElementPointer stringElem(new FontsConfElement(STRING_DEF));
335     stringElem->setText(family);
336     testElem->addChildElement(stringElem);
337     mModified = true;
338 }
339
340 void FontsConf::unsetMatchEditValueFor(const QString &config, const QString &family)
341 {
342     int index = 0;
343     while ((index = mElements->indexOf(MATCH_DEF, index)) >= 0) {
344         FontsConfElementPointer matchElem = mElements->childElementAt(index++);
345
346         bool check = isMatchElementFor(matchElem, config, family);
347         if (!check)
348             continue;
349
350         FontsConfElementPointer testElem = matchElem->childElementOf(TEST_DEF);
351         int sindex = 0;
352         while ((sindex = testElem->indexOf(STRING_DEF, sindex)) >= 0) {
353             FontsConfElementPointer stringElem = testElem->childElementAt(sindex++);
354             if (stringElem->text() == family) {
355                 testElem->removeAt(--sindex);
356                 mModified = true;
357             }
358         }
359
360         if (testElem->count() == 0) {
361             mElements->removeAt(--index);
362         }
363
364     }
365 }
366
367 QStringList FontsConf::patternFamilyFor(const QString &family, const QString &mode) const
368 {
369     int index = 0;
370     while ((index = mElements->indexOf(MATCH_DEF, index)) >= 0) {
371         FontsConfElementPointer matchElem = mElements->childElementAt(index++);
372         bool check = isPatternElementFor(matchElem, family, mode);
373         if (!check)
374             continue;
375         FontsConfElementPointer editElem = getEditPatternElementFor(matchElem, family, mode);
376         return textElementList(editElem, STRING_DEF);
377     }
378     return QStringList();
379 }
380
381 void FontsConf::appendPatternFamilyFor(const QString &family, const QString &mode, const QString &value)
382 {
383     FontsConfElementPointer matchElem;
384
385     int index = 0;
386     while ((index = mElements->indexOf(MATCH_DEF, index)) >= 0) {
387         FontsConfElementPointer elem = mElements->childElementAt(index++);
388         bool check = isPatternElementFor(elem, family, mode);
389         if (check) {
390             matchElem = elem;
391             break;
392         }
393     }
394
395     if (!matchElem) {
396         int index = 0;
397         while ((index = mElements->indexOf(MATCH_DEF, index)) >= 0) {
398             FontsConfElementPointer elem = mElements->childElementAt(index++);
399             bool check = isPatternElementFor(elem, family);
400             if (check) {
401                 matchElem = elem;
402                 break;
403             }
404         }
405     }
406
407     if (!matchElem) {
408         matchElem = patternElementFor(family);
409         mElements->addChildElement(matchElem);
410         mModified = true;
411     }
412
413     FontsConfElementPointer editElem = getEditPatternElementFor(matchElem, family, mode);
414     if (!editElem) {
415         editElem = FontsConfElementPointer(new FontsConfElement(EDIT_DEF));
416         editElem->setAttribute(NAME_DEF, FAMILY_DEF);
417         editElem->setAttribute(MODE_DEF, mode);
418         editElem->setAttribute(BINDING_DEF, STRONG_DEF);
419         matchElem->addChildElement(editElem);
420         mModified = true;
421     }
422
423     QStringList familyList = textElementList(editElem, STRING_DEF);
424     if (familyList.contains(value))
425         return;
426
427     FontsConfElementPointer stringElem(new FontsConfElement(STRING_DEF));
428     stringElem->setText(value);
429     editElem->addChildElement(stringElem);
430     mModified = true;
431 }
432
433 void FontsConf::removePatternFamilyFor(const QString &family, const QString &mode, const QString &value)
434 {
435     FontsConfElementPointer matchElem;
436
437     int index = 0;
438     while ((index = mElements->indexOf(MATCH_DEF, index)) >= 0) {
439         FontsConfElementPointer elem = mElements->childElementAt(index++);
440         bool check = isPatternElementFor(elem, family, mode);
441         if (check) {
442             matchElem = elem;
443             break;
444         }
445     }
446
447     if (!matchElem)
448         return;
449
450     FontsConfElementPointer editElem = getEditPatternElementFor(matchElem, family, mode);
451     if (!editElem)
452         return;
453
454     int sindex = 0;
455     while ((sindex = editElem->indexOf(STRING_DEF, sindex)) >= 0) {
456         FontsConfElementPointer stringElem = editElem->childElementAt(sindex++);
457         if (stringElem->text() == value) {
458             editElem->removeAt(--sindex);
459             mModified = true;
460         }
461     }
462
463     if (editElem->count() == 0) {
464         mModified = true;
465         matchElem->removeOne(editElem);
466         FontsConfElementList editElemList = matchElem->findChildrenElements(EDIT_DEF);
467         if (editElemList.isEmpty())
468             mElements->removeOne(matchElem);
469     }
470
471 }
472
473 QStringList FontsConf::prependFamilyFor(const QString &family) const
474 {
475     return patternFamilyFor(family, PREPEND_DEF);
476 }
477
478 void FontsConf::appendPrependFamilyFor(const QString &family, const QString &value)
479 {
480     appendPatternFamilyFor(family, PREPEND_DEF, value);
481 }
482
483 void FontsConf::removePrependFamilyFor(const QString &family, const QString &value)
484 {
485     removePatternFamilyFor(family, PREPEND_DEF, value);
486 }
487
488 QStringList FontsConf::appendFamilyFor(const QString &family) const
489 {
490     return patternFamilyFor(family, APPEND_DEF);
491 }
492
493 void FontsConf::appendAppendFamilyFor(const QString &family, const QString &value)
494 {
495     appendPatternFamilyFor(family, APPEND_DEF, value);
496 }
497
498 void FontsConf::removeAppendFamilyFor(const QString &family, const QString &value)
499 {
500     removePatternFamilyFor(family, APPEND_DEF, value);
501 }
502
503 QStringList FontsConf::genericFamilies()
504 {
505     static QStringList families;
506     if (families.isEmpty())
507         families << SANSSERIF_DEF << SERIF_DEF << MONOSPACE_DEF;
508     return families;
509 }
510
511 QStringList FontsConf::configKeys()
512 {
513     static QStringList keys;
514     if (keys.isEmpty())
515         keys << EMBEDDEDBITMAP_DEF << HINTING_DEF << ANTIALIAS_DEF << AUTOHINT_DEF;
516     return keys;
517 }
518
519 void FontsConf::load(const QString &path)
520 {
521     QFile fp(path);
522     if (!fp.exists())
523         return;
524
525     fp.open(QIODevice::ReadOnly);
526     if (!fp.isOpen() || fp.error() != QFile::NoError)
527         return;
528
529     QByteArray buf = fp.readAll();
530
531     fp.close();
532
533     bool check = parse(buf);
534     Q_UNUSED(check);
535
536 }
537
538 void FontsConf::save(const QString &path)
539 {
540 #if 0
541     if (!mElements && fp.exists()) {
542         fp.remove();
543         return;
544     }
545 #endif
546
547     QString buf;
548     QXmlStreamWriter xml(&buf);
549
550     xml.setAutoFormatting(true);
551
552     xml.writeStartDocument();
553
554     xml.writeDTD("<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>");
555
556     if (mElements)
557         mElements->save(xml);
558
559     xml.writeEndDocument();
560
561     QFile fp(path);
562     fp.open(QIODevice::WriteOnly);
563     if (!fp.isOpen())
564         return;
565
566     QTextStream ts(&fp);
567     ts.setCodec("UTF-8");
568     ts << buf;
569
570     mModified = false;
571
572     fp.close();
573 }
574
575 bool FontsConf::appendFamilyToAlias(FontsConfElementPointer aliasElem, const QString &family, const QString &mode, const QString &value)
576 {
577     if (aliasElem->type() != ALIAS_DEF)
578         return false;
579
580     FontsConfElementPointer familyElem = aliasElem->childElementOf(FAMILY_DEF);
581     if (!familyElem || familyElem->text() != family)
582         return false;
583
584     FontsConfElementPointer targetElem = aliasElem->childElementOf(mode);
585     if (!targetElem) {
586         targetElem = FontsConfElementPointer(new FontsConfElement(mode));
587         aliasElem->addChildElement(targetElem);
588         mModified = true;
589     }
590
591     int findex = 0;
592     while ((findex = targetElem->indexOf(FAMILY_DEF, findex)) >= 0) {
593         if (targetElem->childElementAt(findex)->text() == value)
594             return true;
595         findex++;
596     }
597
598     FontsConfElementPointer valueElem(new FontsConfElement(FAMILY_DEF));
599     valueElem->setText(value);
600     targetElem->addChildElement(valueElem);
601     mModified = true;
602
603     return true;
604 }
605
606 bool FontsConf::isMatchElementFor(FontsConfElementPointer matchElem, const QString &config, const QString &family, const QString &val) const
607 {
608     if (!matchElem->hasAttribute(TARGET_DEF) || matchElem->value(TARGET_DEF) != FONT_DEF)
609         return false;
610
611     FontsConfElementList testElemList = matchElem->findChildrenElements(TEST_DEF);
612     if (testElemList.count() != 1)
613         return false;
614
615     FontsConfElementPointer testElem = testElemList.at(0);
616     if (!testElem->hasAttribute(NAME_DEF) || testElem->value(NAME_DEF) != FAMILY_DEF)
617         return false;
618     if ((testElem->hasAttribute(QUAL_DEF) && testElem->value(QUAL_DEF) != ANY_DEF) ||
619             (testElem->hasAttribute(COMPARE_DEF) && testElem->value(COMPARE_DEF) != EQ_DEF) ||
620             (testElem->hasAttribute(TARGET_DEF) && testElem->value(TARGET_DEF) != DEFAULT_DEF))
621         return false;
622
623     if (!family.isEmpty()) {
624         if (testElem->count() == 0 && testElem->text() != family)
625             return false;
626         QStringList familyList = textElementList(testElem, STRING_DEF);
627         if (!familyList.contains(family))
628             return false;
629     }
630
631     FontsConfElementList editElemList = matchElem->findChildrenElements(EDIT_DEF);
632     if (editElemList.count() != 1)
633         return false;
634
635     FontsConfElementPointer editElem = editElemList.at(0);
636     if ((!editElem->hasAttribute(NAME_DEF) || editElem->value(NAME_DEF) != config) ||
637             (editElem->hasAttribute(MODE_DEF) && editElem->value(MODE_DEF) != ASSIGN_DEF))
638         return false;
639
640     FontsConfElementList boolElemList = editElem->findChildrenElements(BOOL_DEF);
641     if (boolElemList.count() != 1) {
642         return false;
643     }
644
645     if (!val.isEmpty()) {
646         FontsConfElementPointer boolElem = boolElemList.at(0);
647         if (boolElem->text() != val)
648             return false;
649     }
650
651     return true;
652 }
653
654 bool FontsConf::isPatternElementFor(FontsConfElementPointer matchElem, const QString &family, const QString &mode) const
655 {
656     if (matchElem->hasAttribute(TARGET_DEF) && matchElem->value(TARGET_DEF) != PATTERN_DEF)
657         return false;
658
659     FontsConfElementList testElemList = matchElem->findChildrenElements(TEST_DEF);
660     if (testElemList.count() != 1)
661         return false;
662
663     FontsConfElementPointer testElem = testElemList.at(0);
664     if (testElem->hasAttribute(NAME_DEF) && testElem->value(NAME_DEF) != FAMILY_DEF)
665         return false;
666     if ((testElem->hasAttribute(COMPARE_DEF) && testElem->value(COMPARE_DEF) != EQ_DEF) ||
667             (testElem->hasAttribute(TARGET_DEF) && testElem->value(TARGET_DEF) != DEFAULT_DEF))
668         return false;
669
670     if (testElem->count() == 0) {
671         if (testElem->text().isEmpty() || testElem->text() != family)
672             return false;
673     } else {
674         QStringList familyList = textElementList(testElem, STRING_DEF);
675         if (familyList.count() != 1 || !familyList.contains(family))
676             return false;
677     }
678
679     if (mode.isEmpty())
680         return true;
681
682     int eindex = 0;
683     while ((eindex = matchElem->indexOf(EDIT_DEF, eindex)) >= 0) {
684         FontsConfElementPointer editElem = matchElem->childElementAt(eindex++);
685
686         if ((editElem->hasAttribute(NAME_DEF) && editElem->value(NAME_DEF) == FAMILY_DEF) &&
687                 (editElem->hasAttribute(MODE_DEF) && editElem->value(MODE_DEF) == mode))
688             return true;
689
690     }
691
692     return false;
693 }
694
695 FontsConfElementPointer FontsConf::getEditPatternElementFor(FontsConfElementPointer matchElem, const QString &family, const QString &mode) const
696 {
697     Q_UNUSED(family);
698     int eindex = 0;
699     while ((eindex = matchElem->indexOf(EDIT_DEF, eindex)) >= 0) {
700         FontsConfElementPointer editElem = matchElem->childElementAt(eindex++);
701
702         if ((editElem->hasAttribute(NAME_DEF) && editElem->value(NAME_DEF) == FAMILY_DEF) &&
703                 (editElem->hasAttribute(MODE_DEF) && editElem->value(MODE_DEF) == mode))
704             return editElem;
705     }
706     return FontsConfElementPointer();
707 }
708
709 bool FontsConf::containsTextElement(FontsConfElementPointer elem, const QString &tag, const QString &text) const
710 {
711     int index = 0;
712     while ((index = elem->indexOf(tag, index)) >= 0) {
713         FontsConfElementPointer e = elem->childElementAt(index++);
714         if (e->text() == text)
715             return true;
716     }
717     return false;
718 }
719
720 QStringList FontsConf::textElementList(FontsConfElementPointer elem, const QString &tag) const
721 {
722     if (!elem)
723         return QStringList();
724     QStringList list;
725     int index = 0;
726     while ((index = elem->indexOf(tag, index)) >= 0) {
727         FontsConfElementPointer e = elem->childElementAt(index++);
728         if (!e->text().isEmpty())
729             list << e->text();
730     }
731     return list;
732 }
733
734 FontsConfElementPointer FontsConf::aliasElementFor(const QString &family) const
735 {
736     FontsConfElementPointer aliasElem(new FontsConfElement(ALIAS_DEF));
737     FontsConfElementPointer familyElem(new FontsConfElement(FAMILY_DEF));
738     familyElem->setText(family);
739     aliasElem->addChildElement(familyElem);
740     return aliasElem;
741 }
742
743 FontsConfElementPointer FontsConf::matchElementFor(const QString &config, bool val) const
744 {
745     FontsConfElementPointer matchElem = FontsConfElementPointer(new FontsConfElement(MATCH_DEF));
746     matchElem->setAttribute(TARGET_DEF, FONT_DEF);
747
748     FontsConfElementPointer testElem(new FontsConfElement(TEST_DEF));
749     testElem->setAttribute(QUAL_DEF, ANY_DEF);
750     testElem->setAttribute(NAME_DEF, FAMILY_DEF);
751     matchElem->addChildElement(testElem);
752
753     FontsConfElementPointer editElem(new FontsConfElement(EDIT_DEF));
754     editElem->setAttribute(NAME_DEF, config);
755     editElem->setAttribute(MODE_DEF, ASSIGN_DEF);
756     matchElem->addChildElement(editElem);
757
758     FontsConfElementPointer boolElem(new FontsConfElement(BOOL_DEF));
759     boolElem->setText(boolString(val));
760     editElem->addChildElement(boolElem);
761
762     return matchElem;
763 }
764
765 FontsConfElementPointer FontsConf::patternElementFor(const QString &family) const
766 {
767     FontsConfElementPointer matchElem = FontsConfElementPointer(new FontsConfElement(MATCH_DEF));
768     matchElem->setAttribute(TARGET_DEF, PATTERN_DEF);
769
770     FontsConfElementPointer testElem(new FontsConfElement(TEST_DEF));
771     testElem->setAttribute(QUAL_DEF, ANY_DEF);
772     testElem->setAttribute(NAME_DEF, FAMILY_DEF);
773     matchElem->addChildElement(testElem);
774
775     FontsConfElementPointer stringElem(new FontsConfElement(STRING_DEF));
776     stringElem->setText(family);
777     testElem->addChildElement(stringElem);
778
779     return matchElem;
780 }