7 #include "insetinclude.h"
9 #include "bufferlist.h"
10 #include "BufferView.h"
13 #include "frontends/LyXView.h"
14 #include "LaTeXFeatures.h"
17 #include "frontends/Dialogs.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;
36 extern BufferView * current_view;
38 class InsetInclude::PreviewImpl : public grfx::PreviewedInset {
41 PreviewImpl(InsetInclude & p) : PreviewedInset(p) {}
44 bool previewWanted() const;
46 string const latexString() const;
49 BufferView * view() const { return current_view; }
51 InsetInclude & parent() const {
52 return *static_cast<InsetInclude*>(inset());
59 string const uniqueID()
61 static unsigned int seed = 1000;
64 ost << "file" << ++seed;
66 // Needed if we use lyxstring.
67 return ost.str().c_str();
73 InsetInclude::InsetInclude(Params const & p)
74 : params_(p), include_label(uniqueID()),
75 preview_(new PreviewImpl(*this))
79 InsetInclude::InsetInclude(InsetCommandParams const & p, Buffer const & b)
80 : include_label(uniqueID()),
81 preview_(new PreviewImpl(*this))
84 params_.masterFilename_ = b.fileName();
88 InsetInclude::~InsetInclude()
94 InsetInclude::Params const & InsetInclude::params() const
100 bool InsetInclude::Params::operator==(Params const & o) const
102 if (cparams == o.cparams && flag == o.flag &&
103 noload == o.noload && masterFilename_ == o.masterFilename_)
110 bool InsetInclude::Params::operator!=(Params const & o) const
112 return !(*this == o);
116 void InsetInclude::set(Params const & p)
120 // Just to be safe...
123 switch (params_.flag) {
128 command="verbatiminput";
134 command="verbatiminput*";
138 params_.cparams.setCmdName(command);
140 if (grfx::PreviewedInset::activated() && params_.flag == INPUT)
141 preview_->generatePreview();
145 Inset * InsetInclude::clone(Buffer const & buffer, bool) const
148 p.masterFilename_ = buffer.fileName();
150 return new InsetInclude(p);
154 void InsetInclude::edit(BufferView * bv, int, int, mouse_button::state)
156 bv->owner()->getDialogs()->showInclude(this);
160 void InsetInclude::edit(BufferView * bv, bool)
162 edit(bv, 0, 0, mouse_button::none);
166 void InsetInclude::write(Buffer const *, ostream & os) const
168 os << "Include " << params_.cparams.getCommand() << "\n";
172 void InsetInclude::read(Buffer const *, LyXLex & lex)
174 params_.cparams.read(lex);
176 if (params_.cparams.getCmdName() == "include")
177 params_.flag = INCLUDE;
178 else if (params_.cparams.getCmdName() == "input")
179 params_.flag = INPUT;
180 /* FIXME: is this logic necessary now ? */
181 else if (contains(params_.cparams.getCmdName(), "verbatim")) {
183 if (params_.cparams.getCmdName() == "verbatiminput*")
184 params_.flag = VERBAST;
189 bool InsetInclude::display() const
191 return !(params_.flag == INPUT);
195 string const InsetInclude::getScreenLabel(Buffer const *) const
199 switch (params_.flag) {
200 case INPUT: temp += _("Input"); break;
201 case VERB: temp += _("Verbatim Input"); break;
202 case VERBAST: temp += _("Verbatim Input*"); break;
203 case INCLUDE: temp += _("Include"); break;
208 if (params_.cparams.getContents().empty())
211 temp += params_.cparams.getContents();
217 string const InsetInclude::getRelFileBaseName() const
219 return OnlyFilename(ChangeExtension(params_.cparams.getContents(), string()));
223 string const InsetInclude::getFileName() const
225 return MakeAbsPath(params_.cparams.getContents(),
226 OnlyPath(getMasterFilename()));
230 string const InsetInclude::getMasterFilename() const
232 return params_.masterFilename_;
236 bool InsetInclude::loadIfNeeded() const
238 if (params_.noload || isVerbatim())
241 if (!IsLyXFilename(getFileName()))
244 if (bufferlist.exists(getFileName()))
247 // the readonly flag can/will be wrong, not anymore I think.
248 FileInfo finfo(getFileName());
252 return bufferlist.readFile(getFileName(), !finfo.writable()) != 0;
256 int InsetInclude::latex(Buffer const * buffer, ostream & os,
257 bool /*fragile*/, bool /*fs*/) const
259 string incfile(params_.cparams.getContents());
261 // Do nothing if no file name has been specified
265 if (loadIfNeeded()) {
266 Buffer * tmp = bufferlist.getBuffer(getFileName());
268 // FIXME: this should be a GUI warning
269 if (tmp->params.textclass != buffer->params.textclass) {
270 lyxerr << "WARNING: Included file `"
271 << MakeDisplayPath(getFileName())
272 << "' has textclass `"
273 << tmp->params.getLyXTextClass().name()
274 << "' while parent file has textclass `"
275 << buffer->params.getLyXTextClass().name()
280 // write it to a file (so far the complete file)
281 string writefile = ChangeExtension(getFileName(), ".tex");
283 if (!buffer->tmppath.empty()
284 && !buffer->niceFile) {
285 incfile = subst(incfile, '/','@');
287 incfile = subst(incfile, ':', '$');
289 writefile = AddName(buffer->tmppath, incfile);
291 writefile = getFileName();
292 writefile = ChangeExtension(writefile, ".tex");
293 lyxerr[Debug::LATEX] << "incfile:" << incfile << endl;
294 lyxerr[Debug::LATEX] << "writefile:" << writefile << endl;
296 tmp->markDepClean(buffer->tmppath);
298 tmp->makeLaTeXFile(writefile,
299 OnlyPath(getMasterFilename()),
300 buffer->niceFile, true);
304 os << '\\' << params_.cparams.getCmdName() << '{' << incfile << '}';
305 } else if (params_.flag == INPUT) {
306 // \input wants file with extension (default is .tex)
307 if (!IsLyXFilename(getFileName())) {
308 os << '\\' << params_.cparams.getCmdName() << '{' << incfile << '}';
310 os << '\\' << params_.cparams.getCmdName() << '{'
311 << ChangeExtension(incfile, ".tex")
315 // \include don't want extension and demands that the
316 // file really have .tex
317 os << '\\' << params_.cparams.getCmdName() << '{'
318 << ChangeExtension(incfile, string())
326 int InsetInclude::ascii(Buffer const *, ostream & os, int) const
329 os << GetFileContents(getFileName());
334 int InsetInclude::linuxdoc(Buffer const * buffer, ostream & os) const
336 string incfile(params_.cparams.getContents());
338 // Do nothing if no file name has been specified
342 if (loadIfNeeded()) {
343 Buffer * tmp = bufferlist.getBuffer(getFileName());
345 // write it to a file (so far the complete file)
346 string writefile = ChangeExtension(getFileName(), ".sgml");
347 if (!buffer->tmppath.empty() && !buffer->niceFile) {
348 incfile = subst(incfile, '/','@');
349 writefile = AddName(buffer->tmppath, incfile);
351 writefile = getFileName();
353 if (IsLyXFilename(getFileName()))
354 writefile = ChangeExtension(writefile, ".sgml");
356 lyxerr[Debug::LATEX] << "incfile:" << incfile << endl;
357 lyxerr[Debug::LATEX] << "writefile:" << writefile << endl;
359 tmp->makeLinuxDocFile(writefile, buffer->niceFile, true);
364 << GetFileContents(getFileName())
367 os << '&' << include_label << ';';
373 int InsetInclude::docbook(Buffer const * buffer, ostream & os,
374 bool /*mixcont*/) const
376 string incfile(params_.cparams.getContents());
378 // Do nothing if no file name has been specified
382 if (loadIfNeeded()) {
383 Buffer * tmp = bufferlist.getBuffer(getFileName());
385 // write it to a file (so far the complete file)
386 string writefile = ChangeExtension(getFileName(), ".sgml");
387 if (!buffer->tmppath.empty() && !buffer->niceFile) {
388 incfile = subst(incfile, '/','@');
389 writefile = AddName(buffer->tmppath, incfile);
391 writefile = getFileName();
392 if (IsLyXFilename(getFileName()))
393 writefile = ChangeExtension(writefile, ".sgml");
395 lyxerr[Debug::LATEX] << "incfile:" << incfile << endl;
396 lyxerr[Debug::LATEX] << "writefile:" << writefile << endl;
398 tmp->makeDocBookFile(writefile, buffer->niceFile, true);
402 os << "<inlinegraphic fileref=\""
403 << '&' << include_label << ';'
404 << "\" format=\"linespecific\">";
406 os << '&' << include_label << ';';
412 void InsetInclude::validate(LaTeXFeatures & features) const
415 string incfile(params_.cparams.getContents());
418 Buffer const * const b = bufferlist.getBuffer(getMasterFilename());
420 if (b && !b->tmppath.empty() && !b->niceFile && !isVerbatim()) {
421 incfile = subst(incfile, '/','@');
422 writefile = AddName(b->tmppath, incfile);
424 writefile = getFileName();
426 if (IsLyXFilename(getFileName()))
427 writefile = ChangeExtension(writefile, ".sgml");
429 features.includeFile(include_label, writefile);
432 features.require("verbatim");
434 // Here we must do the fun stuff...
435 // Load the file in the include if it needs
437 if (loadIfNeeded()) {
439 Buffer * const tmp = bufferlist.getBuffer(getFileName());
442 tmp->niceFile = b->niceFile;
443 tmp->validate(features);
449 vector<string> const InsetInclude::getLabelList() const
453 if (loadIfNeeded()) {
454 Buffer * tmp = bufferlist.getBuffer(getFileName());
455 tmp->setParentName("");
456 l = tmp->getLabelList();
457 tmp->setParentName(getMasterFilename());
464 vector<pair<string,string> > const InsetInclude::getKeys() const
466 vector<pair<string,string> > keys;
468 if (loadIfNeeded()) {
469 Buffer * tmp = bufferlist.getBuffer(getFileName());
470 tmp->setParentName("");
471 keys = tmp->getBibkeyList();
472 tmp->setParentName(getMasterFilename());
479 int InsetInclude::ascent(BufferView * bv, LyXFont const & font) const
481 return preview_->previewReady() ?
482 preview_->pimage()->ascent() : InsetButton::ascent(bv, font);
486 int InsetInclude::descent(BufferView * bv, LyXFont const & font) const
488 return preview_->previewReady() ?
489 preview_->pimage()->descent() : InsetButton::descent(bv, font);
493 int InsetInclude::width(BufferView * bv, LyXFont const & font) const
495 return preview_->previewReady() ?
496 preview_->pimage()->width() : InsetButton::width(bv, font);
500 void InsetInclude::draw(BufferView * bv, LyXFont const & font, int y,
501 float & xx, bool b) const
503 if (!preview_->previewReady()) {
504 InsetButton::draw(bv, font, y, xx, b);
508 int const x = int(xx);
509 int const w = width(bv, font);
510 int const d = descent(bv, font);
511 int const a = ascent(bv, font);
514 bv->painter().image(x, y - a, w, h,
515 *(preview_->pimage()->image(*this, *bv)));
525 void InsetInclude::addPreview(grfx::PreviewLoader & ploader) const
527 lyxerr << "InsetInclude::addPreview" << endl;
528 preview_->addPreview(ploader);
532 bool InsetInclude::PreviewImpl::previewWanted() const
534 return parent().params_.flag == InsetInclude::INPUT;
538 string const InsetInclude::PreviewImpl::latexString() const
540 if (!view() || !view()->buffer())
544 parent().latex(view()->buffer(), os, false, false);
546 // This fails if the file has a relative path.
547 // return os.str().c_str();
549 // I would /really/ like not to do this...
552 string file = rtrim(split(os.str().c_str(), command, '{'), "}");
554 if (!AbsolutePath(file))
555 file = MakeAbsPath(file, view()->buffer()->filePath());
558 out << command << '{' << file << '}' << endl;
560 return out.str().c_str();