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