7 #include "insetinclude.h"
9 #include "bufferlist.h"
10 #include "BufferView.h"
13 #include "LaTeXFeatures.h"
16 #include "frontends/Dialogs.h"
17 #include "frontends/LyXView.h"
18 #include "frontends/Painter.h"
20 #include "support/filetools.h"
21 #include "support/FileInfo.h"
22 #include "support/lstrings.h"
24 #include "graphics/PreviewedInset.h"
25 #include "graphics/PreviewImage.h"
35 extern BufferList bufferlist;
38 class InsetInclude::PreviewImpl : public grfx::PreviewedInset {
41 PreviewImpl(InsetInclude & p) : PreviewedInset(p) {}
44 bool previewWanted() const;
46 string const latexString() const;
48 InsetInclude & parent() const {
49 return *static_cast<InsetInclude*>(inset());
56 string const uniqueID()
58 static unsigned int seed = 1000;
61 ost << "file" << ++seed;
63 // Needed if we use lyxstring.
64 return ost.str().c_str();
70 InsetInclude::InsetInclude(Params const & p)
71 : params_(p), include_label(uniqueID()),
72 preview_(new PreviewImpl(*this))
76 InsetInclude::InsetInclude(InsetCommandParams const & p, Buffer const & b)
77 : include_label(uniqueID()),
78 preview_(new PreviewImpl(*this))
81 params_.masterFilename_ = b.fileName();
85 InsetInclude::~InsetInclude()
91 InsetInclude::Params const & InsetInclude::params() const
97 bool InsetInclude::Params::operator==(Params const & o) const
99 if (cparams == o.cparams && flag == o.flag &&
100 noload == o.noload && masterFilename_ == o.masterFilename_)
107 bool InsetInclude::Params::operator!=(Params const & o) const
109 return !(*this == o);
113 void InsetInclude::set(Params const & p)
117 // Just to be safe...
120 switch (params_.flag) {
125 command="verbatiminput";
131 command="verbatiminput*";
135 params_.cparams.setCmdName(command);
137 if (grfx::PreviewedInset::activated() && params_.flag == INPUT)
138 preview_->generatePreview();
142 Inset * InsetInclude::clone(Buffer const & buffer, bool) const
145 p.masterFilename_ = buffer.fileName();
147 return new InsetInclude(p);
151 void InsetInclude::edit(BufferView * bv, int, int, mouse_button::state)
153 bv->owner()->getDialogs()->showInclude(this);
157 void InsetInclude::edit(BufferView * bv, bool)
159 edit(bv, 0, 0, mouse_button::none);
163 void InsetInclude::write(Buffer const *, ostream & os) const
165 os << "Include " << params_.cparams.getCommand() << '\n'
166 << "preview " << tostr(params_.cparams.preview()) << '\n';
170 void InsetInclude::read(Buffer const *, LyXLex & lex)
172 params_.cparams.read(lex);
174 if (params_.cparams.getCmdName() == "include")
175 params_.flag = INCLUDE;
176 else if (params_.cparams.getCmdName() == "input")
177 params_.flag = INPUT;
178 /* FIXME: is this logic necessary now ? */
179 else if (contains(params_.cparams.getCmdName(), "verbatim")) {
181 if (params_.cparams.getCmdName() == "verbatiminput*")
182 params_.flag = VERBAST;
187 bool InsetInclude::display() const
189 return !(params_.flag == INPUT);
193 string const InsetInclude::getScreenLabel(Buffer const *) const
197 switch (params_.flag) {
198 case INPUT: temp += _("Input"); break;
199 case VERB: temp += _("Verbatim Input"); break;
200 case VERBAST: temp += _("Verbatim Input*"); break;
201 case INCLUDE: temp += _("Include"); break;
206 if (params_.cparams.getContents().empty())
209 temp += params_.cparams.getContents();
215 string const InsetInclude::getRelFileBaseName() const
217 return OnlyFilename(ChangeExtension(params_.cparams.getContents(), string()));
221 string const InsetInclude::getFileName() const
223 return MakeAbsPath(params_.cparams.getContents(),
224 OnlyPath(getMasterFilename()));
228 string const InsetInclude::getMasterFilename() const
230 return params_.masterFilename_;
234 bool InsetInclude::loadIfNeeded() const
236 if (params_.noload || isVerbatim())
239 if (!IsLyXFilename(getFileName()))
242 if (bufferlist.exists(getFileName()))
245 // the readonly flag can/will be wrong, not anymore I think.
246 FileInfo finfo(getFileName());
250 return bufferlist.readFile(getFileName(), !finfo.writable()) != 0;
254 int InsetInclude::latex(Buffer const * buffer, ostream & os,
255 bool /*fragile*/, bool /*fs*/) const
257 string incfile(params_.cparams.getContents());
259 // Do nothing if no file name has been specified
263 if (loadIfNeeded()) {
264 Buffer * tmp = bufferlist.getBuffer(getFileName());
266 // FIXME: this should be a GUI warning
267 if (tmp->params.textclass != buffer->params.textclass) {
268 lyxerr << "WARNING: Included file `"
269 << MakeDisplayPath(getFileName())
270 << "' has textclass `"
271 << tmp->params.getLyXTextClass().name()
272 << "' while parent file has textclass `"
273 << buffer->params.getLyXTextClass().name()
278 // write it to a file (so far the complete file)
279 string writefile = ChangeExtension(getFileName(), ".tex");
281 if (!buffer->tmppath.empty()
282 && !buffer->niceFile) {
283 incfile = subst(incfile, '/','@');
285 incfile = subst(incfile, ':', '$');
287 writefile = AddName(buffer->tmppath, incfile);
289 writefile = getFileName();
290 writefile = ChangeExtension(writefile, ".tex");
291 lyxerr[Debug::LATEX] << "incfile:" << incfile << endl;
292 lyxerr[Debug::LATEX] << "writefile:" << writefile << endl;
294 tmp->markDepClean(buffer->tmppath);
296 tmp->makeLaTeXFile(writefile,
297 OnlyPath(getMasterFilename()),
298 buffer->niceFile, true);
302 os << '\\' << params_.cparams.getCmdName() << '{' << incfile << '}';
303 } else if (params_.flag == INPUT) {
304 // \input wants file with extension (default is .tex)
305 if (!IsLyXFilename(getFileName())) {
306 os << '\\' << params_.cparams.getCmdName() << '{' << incfile << '}';
308 os << '\\' << params_.cparams.getCmdName() << '{'
309 << ChangeExtension(incfile, ".tex")
313 // \include don't want extension and demands that the
314 // file really have .tex
315 os << '\\' << params_.cparams.getCmdName() << '{'
316 << ChangeExtension(incfile, string())
324 int InsetInclude::ascii(Buffer const *, ostream & os, int) const
327 os << GetFileContents(getFileName());
332 int InsetInclude::linuxdoc(Buffer const * buffer, ostream & os) const
334 string incfile(params_.cparams.getContents());
336 // Do nothing if no file name has been specified
340 if (loadIfNeeded()) {
341 Buffer * tmp = bufferlist.getBuffer(getFileName());
343 // write it to a file (so far the complete file)
344 string writefile = ChangeExtension(getFileName(), ".sgml");
345 if (!buffer->tmppath.empty() && !buffer->niceFile) {
346 incfile = subst(incfile, '/','@');
347 writefile = AddName(buffer->tmppath, incfile);
349 writefile = getFileName();
351 if (IsLyXFilename(getFileName()))
352 writefile = ChangeExtension(writefile, ".sgml");
354 lyxerr[Debug::LATEX] << "incfile:" << incfile << endl;
355 lyxerr[Debug::LATEX] << "writefile:" << writefile << endl;
357 tmp->makeLinuxDocFile(writefile, buffer->niceFile, true);
362 << GetFileContents(getFileName())
365 os << '&' << include_label << ';';
371 int InsetInclude::docbook(Buffer const * buffer, ostream & os,
372 bool /*mixcont*/) const
374 string incfile(params_.cparams.getContents());
376 // Do nothing if no file name has been specified
380 if (loadIfNeeded()) {
381 Buffer * tmp = bufferlist.getBuffer(getFileName());
383 // write it to a file (so far the complete file)
384 string writefile = ChangeExtension(getFileName(), ".sgml");
385 if (!buffer->tmppath.empty() && !buffer->niceFile) {
386 incfile = subst(incfile, '/','@');
387 writefile = AddName(buffer->tmppath, incfile);
389 writefile = getFileName();
390 if (IsLyXFilename(getFileName()))
391 writefile = ChangeExtension(writefile, ".sgml");
393 lyxerr[Debug::LATEX] << "incfile:" << incfile << endl;
394 lyxerr[Debug::LATEX] << "writefile:" << writefile << endl;
396 tmp->makeDocBookFile(writefile, buffer->niceFile, true);
400 os << "<inlinegraphic fileref=\""
401 << '&' << include_label << ';'
402 << "\" format=\"linespecific\">";
404 os << '&' << include_label << ';';
410 void InsetInclude::validate(LaTeXFeatures & features) const
413 string incfile(params_.cparams.getContents());
416 Buffer const * const b = bufferlist.getBuffer(getMasterFilename());
418 if (b && !b->tmppath.empty() && !b->niceFile && !isVerbatim()) {
419 incfile = subst(incfile, '/','@');
420 writefile = AddName(b->tmppath, incfile);
422 writefile = getFileName();
424 if (IsLyXFilename(getFileName()))
425 writefile = ChangeExtension(writefile, ".sgml");
427 features.includeFile(include_label, writefile);
430 features.require("verbatim");
432 // Here we must do the fun stuff...
433 // Load the file in the include if it needs
435 if (loadIfNeeded()) {
437 Buffer * const tmp = bufferlist.getBuffer(getFileName());
440 tmp->niceFile = b->niceFile;
441 tmp->validate(features);
447 vector<string> const InsetInclude::getLabelList() const
451 if (loadIfNeeded()) {
452 Buffer * tmp = bufferlist.getBuffer(getFileName());
453 tmp->setParentName("");
454 l = tmp->getLabelList();
455 tmp->setParentName(getMasterFilename());
462 vector<pair<string,string> > const InsetInclude::getKeys() const
464 vector<pair<string,string> > keys;
466 if (loadIfNeeded()) {
467 Buffer * tmp = bufferlist.getBuffer(getFileName());
468 tmp->setParentName("");
469 keys = tmp->getBibkeyList();
470 tmp->setParentName(getMasterFilename());
477 int InsetInclude::ascent(BufferView * bv, LyXFont const & font) const
479 return preview_->previewReady() ?
480 preview_->pimage()->ascent() : InsetButton::ascent(bv, font);
484 int InsetInclude::descent(BufferView * bv, LyXFont const & font) const
486 return preview_->previewReady() ?
487 preview_->pimage()->descent() : InsetButton::descent(bv, font);
491 int InsetInclude::width(BufferView * bv, LyXFont const & font) const
493 return preview_->previewReady() ?
494 preview_->pimage()->width() : InsetButton::width(bv, font);
498 void InsetInclude::draw(BufferView * bv, LyXFont const & font, int y,
499 float & xx, bool b) const
501 preview_->setView(bv);
502 if (!preview_->previewReady()) {
503 InsetButton::draw(bv, font, y, xx, b);
507 int const x = int(xx);
508 int const w = width(bv, font);
509 int const d = descent(bv, font);
510 int const a = ascent(bv, font);
513 bv->painter().image(x, y - a, w, h,
514 *(preview_->pimage()->image(*this, *bv)));
524 void InsetInclude::addPreview(grfx::PreviewLoader & ploader) const
526 preview_->addPreview(ploader);
530 bool InsetInclude::PreviewImpl::previewWanted() const
532 return parent().params_.flag == InsetInclude::INPUT &&
533 parent().params_.cparams.preview();
537 string const InsetInclude::PreviewImpl::latexString() const
539 if (!view() || !view()->buffer())
543 parent().latex(view()->buffer(), os, false, false);
545 // This fails if the file has a relative path.
546 // return os.str().c_str();
548 // I would /really/ like not to do this...
551 string file = rtrim(split(os.str().c_str(), command, '{'), "}");
553 if (!AbsolutePath(file))
554 file = MakeAbsPath(file, view()->buffer()->filePath());
557 out << command << '{' << file << '}' << endl;
559 return out.str().c_str();