]> git.lyx.org Git - lyx.git/blob - src/lyxparagraph.h
prepare for 1.1.6pre2
[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         void CopyIntoMinibuffer(BufferParams const &, size_type pos) const;
482         ///
483         void CutIntoMinibuffer(BufferParams const &, size_type pos);
484         ///
485         bool InsertFromMinibuffer(size_type pos);
486
487         ///
488         bool IsHfill(size_type pos) const;
489         ///
490         bool IsInset(size_type pos) const;
491 #ifndef NEW_INSETS
492         ///
493         bool IsFloat(size_type pos) const;
494 #endif
495         ///
496         bool IsNewline(size_type pos) const;
497         ///
498         bool IsSeparator(size_type pos) const;
499         ///
500         bool IsLineSeparator(size_type pos) const;
501         ///
502         bool IsKomma(size_type pos) const;
503         /// Used by the spellchecker
504         bool IsLetter(size_type pos) const;
505         /// 
506         bool IsWord(size_type pos) const;
507
508         /** This one resets all layout and dtp switches but not the font
509          of the single characters
510          */ 
511         void Clear();
512
513         /** paste this paragraph with the next one
514           be carefull, this doesent make any check at all
515           */ 
516         void PasteParagraph(BufferParams const &);
517
518         /// used to remove the error messages
519         int AutoDeleteInsets();
520
521         /// returns -1 if inset not found
522         int GetPositionOfInset(Inset * inset) const;
523
524 #ifndef NEW_INSETS
525         /// ok and now some footnote functions
526         void OpenFootnotes();
527
528         ///
529         void CloseFootnotes();
530         ///
531         LyXParagraph * FirstSelfrowPar();
532 #endif
533
534         ///
535         int StripLeadingSpaces(LyXTextClassList::size_type tclass); 
536
537 #ifndef NEW_INSETS
538         /** A paragraph following a footnote is a "dummy". A paragraph
539             with a footnote in it is stored as three paragraphs:
540             First a paragraph with the text up to the footnote, then
541             one (or more) paragraphs with the footnote, and finally
542             the a paragraph with the text after the footnote. Only the
543             first paragraph keeps information  about layoutparameters, */
544         bool IsDummy() const;
545 #endif
546         /* If I set a PExtra Indent on one paragraph of a ENV_LIST-TYPE
547            I have to set it on each of it's elements */
548         ///
549         void SetPExtraType(BufferParams const &, int type,
550                            string const & width, string const & widthp);
551         ///
552         void UnsetPExtraType(BufferParams const &);
553         ///
554         bool linuxDocConvertChar(char c, string & sgml_string);
555 private:
556         ///
557         struct InsetTable {
558                 ///
559                 size_type pos;
560                 ///
561                 Inset * inset;
562                 ///
563                 InsetTable(size_type p, Inset * i) { pos = p; inset = i;}
564         };
565         ///
566         friend struct matchIT;
567         ///
568         struct matchIT {
569                 /// used by lower_bound and upper_bound
570                 inline
571                 int operator()(LyXParagraph::InsetTable const & a,
572                                LyXParagraph::InsetTable const & b) const {
573                         return a.pos < b.pos;
574                 }
575         };
576         /** A font entry covers a range of positions. Notice that the
577           entries in the list are inserted in random order.
578           I don't think it's worth the effort to implement a more effective
579           datastructure, because the number of different fonts in a paragraph
580           is limited. (Asger)
581           Nevertheless, I decided to store fontlist using a sorted vector:
582           fontlist = { {pos_1,font_1} , {pos_2,font_2} , ... } where
583           pos_1 < pos_2 < ..., font_{i-1} != font_i for all i,
584           and font_i covers the chars in positions pos_{i-1}+1,...,pos_i
585           (font_1 covers the chars 0,...,pos_1) (Dekel)
586         */
587         struct FontTable  {
588                 /// End position of paragraph this font attribute covers
589                 size_type pos;
590                 /** Font. Interpretation of the font values:
591                 If a value is LyXFont::INHERIT_*, it means that the font 
592                 attribute is inherited from either the layout of this
593                 paragraph or, in the case of nested paragraphs, from the 
594                 layout in the environment one level up until completely 
595                 resolved.
596                 The values LyXFont::IGNORE_* and LyXFont::TOGGLE are NOT 
597                 allowed in these font tables.
598                 */
599                 LyXFont font;
600                 ///
601                 FontTable(size_type p, LyXFont const & f) {pos = p; font = f;}
602         };
603         ///
604         friend struct matchFT;
605         ///
606         struct matchFT {
607                 /// used by lower_bound and upper_bound
608                 inline
609                 int operator()(LyXParagraph::FontTable const & a,
610                                LyXParagraph::FontTable const & b) const {
611                         return a.pos < b.pos;
612                 }
613         };
614
615         ///
616         typedef std::vector<FontTable> FontList;
617         ///
618         FontList fontlist;
619         ///
620         typedef std::vector<InsetTable> InsetList;
621         ///
622         InsetList insetlist;
623         ///
624         LyXParagraph * TeXDeeper(Buffer const *, BufferParams const &,
625                                  std::ostream &, TexRow & texrow
626 #ifndef NEW_INSETS
627                                  ,std::ostream & foot, TexRow & foot_texrow,
628                                  int & foot_count
629 #endif
630                 );
631 #ifndef NEW_INSETS
632         ///
633         LyXParagraph * TeXFootnote(Buffer const *, BufferParams const &,
634                                    std::ostream &, TexRow & texrow,
635                                    std::ostream & foot, TexRow & foot_texrow,
636                                    int & foot_count,
637                                    bool parent_is_rtl);
638 #endif
639         ///
640         void SimpleTeXBlanks(std::ostream &, TexRow & texrow,
641                              size_type const i,
642                              int & column, LyXFont const & font,
643                              LyXLayout const & style);
644         ///
645         void SimpleTeXSpecialChars(Buffer const *, BufferParams const &,
646                                    std::ostream &, TexRow & texrow,
647                                    bool moving_arg,
648                                    LyXFont & font, LyXFont & running_font,
649                                    LyXFont & basefont, bool & open_font,
650                                    LyXLayout const & style,
651                                    size_type & i,
652                                    int & column, value_type const c);
653         ///
654         unsigned int id_;
655         ///
656         static unsigned int paragraph_id;
657 public:
658         ///
659         class inset_iterator {
660         public:
661                 ///
662                 inset_iterator() {}
663                 //
664                 inset_iterator(InsetList::iterator const & iter) : it(iter) {};
665                 ///
666                 inset_iterator & operator++() {
667                         ++it;
668                         return *this;
669                 }
670                 ///
671                 Inset * operator*() { return (*it).inset; }
672                 ///
673                 size_type getPos() const {return (*it).pos; }
674                 ///
675                 bool operator==(inset_iterator const & iter) const {
676                         return it == iter.it;
677                 }
678                 ///
679                 bool operator!=(inset_iterator const & iter) const {
680                         return it != iter.it;
681                 }
682         private:
683                 ///
684                 InsetList::iterator it;
685         };
686         ///
687         inset_iterator inset_iterator_begin() {
688                 return inset_iterator(insetlist.begin());
689         }
690         ///
691         inset_iterator inset_iterator_end() {
692                 return inset_iterator(insetlist.end());
693         }
694         ///
695         inset_iterator InsetIterator(size_type pos);
696 };
697
698 #endif