]> git.lyx.org Git - features.git/blob - src/lyxparagraph.h
05bc96d3ce894485cbef21a7f6df3003cb10a1e6
[features.git] / src / lyxparagraph.h
1 // -*- C++ -*-
2 /* This file is part of
3  * ====================================================== 
4  * 
5  *           LyX, The Document Processor
6  *       
7  *          Copyright 1995 Matthias Ettrich
8  *          Copyright 1995-2000 The LyX Team.
9  *
10  * ====================================================== */
11
12 #ifndef LYXPARAGRAPH_H
13 #define LYXPARAGRAPH_H
14
15 #ifdef __GNUG__
16 #pragma interface
17 #endif
18
19 #include "LString.h"
20
21 #include <vector>
22 #include <list>
23 #include <boost/array.hpp>
24
25 #include "insets/lyxinset.h"
26 #include "ParagraphParameters.h"
27 #include "support/LAssert.h"
28
29 class BufferParams;
30 class LyXBuffer;
31 class TexRow;
32 struct LaTeXFeatures;
33 class InsetBibKey;
34 class BufferView;
35 class Language;
36
37 // I dare you to enable this and help me find all the bugs that then show
38 // up. (Lgb)
39 #define NEW_INSETS 1
40 #define NO_PEXTRA 1
41
42 /// A LyXParagraph holds all text, attributes and insets in a text paragraph
43 class LyXParagraph  {
44 public:
45 #ifndef NO_PEXTRA_REALLY
46         ///
47         enum PEXTRA_TYPE {
48                 ///
49                 PEXTRA_NONE,
50                 ///
51                 PEXTRA_INDENT,
52                 ///
53                 PEXTRA_MINIPAGE,
54                 ///
55                 PEXTRA_FLOATFLT
56         };
57         ///
58         enum MINIPAGE_ALIGNMENT {
59                 ///
60                 MINIPAGE_ALIGN_TOP,
61                 ///
62                 MINIPAGE_ALIGN_MIDDLE,
63                 ///
64                 MINIPAGE_ALIGN_BOTTOM
65         };
66 #endif
67         ///
68         enum META_KIND {
69                 ///
70                 META_HFILL = 1,
71                 ///
72                 META_NEWLINE,
73                 ///
74                 META_INSET
75         };
76         ///
77         typedef char value_type;
78         ///
79         typedef std::vector<value_type> TextContainer;
80         ///
81         /* This should be TextContainer::size_type, but we need
82            signed values for now.
83         */
84         typedef TextContainer::difference_type size_type;
85
86         ///
87         LyXParagraph();
88         /// this constructor inserts the new paragraph in a list
89         explicit
90         LyXParagraph(LyXParagraph * par);
91         ///
92         LyXParagraph(LyXParagraph const &);
93         /// the destructor removes the new paragraph from the list
94         ~LyXParagraph();
95
96         ///
97         Language const * getParLanguage(BufferParams const &) const;
98         ///
99         bool isRightToLeftPar(BufferParams const &) const;
100         ///
101         void ChangeLanguage(BufferParams const & bparams,
102                             Language const * from, Language const * to);
103         ///
104         bool isMultiLingual(BufferParams const &);
105         ///
106
107         string const String(Buffer const *, bool label);
108         ///
109         string const String(Buffer const *, size_type beg, size_type end);
110         
111         ///
112         void writeFile(Buffer const *, std::ostream &, BufferParams const &,
113                        char) const;
114         ///
115         void validate(LaTeXFeatures &) const;
116         
117         ///
118         int id() const;
119         ///
120         void id(int id_arg);
121         ///
122         void read();
123
124         ///
125         LyXParagraph * TeXOnePar(Buffer const *, BufferParams const &,
126                                  std::ostream &, TexRow & texrow,
127                                  bool moving_arg);
128         ///
129         bool SimpleTeXOnePar(Buffer const *, BufferParams const &,
130                              std::ostream &, TexRow & texrow, bool moving_arg);
131
132         ///
133         LyXParagraph * TeXEnvironment(Buffer const *, BufferParams const &,
134                                       std::ostream &, TexRow & texrow);
135         ///
136         bool HasSameLayout(LyXParagraph const * par) const;
137         
138         ///
139         void MakeSameLayout(LyXParagraph const * par);
140
141         /// Is it the first par with same depth and layout?
142         bool IsFirstInSequence() const;
143
144         /** Check if the current paragraph is the last paragraph in a
145             proof environment */
146         int GetEndLabel(BufferParams const &) const;
147         ///
148         Inset * InInset();
149         ///
150         void SetInsetOwner(Inset * i);
151         ///
152         void deleteInsetsLyXText(BufferView *);
153         ///
154         void resizeInsetsLyXText(BufferView *);
155 private:
156         ///
157         TextContainer text;
158         ///
159         Inset * inset_owner;
160
161 public:
162         ///
163         inline
164         size_type size() const;
165         ///
166         void fitToSize();
167         ///
168         void setContentsFromPar(LyXParagraph * par);
169         ///
170         void clearContents();
171
172         ParagraphParameters params;
173         
174         ///
175         LyXTextClass::LayoutList::size_type layout;
176 private:
177         ///
178         boost::array<int, 10> counter_;
179 public:
180         ///
181         void setCounter(int i, int v);
182         ///
183         int getCounter(int i) const;
184         ///
185         void incCounter(int i);
186
187         ///
188         char enumdepth;
189         
190         ///
191         char itemdepth;
192 private:
193         ///
194         LyXParagraph * next_;
195         ///
196         LyXParagraph * previous_;
197 public:
198         /// 
199         InsetBibKey * bibkey;  // ale970302
200
201         ///
202         void next(LyXParagraph *);
203         /** these function are able to hide closed footnotes
204          */
205         LyXParagraph * next();
206         ///
207         LyXParagraph const * next() const;
208
209         ///
210         void previous(LyXParagraph *);
211         ///
212         LyXParagraph * previous();
213         ///
214         LyXParagraph const * previous() const;
215
216         /// for the environments
217         LyXParagraph * DepthHook(int depth);
218         /// for the environments
219         LyXParagraph const * DepthHook(int depth) const;
220         ///
221         int BeginningOfMainBody() const;
222         ///
223         string const & GetLabelstring() const;
224         
225         /// the next two functions are for the manual labels
226         string const GetLabelWidthString() const;
227         ///
228         void SetLabelWidthString(string const & s);
229         ///
230         inline
231         LyXTextClass::LayoutList::size_type GetLayout() const;
232         ///
233         char GetAlign() const;
234         ///
235         char GetDepth() const;
236         ///
237         void SetLayout(LyXTextClass::LayoutList::size_type new_layout);
238         ///
239         void SetOnlyLayout(LyXTextClass::LayoutList::size_type new_layout);
240         ///
241         int GetFirstCounter(int i) const;
242         ///
243         void Erase(size_type pos);
244         /** the flag determines wether the layout should be copied
245          */ 
246         void BreakParagraph(BufferParams const &, size_type pos, int flag);
247         ///
248         void BreakParagraphConservative(BufferParams const &, size_type pos);
249         /** Get unistantiated font setting. Returns the difference
250             between the characters font and the layoutfont.
251             This is what is stored in the fonttable
252         */
253         LyXFont const
254         GetFontSettings(BufferParams const &, size_type pos) const;
255         ///
256         LyXFont const GetFirstFontSettings() const;
257
258         /** Get fully instantiated font. If pos == -1, use the layout
259             font attached to this paragraph.
260             If pos == -2, use the label font of the layout attached here.
261             In all cases, the font is instantiated, i.e. does not have any
262             attributes with values LyXFont::INHERIT, LyXFont::IGNORE or 
263             LyXFont::TOGGLE.
264         */
265         LyXFont const getFont(BufferParams const &, size_type pos) const;
266         ///
267         value_type GetChar(size_type pos) const;
268         ///
269         value_type GetUChar(BufferParams const &, size_type pos) const;
270         /// The position must already exist.
271         void SetChar(size_type pos, value_type c);
272         ///
273         void SetFont(size_type pos, LyXFont const & font);
274         ///
275         string const GetWord(size_type &) const;
276         /// Returns the height of the highest font in range
277         LyXFont::FONT_SIZE HighestFontInRange(size_type startpos,
278                                               size_type endpos) const;
279         ///
280         void InsertChar(size_type pos, value_type c);
281         ///
282         void InsertChar(size_type pos, value_type c, LyXFont const &);
283         ///
284         void InsertInset(size_type pos, Inset * inset);
285         ///
286         void InsertInset(size_type pos, Inset * inset, LyXFont const &);
287         ///
288         bool InsertInsetAllowed(Inset * inset);
289         ///
290         Inset * GetInset(size_type pos);
291         ///
292         Inset const * GetInset(size_type pos) const;
293         /** important for cut and paste
294             Temporary change from BufferParams to Buffer. Will revert when we
295             get rid of the argument to Inset::Clone(Buffer const &) */
296         void CopyIntoMinibuffer(Buffer const &, size_type pos) const;
297         ///
298         void CutIntoMinibuffer(BufferParams const &, size_type pos);
299         ///
300         bool InsertFromMinibuffer(size_type pos);
301
302         ///
303         bool IsHfill(size_type pos) const;
304         ///
305         bool IsInset(size_type pos) const;
306         ///
307         bool IsNewline(size_type pos) const;
308         ///
309         bool IsSeparator(size_type pos) const;
310         ///
311         bool IsLineSeparator(size_type pos) const;
312         ///
313         bool IsKomma(size_type pos) const;
314         /// Used by the spellchecker
315         bool IsLetter(size_type pos) const;
316         /// 
317         bool IsWord(size_type pos) const;
318
319         /** This one resets all layout and dtp switches but not the font
320             of the single characters
321         */ 
322         void Clear();
323
324         /** paste this paragraph with the next one
325             be carefull, this doesent make any check at all
326         */ 
327         void PasteParagraph(BufferParams const &);
328
329         /// used to remove the error messages
330         int AutoDeleteInsets();
331
332         /// returns -1 if inset not found
333         int GetPositionOfInset(Inset * inset) const;
334
335         ///
336         int StripLeadingSpaces(LyXTextClassList::size_type tclass); 
337
338 #ifndef NO_PEXTRA_REALLY
339         /* If I set a PExtra Indent on one paragraph of a ENV_LIST-TYPE
340            I have to set it on each of it's elements */
341         ///
342         void SetPExtraType(BufferParams const &, int type,
343                            string const & width, string const & widthp);
344         ///
345         void UnsetPExtraType(BufferParams const &);
346 #endif
347         ///
348         bool linuxDocConvertChar(char c, string & sgml_string);
349 private:
350         ///
351         struct InsetTable {
352                 ///
353                 size_type pos;
354                 ///
355                 Inset * inset;
356                 ///
357                 InsetTable(size_type p, Inset * i) : pos(p), inset(i) {}
358         };
359         ///
360         friend struct matchIT;
361         ///
362         struct matchIT {
363                 /// used by lower_bound and upper_bound
364                 inline
365                 int operator()(LyXParagraph::InsetTable const & a,
366                                LyXParagraph::InsetTable const & b) const {
367                         return a.pos < b.pos;
368                 }
369         };
370         /** A font entry covers a range of positions. Notice that the
371             entries in the list are inserted in random order.
372             I don't think it's worth the effort to implement a more effective
373             datastructure, because the number of different fonts in a paragraph
374             is limited. (Asger)
375             Nevertheless, I decided to store fontlist using a sorted vector:
376             fontlist = { {pos_1,font_1} , {pos_2,font_2} , ... } where
377             pos_1 < pos_2 < ..., font_{i-1} != font_i for all i,
378             and font_i covers the chars in positions pos_{i-1}+1,...,pos_i
379             (font_1 covers the chars 0,...,pos_1) (Dekel)
380         */
381         struct FontTable  {
382                 ///
383                 FontTable(size_type p, LyXFont const & f)
384                         : pos_(p)
385                         {
386                                 font_ = container.get(f);
387                         }
388                 ///
389                 size_type pos() const { return pos_; }
390                 ///
391                 void pos(size_type p) { pos_ = p; }
392                 ///
393                 LyXFont const & font() const { return *font_; }
394                 ///
395                 void font(LyXFont const & f) { font_ = container.get(f);}
396         private:
397                 /// End position of paragraph this font attribute covers
398                 size_type pos_;
399                 /** Font. Interpretation of the font values:
400                     If a value is LyXFont::INHERIT_*, it means that the font 
401                     attribute is inherited from either the layout of this
402                     paragraph or, in the case of nested paragraphs, from the 
403                     layout in the environment one level up until completely 
404                     resolved.
405                     The values LyXFont::IGNORE_* and LyXFont::TOGGLE are NOT 
406                     allowed in these font tables.
407                 */
408                 boost::shared_ptr<LyXFont> font_;
409                 ///
410                 static ShareContainer<LyXFont> container;
411         };
412         ///
413         friend struct matchFT;
414         ///
415         struct matchFT {
416                 /// used by lower_bound and upper_bound
417                 inline
418                 int operator()(LyXParagraph::FontTable const & a,
419                                LyXParagraph::FontTable const & b) const {
420                         return a.pos() < b.pos();
421                 }
422         };
423
424         ///
425         typedef std::vector<FontTable> FontList;
426         ///
427         FontList fontlist;
428         ///
429         typedef std::vector<InsetTable> InsetList;
430         ///
431         InsetList insetlist;
432         ///
433         LyXParagraph * TeXDeeper(Buffer const *, BufferParams const &,
434                                  std::ostream &, TexRow & texrow);
435         ///
436         void SimpleTeXBlanks(std::ostream &, TexRow & texrow,
437                              size_type const i,
438                              int & column, LyXFont const & font,
439                              LyXLayout const & style);
440         ///
441         void SimpleTeXSpecialChars(Buffer const *, BufferParams const &,
442                                    std::ostream &, TexRow & texrow,
443                                    bool moving_arg,
444                                    LyXFont & font, LyXFont & running_font,
445                                    LyXFont & basefont, bool & open_font,
446                                    LyXLayout const & style,
447                                    size_type & i,
448                                    int & column, value_type const c);
449         ///
450         unsigned int id_;
451         ///
452         static unsigned int paragraph_id;
453 public:
454         ///
455         class inset_iterator {
456         public:
457                 ///
458                 inset_iterator() {}
459                 //
460                 inset_iterator(InsetList::iterator const & iter) : it(iter) {};
461                 ///
462                 inset_iterator & operator++() {
463                         ++it;
464                         return *this;
465                 }
466                 ///
467                 Inset * operator*() { return (*it).inset; }
468                 ///
469                 size_type getPos() const {return (*it).pos; }
470                 ///
471                 bool operator==(inset_iterator const & iter) const {
472                         return it == iter.it;
473                 }
474                 ///
475                 bool operator!=(inset_iterator const & iter) const {
476                         return it != iter.it;
477                 }
478         private:
479                 ///
480                 InsetList::iterator it;
481         };
482         ///
483         inset_iterator inset_iterator_begin();
484         ///
485         inset_iterator inset_iterator_end();
486         ///
487         inset_iterator InsetIterator(size_type pos);
488 };
489
490
491 inline
492 LyXParagraph::size_type LyXParagraph::size() const
493 {
494         return text.size();
495 }
496
497
498 inline
499 LyXParagraph::value_type
500 LyXParagraph::GetChar(LyXParagraph::size_type pos) const
501 {
502         lyx::Assert(pos <= size());
503         // This is stronger, and I belive that this is the assertion
504         // that we should really use. (Lgb)
505         //Assert(pos < size());
506
507         // Then this has no meaning. (Lgb)
508         if (!size() || pos == size()) return '\0';
509         
510         return text[pos];
511 }
512
513
514 inline
515 int LyXParagraph::id() const
516 {
517         return id_;
518 }
519
520
521 inline
522 void  LyXParagraph::id(int id_arg)
523 {
524         id_ = id_arg;
525 }
526
527
528 inline
529 LyXTextClass::size_type LyXParagraph::GetLayout() const
530 {
531         return layout;
532 }
533
534
535 inline
536 bool LyXParagraph::IsFirstInSequence() const
537 {
538         LyXParagraph const * dhook = DepthHook(GetDepth());
539         return (dhook == this
540                 || dhook->GetLayout() != GetLayout()
541                 || dhook->GetDepth() != GetDepth());
542 }
543
544
545 inline
546 Inset * LyXParagraph::InInset()
547 {
548         return inset_owner;
549 }
550
551
552 inline
553 void LyXParagraph::clearContents()
554 {
555         text.clear();
556 }
557
558
559 inline
560 void LyXParagraph::setCounter(int i, int v)
561 {
562         counter_[i] = v;
563 }
564
565
566 inline
567 int LyXParagraph::getCounter(int i) const
568 {
569         return counter_[i];
570 }
571
572
573 inline
574 void LyXParagraph::incCounter(int i)
575 {
576         counter_[i]++;
577 }
578
579
580 inline
581 void LyXParagraph::SetChar(size_type pos, value_type c)
582 {
583         text[pos] = c;
584 }
585
586
587 inline
588 LyXParagraph::inset_iterator LyXParagraph::inset_iterator_begin()
589 {
590         return inset_iterator(insetlist.begin());
591 }
592
593
594 inline
595 LyXParagraph::inset_iterator LyXParagraph::inset_iterator_end()
596 {
597         return inset_iterator(insetlist.end());
598 }
599 #endif