]> git.lyx.org Git - lyx.git/blob - src/lyxparagraph.h
1c09a72024d8adf7d069ec63b32aded0d82e5e53
[lyx.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, 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 #if 0
136         ///
137         LyXParagraph * Clone() const;
138 #endif
139         ///
140         bool HasSameLayout(LyXParagraph const * par) const;
141         
142         ///
143         void MakeSameLayout(LyXParagraph const * par);
144
145         /// Is it the first par with same depth and layout?
146         bool IsFirstInSequence() const;
147
148         /** Check if the current paragraph is the last paragraph in a
149             proof environment */
150         int GetEndLabel(BufferParams const &) const;
151         ///
152         Inset * InInset();
153         ///
154         void SetInsetOwner(Inset * i);
155         ///
156         void deleteInsetsLyXText(BufferView *);
157         ///
158         void resizeInsetsLyXText(BufferView *);
159 private:
160         ///
161         TextContainer text;
162         ///
163         Inset * inset_owner;
164
165 public:
166         ///
167         inline
168         size_type size() const;
169         ///
170         void fitToSize();
171         ///
172         void setContentsFromPar(LyXParagraph * par);
173         ///
174         void clearContents();
175
176         ParagraphParameters params;
177         
178         ///
179         LyXTextClass::LayoutList::size_type layout;
180 private:
181         ///
182         boost::array<int, 10> counter_;
183 public:
184         ///
185         void setCounter(int i, int v);
186         ///
187         int getCounter(int i) const;
188         ///
189         void incCounter(int i);
190
191         ///
192         char enumdepth;
193         
194         ///
195         char itemdepth;
196 private:
197         ///
198         LyXParagraph * next_;
199         ///
200         LyXParagraph * previous_;
201 public:
202         /// 
203         InsetBibKey * bibkey;  // ale970302
204
205         ///
206         void next(LyXParagraph *);
207         /** these function are able to hide closed footnotes
208          */
209         LyXParagraph * next();
210         ///
211         LyXParagraph const * next() const;
212
213         ///
214         void previous(LyXParagraph *);
215         ///
216         LyXParagraph * previous();
217         ///
218         LyXParagraph const * previous() const;
219
220         /// for the environments
221         LyXParagraph * DepthHook(int depth);
222         /// for the environments
223         LyXParagraph const * DepthHook(int depth) const;
224         ///
225         int BeginningOfMainBody() const;
226         ///
227         string const & GetLabelstring() const;
228         
229         /// the next two functions are for the manual labels
230         string const GetLabelWidthString() const;
231         ///
232         void SetLabelWidthString(string const & s);
233         ///
234         inline
235         LyXTextClass::LayoutList::size_type GetLayout() const;
236         ///
237         char GetAlign() const;
238         ///
239         char GetDepth() const;
240         ///
241         void SetLayout(LyXTextClass::LayoutList::size_type new_layout);
242         ///
243         void SetOnlyLayout(LyXTextClass::LayoutList::size_type new_layout);
244         ///
245         int GetFirstCounter(int i) const;
246         ///
247         void Erase(size_type pos);
248         /** the flag determines wether the layout should be copied
249          */ 
250         void BreakParagraph(BufferParams const &, size_type pos, int flag);
251         ///
252         void BreakParagraphConservative(BufferParams const &, size_type pos);
253         /** Get unistantiated font setting. Returns the difference
254             between the characters font and the layoutfont.
255             This is what is stored in the fonttable
256         */
257         LyXFont const
258         GetFontSettings(BufferParams const &, size_type pos) const;
259         ///
260         LyXFont const GetFirstFontSettings() const;
261
262         /** Get fully instantiated font. If pos == -1, use the layout
263             font attached to this paragraph.
264             If pos == -2, use the label font of the layout attached here.
265             In all cases, the font is instantiated, i.e. does not have any
266             attributes with values LyXFont::INHERIT, LyXFont::IGNORE or 
267             LyXFont::TOGGLE.
268         */
269         LyXFont const getFont(BufferParams const &, size_type pos) const;
270         ///
271         value_type GetChar(size_type pos) const;
272         ///
273         value_type GetUChar(BufferParams const &, size_type pos) const;
274         /// The position must already exist.
275         void SetChar(size_type pos, value_type c);
276         ///
277         void SetFont(size_type pos, LyXFont const & font);
278         ///
279         string const GetWord(size_type &) const;
280         /// Returns the height of the highest font in range
281         LyXFont::FONT_SIZE HighestFontInRange(size_type startpos,
282                                               size_type endpos) const;
283         ///
284         void InsertChar(size_type pos, value_type c);
285         ///
286         void InsertChar(size_type pos, value_type c, LyXFont const &);
287         ///
288         void InsertInset(size_type pos, Inset * inset);
289         ///
290         void InsertInset(size_type pos, Inset * inset, LyXFont const &);
291         ///
292         bool InsertInsetAllowed(Inset * inset);
293         ///
294         Inset * GetInset(size_type pos);
295         ///
296         Inset const * GetInset(size_type pos) const;
297         /** important for cut and paste
298             Temporary change from BufferParams to Buffer. Will revert when we
299             get rid of the argument to Inset::Clone(Buffer const &) */
300         void CopyIntoMinibuffer(Buffer const &, size_type pos) const;
301         ///
302         void CutIntoMinibuffer(BufferParams const &, size_type pos);
303         ///
304         bool InsertFromMinibuffer(size_type pos);
305
306         ///
307         bool IsHfill(size_type pos) const;
308         ///
309         bool IsInset(size_type pos) const;
310         ///
311         bool IsNewline(size_type pos) const;
312         ///
313         bool IsSeparator(size_type pos) const;
314         ///
315         bool IsLineSeparator(size_type pos) const;
316         ///
317         bool IsKomma(size_type pos) const;
318         /// Used by the spellchecker
319         bool IsLetter(size_type pos) const;
320         /// 
321         bool IsWord(size_type pos) const;
322
323         /** This one resets all layout and dtp switches but not the font
324             of the single characters
325         */ 
326         void Clear();
327
328         /** paste this paragraph with the next one
329             be carefull, this doesent make any check at all
330         */ 
331         void PasteParagraph(BufferParams const &);
332
333         /// used to remove the error messages
334         int AutoDeleteInsets();
335
336         /// returns -1 if inset not found
337         int GetPositionOfInset(Inset * inset) const;
338
339         ///
340         int StripLeadingSpaces(LyXTextClassList::size_type tclass); 
341
342 #ifndef NO_PEXTRA_REALLY
343         /* If I set a PExtra Indent on one paragraph of a ENV_LIST-TYPE
344            I have to set it on each of it's elements */
345         ///
346         void SetPExtraType(BufferParams const &, int type,
347                            string const & width, string const & widthp);
348         ///
349         void UnsetPExtraType(BufferParams const &);
350 #endif
351         ///
352         bool linuxDocConvertChar(char c, string & sgml_string);
353 private:
354         ///
355         struct InsetTable {
356                 ///
357                 size_type pos;
358                 ///
359                 Inset * inset;
360                 ///
361                 InsetTable(size_type p, Inset * i) : pos(p), inset(i) {}
362         };
363         ///
364         friend struct matchIT;
365         ///
366         struct matchIT {
367                 /// used by lower_bound and upper_bound
368                 inline
369                 int operator()(LyXParagraph::InsetTable const & a,
370                                LyXParagraph::InsetTable const & b) const {
371                         return a.pos < b.pos;
372                 }
373         };
374         /** A font entry covers a range of positions. Notice that the
375             entries in the list are inserted in random order.
376             I don't think it's worth the effort to implement a more effective
377             datastructure, because the number of different fonts in a paragraph
378             is limited. (Asger)
379             Nevertheless, I decided to store fontlist using a sorted vector:
380             fontlist = { {pos_1,font_1} , {pos_2,font_2} , ... } where
381             pos_1 < pos_2 < ..., font_{i-1} != font_i for all i,
382             and font_i covers the chars in positions pos_{i-1}+1,...,pos_i
383             (font_1 covers the chars 0,...,pos_1) (Dekel)
384         */
385         struct FontTable  {
386                 ///
387                 FontTable(size_type p, LyXFont const & f)
388                         : pos_(p)
389                         {
390                                 font_ = container.get(f);
391                         }
392                 ///
393                 size_type pos() const { return pos_; }
394                 ///
395                 void pos(size_type p) { pos_ = p; }
396                 ///
397                 LyXFont const & font() const { return *font_; }
398                 ///
399                 void font(LyXFont const & f) { font_ = container.get(f);}
400         private:
401                 /// End position of paragraph this font attribute covers
402                 size_type pos_;
403                 /** Font. Interpretation of the font values:
404                     If a value is LyXFont::INHERIT_*, it means that the font 
405                     attribute is inherited from either the layout of this
406                     paragraph or, in the case of nested paragraphs, from the 
407                     layout in the environment one level up until completely 
408                     resolved.
409                     The values LyXFont::IGNORE_* and LyXFont::TOGGLE are NOT 
410                     allowed in these font tables.
411                 */
412                 boost::shared_ptr<LyXFont> font_;
413                 ///
414                 static ShareContainer<LyXFont> container;
415         };
416         ///
417         friend struct matchFT;
418         ///
419         struct matchFT {
420                 /// used by lower_bound and upper_bound
421                 inline
422                 int operator()(LyXParagraph::FontTable const & a,
423                                LyXParagraph::FontTable const & b) const {
424                         return a.pos() < b.pos();
425                 }
426         };
427
428         ///
429         typedef std::vector<FontTable> FontList;
430         ///
431         FontList fontlist;
432         ///
433         typedef std::vector<InsetTable> InsetList;
434         ///
435         InsetList insetlist;
436         ///
437         LyXParagraph * TeXDeeper(Buffer const *, BufferParams const &,
438                                  std::ostream &, TexRow & texrow);
439         ///
440         void SimpleTeXBlanks(std::ostream &, TexRow & texrow,
441                              size_type const i,
442                              int & column, LyXFont const & font,
443                              LyXLayout const & style);
444         ///
445         void SimpleTeXSpecialChars(Buffer const *, BufferParams const &,
446                                    std::ostream &, TexRow & texrow,
447                                    bool moving_arg,
448                                    LyXFont & font, LyXFont & running_font,
449                                    LyXFont & basefont, bool & open_font,
450                                    LyXLayout const & style,
451                                    size_type & i,
452                                    int & column, value_type const c);
453         ///
454         unsigned int id_;
455         ///
456         static unsigned int paragraph_id;
457 public:
458         ///
459         class inset_iterator {
460         public:
461                 ///
462                 inset_iterator() {}
463                 //
464                 inset_iterator(InsetList::iterator const & iter) : it(iter) {};
465                 ///
466                 inset_iterator & operator++() {
467                         ++it;
468                         return *this;
469                 }
470                 ///
471                 Inset * operator*() { return (*it).inset; }
472                 ///
473                 size_type getPos() const {return (*it).pos; }
474                 ///
475                 bool operator==(inset_iterator const & iter) const {
476                         return it == iter.it;
477                 }
478                 ///
479                 bool operator!=(inset_iterator const & iter) const {
480                         return it != iter.it;
481                 }
482         private:
483                 ///
484                 InsetList::iterator it;
485         };
486         ///
487         inset_iterator inset_iterator_begin();
488         ///
489         inset_iterator inset_iterator_end();
490         ///
491         inset_iterator InsetIterator(size_type pos);
492 };
493
494
495 inline
496 LyXParagraph::size_type LyXParagraph::size() const
497 {
498         return text.size();
499 }
500
501
502 inline
503 LyXParagraph::value_type
504 LyXParagraph::GetChar(LyXParagraph::size_type pos) const
505 {
506         lyx::Assert(pos <= size());
507         // This is stronger, and I belive that this is the assertion
508         // that we should really use. (Lgb)
509         //Assert(pos < size());
510
511         // Then this has no meaning. (Lgb)
512         if (!size() || pos == size()) return '\0';
513         
514         return text[pos];
515 }
516
517
518 inline
519 int LyXParagraph::id() const
520 {
521         return id_;
522 }
523
524
525 inline
526 void  LyXParagraph::id(int id_arg)
527 {
528         id_ = id_arg;
529 }
530
531
532 inline
533 LyXTextClass::size_type LyXParagraph::GetLayout() const
534 {
535         return layout;
536 }
537
538
539 inline
540 bool LyXParagraph::IsFirstInSequence() const
541 {
542         LyXParagraph const * dhook = DepthHook(GetDepth());
543         return (dhook == this
544                 || dhook->GetLayout() != GetLayout()
545                 || dhook->GetDepth() != GetDepth());
546 }
547
548
549 inline
550 Inset * LyXParagraph::InInset()
551 {
552         return inset_owner;
553 }
554
555
556 inline
557 void LyXParagraph::clearContents()
558 {
559         text.clear();
560 }
561
562
563 inline
564 void LyXParagraph::setCounter(int i, int v)
565 {
566         counter_[i] = v;
567 }
568
569
570 inline
571 int LyXParagraph::getCounter(int i) const
572 {
573         return counter_[i];
574 }
575
576
577 inline
578 void LyXParagraph::incCounter(int i)
579 {
580         counter_[i]++;
581 }
582
583
584 inline
585 void LyXParagraph::SetChar(size_type pos, value_type c)
586 {
587         text[pos] = c;
588 }
589
590
591 inline
592 LyXParagraph::inset_iterator LyXParagraph::inset_iterator_begin()
593 {
594         return inset_iterator(insetlist.begin());
595 }
596
597
598 inline
599 LyXParagraph::inset_iterator LyXParagraph::inset_iterator_end()
600 {
601         return inset_iterator(insetlist.end());
602 }
603 #endif