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