]> git.lyx.org Git - lyx.git/blob - src/lyxparagraph.h
13271163431b1e30fb2faafe367698ce4c62c8bd
[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 #ifndef NEW_INSETS
70                 ///
71                 META_FOOTNOTE = 1,
72                 ///
73                 META_MARGIN,
74                 ///
75                 META_FIG,
76                 ///
77                 META_TAB,
78                 ///
79                 META_ALGORITHM,
80                 ///
81                 META_WIDE_FIG,
82                 ///
83                 META_WIDE_TAB,
84                 ///
85                 META_HFILL,
86 #else
87                 ///
88                 META_HFILL = 1,
89 #endif
90                 ///
91                 META_NEWLINE,
92                 //
93                 //META_PROTECTED_SEPARATOR,
94                 ///
95                 META_INSET
96         };
97 #ifndef NEW_INSETS
98
99         /// The footnoteflag
100         enum footnote_flag {
101                 ///
102                 NO_FOOTNOTE,
103                 ///
104                 OPEN_FOOTNOTE,
105                 ///
106                 CLOSED_FOOTNOTE
107         };
108
109         /// The footnotekinds
110         enum footnote_kind {
111                 ///
112                 FOOTNOTE,
113                 ///
114                 MARGIN,
115                 ///
116                 FIG,
117                 ///
118                 TAB,
119                 ///
120                 ALGORITHM,  // Bernhard, 970807
121                 ///
122                 WIDE_FIG,   // CFO-G, 971106
123                 ///
124                 WIDE_TAB    // CFO-G, 971106
125         };
126 #endif
127         ///
128         typedef char value_type;
129         ///
130         typedef std::vector<value_type> TextContainer;
131         ///
132         /* This should be TextContainer::size_type, but we need
133            signed values for now.
134         */
135         typedef TextContainer::difference_type size_type;
136
137         ///
138         LyXParagraph();
139         /// this constructor inserts the new paragraph in a list
140         explicit
141         LyXParagraph(LyXParagraph * par);
142         /// the destructor removes the new paragraph from the list
143         ~LyXParagraph();
144
145         ///
146         Language const * getParLanguage(BufferParams const &) const;
147         ///
148         bool isRightToLeftPar(BufferParams const &) const;
149         ///
150         void ChangeLanguage(BufferParams const & bparams,
151                             Language const * from, Language const * to);
152         ///
153         bool isMultiLingual(BufferParams const &);
154         ///
155
156         string const String(Buffer const *, bool label);
157         ///
158         string const String(Buffer const *, size_type beg, size_type end);
159         
160         ///
161         void writeFile(Buffer const *, std::ostream &, BufferParams const &,
162                        char, char) const;
163         ///
164         void validate(LaTeXFeatures &) const;
165         
166         ///
167         int id() const;
168         ///
169         void id(int id_arg);
170         ///
171         void read();
172
173         ///
174         LyXParagraph * TeXOnePar(Buffer const *, BufferParams const &,
175                                  std::ostream &, TexRow & texrow,
176                                  bool moving_arg
177 #ifndef NEW_INSETS
178                                  ,
179                                  std::ostream & foot, TexRow & foot_texrow,
180                                  int & foot_count
181 #endif
182                 );
183         ///
184         bool SimpleTeXOnePar(Buffer const *, BufferParams const &,
185                              std::ostream &, TexRow & texrow, bool moving_arg);
186
187         ///
188         LyXParagraph * TeXEnvironment(Buffer const *, BufferParams const &,
189                                       std::ostream &, TexRow & texrow
190 #ifndef NEW_INSETS
191                                       ,std::ostream & foot, TexRow & foot_texrow,
192                                       int & foot_count
193 #endif
194                 );
195         ///
196         LyXParagraph * Clone() const;
197         
198         ///
199         bool HasSameLayout(LyXParagraph const * par) const;
200         
201         ///
202         void MakeSameLayout(LyXParagraph const * par);
203
204         /// Is it the first par with same depth and layout?
205         bool IsFirstInSequence() const;
206
207         /** Check if the current paragraph is the last paragraph in a
208             proof environment */
209         int GetEndLabel(BufferParams const &) const;
210         ///
211         Inset * InInset();
212         ///
213         void SetInsetOwner(Inset * i);
214         ///
215         void deleteInsetsLyXText(BufferView *);
216         ///
217         void resizeInsetsLyXText(BufferView *);
218 private:
219         ///
220         TextContainer text;
221         ///
222         Inset * inset_owner;
223
224 public:
225         ///
226         inline
227         size_type size() const;
228         ///
229         void fitToSize();
230         ///
231         void setContentsFromPar(LyXParagraph * par);
232         ///
233         void clearContents();
234
235         ParagraphParameters params;
236         
237         ///
238         LyXTextClass::LayoutList::size_type layout;
239 #ifndef NEW_INSETS
240         /**
241           \begin{itemize}
242           \item no footnote, closed footnote, 
243           \item open footnote, where footnote
244           \item means footnote-environment
245           \end{itemize}
246          */
247         footnote_flag footnoteflag;
248
249         /// footnote, margin, fig, tab
250         footnote_kind footnotekind;
251 #endif
252         
253 private:
254         ///
255         boost::array<int, 10> counter_;
256 public:
257         ///
258         void setCounter(int i, int v);
259         ///
260         int getCounter(int i) const;
261         ///
262         void incCounter(int i);
263
264         ///
265         char enumdepth;
266         
267         ///
268         char itemdepth;
269 #ifdef NEW_INSETS
270 private:
271 #endif
272         ///
273         LyXParagraph * next_;
274         ///
275         LyXParagraph * previous_;
276 public:
277         /// 
278         InsetBibKey * bibkey;  // ale970302
279
280         ///
281         void next(LyXParagraph *);
282         /** these function are able to hide closed footnotes
283          */
284         LyXParagraph * next();
285         ///
286         LyXParagraph const * next() const;
287
288         ///
289         void previous(LyXParagraph *);
290         ///
291         LyXParagraph * previous();
292         ///
293         LyXParagraph const * previous() const;
294
295 #ifndef NEW_INSETS
296         /** these function are able to hide open and closed footnotes
297          */ 
298         LyXParagraph * NextAfterFootnote();
299         ///
300         LyXParagraph const * NextAfterFootnote() const;
301         
302         ///
303         LyXParagraph * PreviousBeforeFootnote();
304         ///
305         LyXParagraph * LastPhysicalPar();
306         ///
307         LyXParagraph const * LastPhysicalPar() const;
308         
309         ///
310         LyXParagraph * FirstPhysicalPar();
311         ///
312         LyXParagraph const * FirstPhysicalPar() const;
313         /// returns the physical paragraph
314         LyXParagraph * ParFromPos(size_type pos);
315         /// returns the position in the physical par
316         int PositionInParFromPos(size_type pos) const;
317 #endif
318
319         /// for the environments
320         LyXParagraph * DepthHook(int depth);
321         /// for the environments
322         LyXParagraph const * DepthHook(int depth) const;
323         ///
324         int BeginningOfMainBody() const;
325         ///
326         string const & GetLabelstring() const;
327         
328         /// the next two functions are for the manual labels
329         string const GetLabelWidthString() const;
330         ///
331         void SetLabelWidthString(string const & s);
332         ///
333         inline
334         LyXTextClass::LayoutList::size_type GetLayout() const;
335         ///
336         char GetAlign() const;
337         ///
338         char GetDepth() const;
339 #ifndef NEW_INSETS
340         ///
341         void SetLayout(BufferParams const &,
342                        LyXTextClass::LayoutList::size_type new_layout);
343         ///
344         void SetOnlyLayout(BufferParams const &,
345                            LyXTextClass::LayoutList::size_type new_layout);
346         ///
347         size_type Last() const;
348 #else
349         ///
350         void SetLayout(LyXTextClass::LayoutList::size_type new_layout);
351         ///
352         void SetOnlyLayout(LyXTextClass::LayoutList::size_type new_layout);
353 #endif
354         ///
355         int GetFirstCounter(int i) const;
356         ///
357         void Erase(size_type pos);
358         /** the flag determines wether the layout should be copied
359          */ 
360         void BreakParagraph(BufferParams const &, size_type pos, int flag);
361         ///
362         void BreakParagraphConservative(BufferParams const &, size_type pos);
363         /** Get unistantiated font setting. Returns the difference
364           between the characters font and the layoutfont.
365           This is what is stored in the fonttable
366          */
367         LyXFont const
368         GetFontSettings(BufferParams const &, size_type pos) const;
369         ///
370         LyXFont const GetFirstFontSettings() const;
371
372         /** Get fully instantiated font. If pos == -1, use the layout
373             font attached to this paragraph.
374             If pos == -2, use the label font of the layout attached here.
375             In all cases, the font is instantiated, i.e. does not have any
376             attributes with values LyXFont::INHERIT, LyXFont::IGNORE or 
377             LyXFont::TOGGLE.
378         */
379         LyXFont const getFont(BufferParams const &, size_type pos) const;
380         ///
381         value_type GetChar(size_type pos) const;
382         ///
383         value_type GetUChar(BufferParams const &, size_type pos) const;
384         /// The position must already exist.
385         void SetChar(size_type pos, value_type c);
386         ///
387         void SetFont(size_type pos, LyXFont const & font);
388         ///
389         string const GetWord(size_type &) const;
390         /// Returns the height of the highest font in range
391         LyXFont::FONT_SIZE HighestFontInRange(size_type startpos,
392                                               size_type endpos) const;
393         ///
394         void InsertChar(size_type pos, value_type c);
395         ///
396         void InsertChar(size_type pos, value_type c, LyXFont const &);
397         ///
398         void InsertInset(size_type pos, Inset * inset);
399         ///
400         void InsertInset(size_type pos, Inset * inset, LyXFont const &);
401         ///
402         bool InsertInsetAllowed(Inset * inset);
403         ///
404         Inset * GetInset(size_type pos);
405         ///
406         Inset const * GetInset(size_type pos) const;
407 #ifndef NEW_INSETS
408         ///
409         void OpenFootnote(size_type pos);
410         ///
411         void CloseFootnote(size_type pos);
412 #endif
413         /** important for cut and paste
414             Temporary change from BufferParams to Buffer. Will revert when we
415             get rid of the argument to Inset::Clone(Buffer const &) */
416         void CopyIntoMinibuffer(Buffer const &, size_type pos) const;
417         ///
418         void CutIntoMinibuffer(BufferParams const &, size_type pos);
419         ///
420         bool InsertFromMinibuffer(size_type pos);
421
422         ///
423         bool IsHfill(size_type pos) const;
424         ///
425         bool IsInset(size_type pos) const;
426 #ifndef NEW_INSETS
427         ///
428         bool IsFloat(size_type pos) const;
429 #endif
430         ///
431         bool IsNewline(size_type pos) const;
432         ///
433         bool IsSeparator(size_type pos) const;
434         ///
435         bool IsLineSeparator(size_type pos) const;
436         ///
437         bool IsKomma(size_type pos) const;
438         /// Used by the spellchecker
439         bool IsLetter(size_type pos) const;
440         /// 
441         bool IsWord(size_type pos) const;
442
443         /** This one resets all layout and dtp switches but not the font
444          of the single characters
445          */ 
446         void Clear();
447
448         /** paste this paragraph with the next one
449           be carefull, this doesent make any check at all
450           */ 
451         void PasteParagraph(BufferParams const &);
452
453         /// used to remove the error messages
454         int AutoDeleteInsets();
455
456         /// returns -1 if inset not found
457         int GetPositionOfInset(Inset * inset) const;
458
459 #ifndef NEW_INSETS
460         /// ok and now some footnote functions
461         void OpenFootnotes();
462
463         ///
464         void CloseFootnotes();
465         ///
466         LyXParagraph * FirstSelfrowPar();
467 #endif
468
469         ///
470         int StripLeadingSpaces(LyXTextClassList::size_type tclass); 
471
472 #ifndef NEW_INSETS
473         /** A paragraph following a footnote is a "dummy". A paragraph
474             with a footnote in it is stored as three paragraphs:
475             First a paragraph with the text up to the footnote, then
476             one (or more) paragraphs with the footnote, and finally
477             the a paragraph with the text after the footnote. Only the
478             first paragraph keeps information  about layoutparameters, */
479         bool IsDummy() const;
480 #endif
481 #ifndef NO_PEXTRA_REALLY
482         /* If I set a PExtra Indent on one paragraph of a ENV_LIST-TYPE
483            I have to set it on each of it's elements */
484         ///
485         void SetPExtraType(BufferParams const &, int type,
486                            string const & width, string const & widthp);
487         ///
488         void UnsetPExtraType(BufferParams const &);
489 #endif
490         ///
491         bool linuxDocConvertChar(char c, string & sgml_string);
492 private:
493         ///
494         struct InsetTable {
495                 ///
496                 size_type pos;
497                 ///
498                 Inset * inset;
499                 ///
500                 InsetTable(size_type p, Inset * i) : pos(p), inset(i) {}
501         };
502         ///
503         friend struct matchIT;
504         ///
505         struct matchIT {
506                 /// used by lower_bound and upper_bound
507                 inline
508                 int operator()(LyXParagraph::InsetTable const & a,
509                                LyXParagraph::InsetTable const & b) const {
510                         return a.pos < b.pos;
511                 }
512         };
513         /** A font entry covers a range of positions. Notice that the
514           entries in the list are inserted in random order.
515           I don't think it's worth the effort to implement a more effective
516           datastructure, because the number of different fonts in a paragraph
517           is limited. (Asger)
518           Nevertheless, I decided to store fontlist using a sorted vector:
519           fontlist = { {pos_1,font_1} , {pos_2,font_2} , ... } where
520           pos_1 < pos_2 < ..., font_{i-1} != font_i for all i,
521           and font_i covers the chars in positions pos_{i-1}+1,...,pos_i
522           (font_1 covers the chars 0,...,pos_1) (Dekel)
523         */
524         struct FontTable  {
525                 ///
526                 FontTable(size_type p, LyXFont const & f)
527                         : pos_(p)
528                 {
529                         font_ = container.get(f);
530                 }
531                 ///
532                 size_type pos() const { return pos_; }
533                 ///
534                 void pos(size_type p) { pos_ = p; }
535                 ///
536                 LyXFont const & font() const { return *font_; }
537                 ///
538                 void font(LyXFont const & f) { font_ = container.get(f);}
539         private:
540                 /// End position of paragraph this font attribute covers
541                 size_type pos_;
542                 /** Font. Interpretation of the font values:
543                 If a value is LyXFont::INHERIT_*, it means that the font 
544                 attribute is inherited from either the layout of this
545                 paragraph or, in the case of nested paragraphs, from the 
546                 layout in the environment one level up until completely 
547                 resolved.
548                 The values LyXFont::IGNORE_* and LyXFont::TOGGLE are NOT 
549                 allowed in these font tables.
550                 */
551                 boost::shared_ptr<LyXFont> font_;
552                 ///
553                 static ShareContainer<LyXFont> container;
554         };
555         ///
556         friend struct matchFT;
557         ///
558         struct matchFT {
559                 /// used by lower_bound and upper_bound
560                 inline
561                 int operator()(LyXParagraph::FontTable const & a,
562                                LyXParagraph::FontTable const & b) const {
563                         return a.pos() < b.pos();
564                 }
565         };
566
567         ///
568         typedef std::vector<FontTable> FontList;
569         ///
570         FontList fontlist;
571         ///
572         typedef std::vector<InsetTable> InsetList;
573         ///
574         InsetList insetlist;
575         ///
576         LyXParagraph * TeXDeeper(Buffer const *, BufferParams const &,
577                                  std::ostream &, TexRow & texrow
578 #ifndef NEW_INSETS
579                                  ,std::ostream & foot, TexRow & foot_texrow,
580                                  int & foot_count
581 #endif
582                 );
583 #ifndef NEW_INSETS
584         ///
585         LyXParagraph * TeXFootnote(Buffer const *, BufferParams const &,
586                                    std::ostream &, TexRow & texrow,
587                                    std::ostream & foot, TexRow & foot_texrow,
588                                    int & foot_count,
589                                    bool parent_is_rtl);
590 #endif
591         ///
592         void SimpleTeXBlanks(std::ostream &, TexRow & texrow,
593                              size_type const i,
594                              int & column, LyXFont const & font,
595                              LyXLayout const & style);
596         ///
597         void SimpleTeXSpecialChars(Buffer const *, BufferParams const &,
598                                    std::ostream &, TexRow & texrow,
599                                    bool moving_arg,
600                                    LyXFont & font, LyXFont & running_font,
601                                    LyXFont & basefont, bool & open_font,
602                                    LyXLayout const & style,
603                                    size_type & i,
604                                    int & column, value_type const c);
605         ///
606         unsigned int id_;
607         ///
608         static unsigned int paragraph_id;
609 public:
610         ///
611         class inset_iterator {
612         public:
613                 ///
614                 inset_iterator() {}
615                 //
616                 inset_iterator(InsetList::iterator const & iter) : it(iter) {};
617                 ///
618                 inset_iterator & operator++() {
619                         ++it;
620                         return *this;
621                 }
622                 ///
623                 Inset * operator*() { return (*it).inset; }
624                 ///
625                 size_type getPos() const {return (*it).pos; }
626                 ///
627                 bool operator==(inset_iterator const & iter) const {
628                         return it == iter.it;
629                 }
630                 ///
631                 bool operator!=(inset_iterator const & iter) const {
632                         return it != iter.it;
633                 }
634         private:
635                 ///
636                 InsetList::iterator it;
637         };
638         ///
639         inset_iterator inset_iterator_begin();
640         ///
641         inset_iterator inset_iterator_end();
642         ///
643         inset_iterator InsetIterator(size_type pos);
644 };
645
646
647 #ifdef NEW_INSETS
648 inline
649 LyXParagraph::value_type
650 LyXParagraph::GetChar(LyXParagraph::size_type pos) const
651 {
652         Assert(pos <= size());
653         // This is stronger, and I belive that this is the assertion
654         // that we should really use. (Lgb)
655         //Assert(pos < size());
656
657         // Then this has no meaning. (Lgb)
658         if (!size() || pos == size()) return '\0';
659         
660         return text[pos];
661 }
662 #endif
663
664 inline
665 int LyXParagraph::id() const
666 {
667         return id_;
668 }
669
670
671 inline
672 void  LyXParagraph::id(int id_arg)
673 {
674         id_ = id_arg;
675 }
676
677
678 inline
679 bool LyXParagraph::IsFirstInSequence() const
680 {
681         LyXParagraph const * dhook = DepthHook(GetDepth());
682         return (dhook == this
683                 || dhook->GetLayout() != GetLayout()
684                 || dhook->GetDepth() != GetDepth());
685 }
686
687
688 inline
689 Inset * LyXParagraph::InInset()
690 {
691         return inset_owner;
692 }
693
694
695 inline
696 LyXParagraph::size_type LyXParagraph::size() const
697 {
698         return text.size();
699 }
700
701
702 inline
703 void LyXParagraph::clearContents()
704 {
705         text.clear();
706 }
707
708
709 inline
710 void LyXParagraph::setCounter(int i, int v)
711 {
712         counter_[i] = v;
713 }
714
715
716 inline
717 int LyXParagraph::getCounter(int i) const
718 {
719         return counter_[i];
720 }
721
722
723 inline
724 void LyXParagraph::incCounter(int i)
725 {
726         counter_[i]++;
727 }
728
729
730 inline
731 void LyXParagraph::SetChar(size_type pos, value_type c)
732 {
733         text[pos] = c;
734 }
735
736
737 inline
738 LyXTextClass::size_type LyXParagraph::GetLayout() const
739 {
740 #ifndef NEW_INSETS
741         return FirstPhysicalPar()->layout;
742 #else
743         return layout;
744 #endif
745 }
746
747
748 inline
749 LyXParagraph::inset_iterator LyXParagraph::inset_iterator_begin()
750 {
751         return inset_iterator(insetlist.begin());
752 }
753
754
755 inline
756 LyXParagraph::inset_iterator LyXParagraph::inset_iterator_end()
757 {
758         return inset_iterator(insetlist.end());
759 }
760 #endif