]> git.lyx.org Git - lyx.git/blob - src/buffer.h
The ParagraphList stuff
[lyx.git] / src / buffer.h
1 // -*- C++ -*-
2 /* This file is part of
3  * ======================================================
4  *
5  *           LyX, The Document Processor
6  *           Copyright 1995 Matthias Ettrich
7  *
8  *           This file is Copyleft 1996
9  *           Lars Gullik Bjønnes
10  *
11  * ====================================================== */
12
13 #ifndef BUFFER_H
14 #define BUFFER_H
15
16 #ifdef __GNUG__
17 #pragma interface
18 #endif
19
20 #include "LString.h"
21 #include "undo.h"
22 #include "support/limited_stack.h"
23
24 #include "lyxvc.h"
25 #include "bufferparams.h"
26 #include "texrow.h"
27 #include "ParagraphList.h"
28 #include "paragraph.h"
29
30 #include <boost/shared_ptr.hpp>
31
32 class BufferView;
33 class LyXRC;
34 class TeXErrors;
35 class LaTeXFeatures;
36 class Language;
37 class ParIterator;
38
39 #define NO_COMPABILITY 1
40
41 ///
42 struct DEPCLEAN {
43         ///
44         bool clean;
45         ///
46         string master;
47         ///
48         DEPCLEAN * next;
49 };
50
51 /** The buffer object.
52   This is the buffer object. It contains all the informations about
53   a document loaded into LyX. I am not sure if the class is complete or
54   minimal, probably not.
55   \author Lars Gullik Bjønnes
56   */
57 class Buffer {
58 public:
59         /// What type of log will \c getLogName() return?
60         enum LogType {
61                 latexlog, ///< LaTeX log
62                 buildlog  ///< Literate build log
63         };
64
65         /** Constructor
66             \param file
67             \param b  optional \c false by default
68         */
69         explicit Buffer(string const & file, bool b = false);
70
71         /// Destructor
72         ~Buffer();
73
74         /** High-level interface to buffer functionality.
75             This function parses a command string and executes it
76         */
77         bool dispatch(string const & command, bool * result = 0);
78
79         /// Maybe we know the function already by number...
80         bool dispatch(int ac, string const & argument, bool * result = 0);
81
82         ///
83         void resizeInsets(BufferView *);
84
85         /// Update window titles of all users.
86         void updateTitles() const;
87
88         /// Reset autosave timers for all users.
89         void resetAutosaveTimers() const;
90
91         /** Adds the BufferView to the users list.
92             Later this func will insert the \c BufferView into a real list,
93             not just setting a pointer.
94         */
95         void addUser(BufferView * u);
96
97         /** Removes the #BufferView# from the users list.
98             Since we only can have one at the moment, we just reset it.
99         */
100         void delUser(BufferView *);
101
102         ///
103         void redraw();
104
105         /// Load the autosaved file.
106         void loadAutoSaveFile();
107
108         /** Reads a file.
109             \param par if != 0 insert the file.
110             \return \c false if method fails.
111         */
112         bool readFile(LyXLex &, Paragraph * par = 0);
113
114         /** Reads a file without header.
115             \param par if != 0 insert the file.
116             \return \c false if file is not completely read.
117         */
118         bool readLyXformat2(LyXLex &, Paragraph * par = 0);
119
120         /// This parses a single LyXformat-Token.
121         bool parseSingleLyXformat2Token(LyXLex &, Paragraph *& par,
122                                         Paragraph *& return_par,
123                                         string const & token, int & pos,
124                                         Paragraph::depth_type & depth,
125                                         LyXFont &);
126         ///
127         void insertStringAsLines(Paragraph *&, lyx::pos_type &,
128                                  LyXFont const &, string const &) const;
129 #ifndef NO_COMPABILITY
130         ///
131         Inset * isErtInset(Paragraph * par, int pos) const;
132         ///
133         void insertErtContents(Paragraph * par, int & pos,
134                                bool set_inactive = true);
135 #endif
136         ///
137         Paragraph * getParFromID(int id) const;
138 private:
139         /// Parse a single inset.
140         void readInset(LyXLex &, Paragraph *& par, int & pos, LyXFont &);
141 public:
142         /** Save file.
143             Takes care of auto-save files and backup file if requested.
144             Returns \c true if the save is successful, \c false otherwise.
145         */
146         bool save() const;
147
148         /// Write file. Returns \c false if unsuccesful.
149         bool writeFile(string const &) const;
150
151         ///
152         void writeFileAscii(string const & , int);
153         ///
154         void writeFileAscii(std::ostream &, int);
155         ///
156         string const asciiParagraph(Paragraph const *, unsigned int linelen,
157                                     bool noparbreak = false) const;
158         /// Just a wrapper for the method below, first creating the ofstream.
159         void makeLaTeXFile(string const & filename,
160                            string const & original_path,
161                            bool nice,
162                            bool only_body = false,
163                            bool only_preamble = false);
164         ///
165         void makeLaTeXFile(std::ostream & os,
166                            string const & original_path,
167                            bool nice,
168                            bool only_body = false,
169                            bool only_preamble = false);
170         /** LaTeX all paragraphs from par to endpar.
171             \param \a endpar if == 0 then to the end
172         */
173         void latexParagraphs(std::ostream & os, Paragraph * par,
174                              Paragraph * endpar, TexRow & texrow, bool moving_arg = false) const;
175         ///
176         void simpleDocBookOnePar(std::ostream &,
177                                  Paragraph * par, int & desc_on,
178                                  Paragraph::depth_type depth) const ;
179         ///
180         void simpleLinuxDocOnePar(std::ostream & os, Paragraph * par,
181                                   Paragraph::depth_type depth);
182         ///
183         void makeLinuxDocFile(string const & filename,
184                               bool nice, bool only_body = false);
185         ///
186         void makeDocBookFile(string const & filename,
187                              bool nice, bool only_body = false);
188         /// Open SGML/XML tag.
189         int sgmlOpenTag(std::ostream & os, Paragraph::depth_type depth, bool mixcont,
190                 string const & latexname) const;
191         /// Closes SGML/XML tag.
192         int sgmlCloseTag(std::ostream & os, Paragraph::depth_type depth, bool mixcont,
193                 string const & latexname) const;
194         ///
195         void sgmlError(Paragraph * par, int pos, string const & message) const;
196
197         /// returns the main language for the buffer (document)
198         Language const * getLanguage() const;
199         ///
200         int runChktex();
201         /// return true if the main lyx file does not need saving
202         bool isClean() const;
203         ///
204         bool isBakClean() const;
205         ///
206         bool isDepClean(string const & name) const;
207
208         /// mark the main lyx file as not needing saving
209         void markClean() const;
210
211         ///
212         void markBakClean();
213
214         ///
215         void markDepClean(string const & name);
216
217         ///
218         void setUnnamed(bool flag = true);
219
220         ///
221         bool isUnnamed();
222
223         /// Mark this buffer as dirty.
224         void markDirty();
225
226         /// Returns the buffer's filename. It is always an absolute path.
227         string const & fileName() const;
228
229         /// Returns the the path where the buffer lives.
230         /// It is always an absolute path.
231         string const & filePath() const;
232
233         /** A transformed version of the file name, adequate for LaTeX.
234             \param no_path optional if \c true then the path is stripped.
235         */
236         string const getLatexName(bool no_path = true) const;
237
238         /// Get the name and type of the log.
239         std::pair<LogType, string> const getLogName() const;
240
241         /// Change name of buffer. Updates "read-only" flag.
242         void setFileName(string const & newfile);
243
244         /// Name of the document's parent
245         void setParentName(string const &);
246
247         /// Is buffer read-only?
248         bool isReadonly() const;
249
250         /// Set buffer read-only flag
251         void setReadonly(bool flag = true);
252
253         /// returns \c true if the buffer contains a LaTeX document
254         bool isLatex() const;
255         /// returns \c true if the buffer contains a LinuxDoc document
256         bool isLinuxDoc() const;
257         /// returns \c true if the buffer contains a DocBook document
258         bool isDocBook() const;
259         /** returns \c true if the buffer contains either a LinuxDoc
260             or DocBook document */
261         bool isSGML() const;
262         /// returns \c true if the buffer contains a Wed document
263         bool isLiterate() const;
264
265         /** Validate a buffer for LaTeX.
266             This validates the buffer, and returns a struct for use by
267             #makeLaTeX# and others. Its main use is to figure out what
268             commands and packages need to be included in the LaTeX file.
269             It (should) also check that the needed constructs are there
270             (i.e. that the \refs points to coresponding \labels). It
271             should perhaps inset "error" insets to help the user correct
272             obvious mistakes.
273         */
274         void validate(LaTeXFeatures &) const;
275
276         ///
277         string const getIncludeonlyList(char delim = ',');
278         ///
279         std::vector<std::pair<string, string> > const getBibkeyList() const;
280         ///
281         std::vector<string> const getLabelList();
282
283         /** This will clearly have to change later. Later we can have more
284             than one user per buffer. */
285         BufferView * getUser() const;
286
287         ///
288         void changeLanguage(Language const * from, Language const * to);
289         ///
290         bool isMultiLingual();
291
292         /// Does this mean that this is buffer local?
293         limited_stack<boost::shared_ptr<Undo> > undostack;
294
295         /// Does this mean that this is buffer local?
296         limited_stack<boost::shared_ptr<Undo> > redostack;
297
298         ///
299         BufferParams params;
300
301         /** The list of paragraphs.
302             This is a linked list of paragraph, this list holds the
303             whole contents of the document.
304          */
305         ParagraphList paragraphs;
306
307         /// LyX version control object.
308         LyXVC lyxvc;
309
310         /// Where to put temporary files.
311         string tmppath;
312
313         /** If we are writing a nice LaTeX file or not.
314             While writing as LaTeX, tells whether we are
315             doing a 'nice' LaTeX file */
316         bool niceFile;
317
318         /// Used when typesetting to place errorboxes.
319         TexRow texrow;
320 private:
321         /// is save needed
322         mutable bool lyx_clean;
323
324         /// is autosave needed
325         mutable bool bak_clean;
326
327         /// is this a unnamed file (New...)
328         bool unnamed;
329
330         /// is regenerating #.tex# necessary
331         DEPCLEAN * dep_clean;
332
333         /// buffer is r/o
334         bool read_only;
335
336         /// name of the file the buffer is associated with.
337         string filename_;
338
339         /// The path to the document file.
340         string filepath_;
341
342         /// Format number of buffer
343         int file_format;
344         /** A list of views using this buffer.
345             Why not keep a list of the BufferViews that use this buffer?
346
347             At least then we don't have to do a lot of magic like:
348             #buffer->lyx_gui->bufferview->updateLayoutChoice#. Just ask each
349             of the buffers in the list of users to do a #updateLayoutChoice#.
350         */
351         BufferView * users;
352
353 public:
354         ///
355         class inset_iterator {
356         public:
357                 typedef std::input_iterator_tag iterator_category;
358                 typedef Inset value_type;
359                 typedef ptrdiff_t difference_type;
360                 typedef Inset * pointer;
361                 typedef Inset & reference;
362
363
364                 ///
365                 inset_iterator() : par(0) /*, it(0)*/ {}
366                 //
367                 inset_iterator(Paragraph * paragraph) : par(paragraph) {
368                         setParagraph();
369                 }
370                 ///
371                 inset_iterator(Paragraph * paragraph, lyx::pos_type pos);
372                 ///
373                 inset_iterator & operator++() { // prefix ++
374                         if (par) {
375                                 ++it;
376                                 if (it == par->insetlist.end()) {
377                                         par = par->next();
378                                         setParagraph();
379                                 }
380                         }
381                         return *this;
382                 }
383                 ///
384                 inset_iterator operator++(int) { // postfix ++
385                         inset_iterator tmp(par, it.getPos());
386                         if (par) {
387                                 ++it;
388                                 if (it == par->insetlist.end()) {
389                                         par = par->next();
390                                         setParagraph();
391                                 }
392                         }
393                         return tmp;
394                 }
395
396                 ///
397                 Inset * operator*() { return it.getInset(); }
398
399                 ///
400                 Paragraph * getPar() { return par; }
401                 ///
402                 lyx::pos_type getPos() const { return it.getPos(); }
403                 ///
404                 friend
405                 bool operator==(inset_iterator const & iter1,
406                                 inset_iterator const & iter2);
407         private:
408                 ///
409                 void setParagraph();
410                 ///
411                 Paragraph * par;
412                 ///
413                 InsetList::iterator it;
414         };
415
416         ///
417         inset_iterator inset_iterator_begin() {
418                 return inset_iterator(&*paragraphs.begin());
419         }
420         ///
421         inset_iterator inset_iterator_end() {
422                 return inset_iterator();
423         }
424         ///
425         inset_iterator inset_const_iterator_begin() const {
426                 return inset_iterator(&*paragraphs.begin());
427         }
428         ///
429         inset_iterator inset_const_iterator_end() const {
430                 return inset_iterator();
431         }
432
433         ///
434         ParIterator par_iterator_begin();
435         ///
436         ParIterator par_iterator_end();
437
438         ///
439         Inset * getInsetFromID(int id_arg) const;
440 };
441
442
443 inline
444 void Buffer::addUser(BufferView * u)
445 {
446         users = u;
447 }
448
449
450 inline
451 void Buffer::delUser(BufferView *)
452 {
453         users = 0;
454 }
455
456
457 inline
458 Language const * Buffer::getLanguage() const
459 {
460         return params.language;
461 }
462
463
464 inline
465 bool Buffer::isClean() const
466 {
467         return lyx_clean;
468 }
469
470
471 inline
472 bool Buffer::isBakClean() const
473 {
474         return bak_clean;
475 }
476
477
478 inline
479 void Buffer::markClean() const
480 {
481         if (!lyx_clean) {
482                 lyx_clean = true;
483                 updateTitles();
484         }
485         // if the .lyx file has been saved, we don't need an
486         // autosave
487         bak_clean = true;
488 }
489
490
491 inline
492 void Buffer::markBakClean()
493 {
494         bak_clean = true;
495 }
496
497
498 inline
499 void Buffer::setUnnamed(bool flag)
500 {
501         unnamed = flag;
502 }
503
504
505 inline
506 bool Buffer::isUnnamed()
507 {
508         return unnamed;
509 }
510
511
512 inline
513 void Buffer::markDirty()
514 {
515         if (lyx_clean) {
516                 lyx_clean = false;
517                 updateTitles();
518         }
519         bak_clean = false;
520         DEPCLEAN * tmp = dep_clean;
521         while (tmp) {
522                 tmp->clean = false;
523                 tmp = tmp->next;
524         }
525 }
526
527
528 inline
529 string const & Buffer::fileName() const
530 {
531         return filename_;
532 }
533
534
535 inline
536 string const & Buffer::filePath() const
537 {
538         return filepath_;
539 }
540
541
542 inline
543 bool Buffer::isReadonly() const
544 {
545         return read_only;
546 }
547
548
549 inline
550 BufferView * Buffer::getUser() const
551 {
552         return users;
553 }
554
555
556 inline
557 void Buffer::setParentName(string const & name)
558 {
559         params.parentname = name;
560 }
561
562
563 ///
564 inline
565 bool operator==(Buffer::inset_iterator const & iter1,
566                 Buffer::inset_iterator const & iter2)
567 {
568         return iter1.par == iter2.par
569                 && (iter1.par == 0 || iter1.it == iter2.it);
570 }
571
572
573 ///
574 inline
575 bool operator!=(Buffer::inset_iterator const & iter1,
576                 Buffer::inset_iterator const & iter2)
577 {
578         return !(iter1 == iter2);
579 }
580
581 #endif