]> git.lyx.org Git - lyx.git/blob - src/FontList.cpp
0c38c03e5d957f9f2987640043087ec7286df07f
[lyx.git] / src / FontList.cpp
1 /**
2  * \file FontList.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Asger Alstrup
7  * \author Lars Gullik Bjønnes
8  * \author Jean-Marc Lasgouttes
9  * \author Angus Leeming
10  * \author John Levon
11  * \author André Pönitz
12  * \author Dekel Tsur
13  * \author Jürgen Vigna
14  * \author Abdelrazak Younes
15  *
16  * Full author contact details are available in file CREDITS.
17  */
18
19 #include <config.h>
20
21 #include "FontList.h"
22
23 #include <boost/next_prior.hpp>
24
25 #include <algorithm>
26
27 using namespace std;
28
29 namespace lyx {
30
31
32 FontList::iterator FontList::fontIterator(pos_type pos)
33 {
34         FontList::iterator it = list_.begin();
35         FontList::iterator end = list_.end();
36         for (; it != end; ++it) {
37                 if (it->pos() >= pos)
38                         break;
39         }
40         return it;
41 }
42
43
44 FontList::const_iterator FontList::fontIterator(pos_type pos) const
45 {
46         FontList::const_iterator it = list_.begin();
47         FontList::const_iterator end = list_.end();
48         for (; it != end; ++it) {
49                 if (it->pos() >= pos)
50                         break;
51         }
52         return it;
53 }
54
55
56 Font & FontList::get(pos_type pos)
57 {
58         iterator end = list_.end();
59         iterator it = fontIterator(pos);
60         if (it != end && it->pos() == pos)
61                 return it->font_;
62         static Font dummy;
63         return dummy;
64 }
65
66
67 void FontList::erase(pos_type pos)
68 {
69         // Erase entries in the tables.
70         iterator it = fontIterator(pos);
71         iterator beg = list_.begin();
72         if (it != list_.end() && it->pos() == pos
73                 && (pos == 0 
74                         || (it != list_.begin() && boost::prior(it)->pos() == pos - 1))) {
75
76                 // If it is a multi-character font
77                 // entry, we just make it smaller
78                 // (see update below), otherwise we
79                 // should delete it.
80                 unsigned int const i = it - list_.begin();
81                 list_.erase(it);
82                 if (i >= list_.size())
83                         return;
84                 it = list_.begin() + i;
85                 if (i > 0 && i < list_.size() &&
86                     list_[i - 1].font() == list_[i].font()) {
87                         list_.erase(beg + i - 1);
88                         it = list_.begin() + i - 1;
89                 }
90         }
91
92         // Update all other entries
93         iterator end = list_.end();
94         for (; it != end; ++it)
95                 it->pos(it->pos() - 1);
96 }
97
98 void FontList::increasePosAfterPos(pos_type pos)
99 {
100         List::iterator end = list_.end();
101         List::iterator it = fontIterator(pos);
102         for (; it != end; ++it)
103                 ++it->pos_;
104 }
105
106
107 void FontList::decreasePosAfterPos(pos_type pos)
108 {
109         List::iterator end = list_.end();
110         List::iterator it = fontIterator(pos);
111         for (; it != end; ++it)
112                 --it->pos_;
113 }
114
115
116 void FontList::setRange(pos_type startpos, pos_type endpos, Font const & font)
117 {
118         // FIXME: Optimize!!!
119         for (pos_type pos = startpos; pos != endpos; ++pos)
120                 set(pos, font);
121 }
122
123
124 void FontList::set(pos_type pos, Font const & font)
125 {
126         // No need to simplify this because it will disappear
127         // in a new kernel. (Asger)
128         // Next search font table
129
130         List::iterator it = fontIterator(pos);
131         bool const found = it != list_.end();
132         if (found && it->font() == font)
133                 // Font is already set.
134                 return;
135
136         size_t const i = distance(list_.begin(), it);
137
138         // Is position pos a beginning of a font block?
139         bool const begin = pos == 0 || !found 
140                 || (i > 0 && list_[i - 1].pos() == pos - 1);
141
142         // Is position pos at the end of a font block?
143         bool const end = found && list_[i].pos() == pos;
144
145         if (!begin && !end) {
146                 // The general case: The block is splitted into 3 blocks
147                 list_.insert(list_.begin() + i,
148                                 FontTable(pos - 1, list_[i].font()));
149                 list_.insert(list_.begin() + i + 1,
150                                 FontTable(pos, font));
151                 return;
152         }
153
154         if (begin && end) {
155                 // A single char block
156                 if (i + 1 < list_.size() &&
157                     list_[i + 1].font() == font) {
158                         // Merge the singleton block with the next block
159                         list_.erase(list_.begin() + i);
160                         if (i > 0 && list_[i - 1].font() == font)
161                                 list_.erase(list_.begin() + i - 1);
162                 } else if (i > 0 && list_[i - 1].font() == font) {
163                         // Merge the singleton block with the previous block
164                         list_[i - 1].pos(pos);
165                         list_.erase(list_.begin() + i);
166                 } else
167                         list_[i].font(font);
168         } else if (begin) {
169                 if (i > 0 && list_[i - 1].font() == font)
170                         list_[i - 1].pos(pos);
171                 else
172                         list_.insert(list_.begin() + i,
173                                         FontTable(pos, font));
174         } else if (end) {
175                 list_[i].pos(pos - 1);
176                 if (!(i + 1 < list_.size() &&
177                       list_[i + 1].font() == font))
178                         list_.insert(list_.begin() + i + 1,
179                                         FontTable(pos, font));
180         }
181 }
182
183
184 FontSize FontList::highestInRange(pos_type startpos, pos_type endpos,
185         FontSize def_size) const
186 {
187         if (list_.empty())
188                 return def_size;
189
190         List::const_iterator end_it = fontIterator(endpos);
191         const_iterator const end = list_.end();
192         if (end_it != end)
193                 ++end_it;
194
195         List::const_iterator cit = fontIterator(startpos);
196
197         FontSize maxsize = FONT_SIZE_TINY;
198         for (; cit != end_it; ++cit) {
199                 FontSize size = cit->font().fontInfo().size();
200                 if (size == FONT_SIZE_INHERIT)
201                         size = def_size;
202                 if (size > maxsize && size <= FONT_SIZE_HUGER)
203                         maxsize = size;
204         }
205         return maxsize;
206 }
207
208
209 bool FontList::hasChangeInRange(pos_type pos, int len) const
210 {
211         List::const_iterator cit = fontIterator(pos);
212         return cit == list_.end() || pos + len - 1 <= cit->pos();
213 }
214
215
216 void FontList::validate(LaTeXFeatures & features) const
217 {
218         const_iterator fcit = list_.begin();
219         const_iterator fend = list_.end();
220         for (; fcit != fend; ++fcit)
221                 fcit->font().validate(features);
222 }
223
224 } // namespace lyx