2 * \file buffer_funcs.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Lars Gullik Bjønnes
7 * \author Alfredo Braunstein
9 * Full author contact details are available in file CREDITS.
15 #include "buffer_funcs.h"
17 #include "BufferList.h"
18 #include "BufferParams.h"
19 #include "DocIterator.h"
21 #include "ErrorList.h"
23 #include "FloatList.h"
24 #include "InsetList.h"
29 #include "TextClass.h"
30 #include "Paragraph.h"
31 #include "ParagraphList.h"
32 #include "ParagraphParameters.h"
33 #include "ParIterator.h"
36 #include "TocBackend.h"
38 #include "frontends/alert.h"
40 #include "insets/InsetBibitem.h"
41 #include "insets/InsetInclude.h"
43 #include "support/lassert.h"
44 #include "support/convert.h"
45 #include "support/debug.h"
46 #include "support/filetools.h"
47 #include "support/gettext.h"
48 #include "support/lstrings.h"
49 #include "support/textutils.h"
52 using namespace lyx::support
;
56 namespace Alert
= frontend::Alert
;
59 Buffer
* checkAndLoadLyXFile(FileName
const & filename
, bool const acceptDirty
)
62 Buffer
* checkBuffer
= theBufferList().getBuffer(filename
);
64 // sometimes (when setting the master buffer from a child)
65 // we accept a dirty buffer right away (otherwise we'd get
66 // an infinite loop (bug 5514)
67 if (checkBuffer
->isClean() || acceptDirty
)
69 docstring
const file
= makeDisplayPath(filename
.absFilename(), 20);
70 docstring text
= bformat(_(
71 "The document %1$s is already loaded and has unsaved changes.\n"
72 "Do you want to abandon your changes and reload the version on disk?"), file
);
73 if (Alert::prompt(_("Reload saved document?"),
74 text
, 0, 1, _("&Reload"), _("&Keep Changes")))
77 // FIXME: should be LFUN_REVERT
78 theBufferList().release(checkBuffer
);
80 return checkAndLoadLyXFile(filename
);
83 if (filename
.exists()) {
84 if (!filename
.isReadableFile()) {
85 docstring text
= bformat(_("The file %1$s exists but is not "
86 "readable by the current user."),
87 from_utf8(filename
.absFilename()));
88 Alert::error(_("File not readable!"), text
);
91 Buffer
* b
= theBufferList().newBuffer(filename
.absFilename());
93 // Buffer creation is not possible.
96 if (!b
->loadLyXFile(filename
)) {
97 theBufferList().release(b
);
103 docstring text
= bformat(_("The document %1$s does not yet "
104 "exist.\n\nDo you want to create a new document?"),
105 from_utf8(filename
.absFilename()));
106 if (!Alert::prompt(_("Create new document?"),
107 text
, 0, 1, _("&Create"), _("Cancel")))
108 return newFile(filename
.absFilename(), string(), true);
114 // FIXME newFile() should probably be a member method of Application...
115 Buffer
* newFile(string
const & filename
, string
const & templatename
,
119 Buffer
* b
= theBufferList().newBuffer(filename
);
121 // Buffer creation is not possible.
125 // use defaults.lyx as a default template if it exists.
126 if (templatename
.empty())
127 tname
= libFileSearch("templates", "defaults.lyx");
129 tname
= makeAbsPath(templatename
);
131 if (!tname
.empty()) {
132 if (!b
->readFile(tname
)) {
133 docstring
const file
= makeDisplayPath(tname
.absFilename(), 50);
134 docstring
const text
= bformat(
135 _("The specified document template\n%1$s\ncould not be read."),
137 Alert::error(_("Could not read template"), text
);
138 theBufferList().release(b
);
145 b
->setFileName(filename
);
148 b
->setReadonly(false);
149 b
->setFullyLoaded(true);
155 Buffer
* newUnnamedFile(string
const & templatename
, FileName
const & path
)
157 static int newfile_number
;
159 FileName
filename(path
,
160 "newfile" + convert
<string
>(++newfile_number
) + ".lyx");
161 while (theBufferList().exists(filename
)
162 || filename
.isReadableFile()) {
165 "newfile" + convert
<string
>(newfile_number
) + ".lyx");
167 return newFile(filename
.absFilename(), templatename
, false);
171 * FIXME : merge with countChars. The structures of the two functions
172 * are similar but, unfortunately, they seem to have a different
173 * notion of what to count. Since nobody ever complained about that,
174 * this proves (again) that any number beats no number ! (JMarc)
176 int countWords(DocIterator
const & from
, DocIterator
const & to
)
180 for (DocIterator dit
= from
; dit
!= to
; ) {
181 if (!dit
.inTexted()) {
186 Paragraph
const & par
= dit
.paragraph();
187 pos_type
const pos
= dit
.pos();
189 // Copied and adapted from isWordSeparator() in Paragraph
190 if (pos
!= dit
.lastpos() && !par
.isDeleted(pos
)) {
191 Inset
const * ins
= par
.getInset(pos
);
192 if (ins
&& !ins
->producesOutput()) {
197 if (par
.isWordSeparator(pos
))
211 int countChars(DocIterator
const & from
, DocIterator
const & to
,
216 for (DocIterator dit
= from
; dit
!= to
; ) {
217 if (!dit
.inTexted()) {
222 Paragraph
const & par
= dit
.paragraph();
223 pos_type
const pos
= dit
.pos();
225 if (pos
!= dit
.lastpos() && !par
.isDeleted(pos
)) {
226 if (Inset
const * ins
= par
.getInset(pos
)) {
227 if (!ins
->producesOutput()) {
234 else if (with_blanks
&& ins
->isSpace())
237 char_type
const c
= par
.getChar(pos
);
238 if (isPrintableNonspace(c
))
240 else if (isSpace(c
) && with_blanks
)
247 return chars
+ blanks
;