]> git.lyx.org Git - features.git/blob - src/insets/insetinclude.C
time to recompile everything: I removed #include directives from headers here and...
[features.git] / src / insets / insetinclude.C
1 #include <config.h>
2
3 #ifdef __GNUG__
4 #pragma implementation
5 #endif
6
7 #include "insetinclude.h"
8 #include "buffer.h"
9 #include "bufferlist.h"
10 #include "BufferView.h"
11 #include "debug.h"
12 #include "lyxrc.h"
13 #include "frontends/LyXView.h"
14 #include "LaTeXFeatures.h"
15 #include "gettext.h"
16
17 #include "frontends/Dialogs.h"
18
19 #include "support/filetools.h"
20 #include "support/FileInfo.h"
21 #include "support/lstrings.h"
22
23 #include <cstdlib>
24
25
26 using std::ostream;
27 using std::endl;
28 using std::vector;
29 using std::pair;
30
31 extern BufferList bufferlist;
32
33 namespace {
34
35 string const uniqueID()
36 {
37         static unsigned int seed = 1000;
38
39         ostringstream ost;
40         ost << "file" << ++seed;
41
42         // Needed if we use lyxstring.
43         return ost.str().c_str();
44 }
45
46 } // namespace anon
47
48
49 InsetInclude::InsetInclude(Params const & p)
50         : params_(p), include_label(uniqueID())
51 {}
52
53
54 InsetInclude::InsetInclude(InsetCommandParams const & p, Buffer const & b)
55         : include_label(uniqueID())
56 {
57         params_.cparams = p;
58         params_.masterFilename_ = b.fileName();
59 }
60
61
62 InsetInclude::~InsetInclude()
63 {
64         hideDialog();
65 }
66
67
68 InsetInclude::Params const & InsetInclude::params() const
69 {
70         return params_;
71 }
72
73
74 bool InsetInclude::Params::operator==(Params const & o) const
75 {
76         if (cparams == o.cparams && flag == o.flag &&
77             noload == o.noload && masterFilename_ == o.masterFilename_)
78                 return true;
79
80         return false;
81 }
82
83
84 bool InsetInclude::Params::operator!=(Params const & o) const
85 {
86         return !(*this == o);
87 }
88
89
90 void InsetInclude::set(Params const & p)
91 {
92         params_ = p;
93
94         // Just to be safe...
95         string command;
96
97         switch (params_.flag) {
98                 case INCLUDE:
99                         command="include";
100                         break;
101                 case VERB:
102                         command="verbatiminput";
103                         break;
104                 case INPUT:
105                         command="input";
106                         break;
107                 case VERBAST:
108                         command="verbatiminput*";
109                         break;
110         }
111
112         params_.cparams.setCmdName(command);
113 }
114
115
116 Inset * InsetInclude::clone(Buffer const & buffer, bool) const
117 {
118         Params p(params_);
119         p.masterFilename_ = buffer.fileName();
120
121         return new InsetInclude(p);
122 }
123
124
125 void InsetInclude::edit(BufferView * bv, int, int, mouse_button::state)
126 {
127         bv->owner()->getDialogs()->showInclude(this);
128 }
129
130
131 void InsetInclude::edit(BufferView * bv, bool)
132 {
133         edit(bv, 0, 0, mouse_button::none);
134 }
135
136
137 void InsetInclude::write(Buffer const *, ostream & os) const
138 {
139         os << "Include " << params_.cparams.getCommand() << "\n";
140 }
141
142
143 void InsetInclude::read(Buffer const *, LyXLex & lex)
144 {
145         params_.cparams.read(lex);
146
147         if (params_.cparams.getCmdName() == "include")
148                 params_.flag = INCLUDE;
149         else if (params_.cparams.getCmdName() == "input")
150                 params_.flag = INPUT;
151         /* FIXME: is this logic necessary now ? */
152         else if (contains(params_.cparams.getCmdName(), "verbatim")) {
153                 params_.flag = VERB;
154                 if (params_.cparams.getCmdName() == "verbatiminput*")
155                         params_.flag = VERBAST;
156         }
157 }
158
159
160 bool InsetInclude::display() const
161 {
162         return !(params_.flag == INPUT);
163 }
164
165
166 string const InsetInclude::getScreenLabel(Buffer const *) const
167 {
168         string temp;
169
170         switch (params_.flag) {
171                 case INPUT: temp += _("Input"); break;
172                 case VERB: temp += _("Verbatim Input"); break;
173                 case VERBAST: temp += _("Verbatim Input*"); break;
174                 case INCLUDE: temp += _("Include"); break;
175         }
176
177         temp += ": ";
178
179         if (params_.cparams.getContents().empty())
180                 temp += "???";
181         else
182                 temp += params_.cparams.getContents();
183
184         return temp;
185 }
186
187
188 string const InsetInclude::getRelFileBaseName() const
189 {
190         return OnlyFilename(ChangeExtension(params_.cparams.getContents(), string()));
191 }
192
193
194 string const InsetInclude::getFileName() const
195 {
196         return MakeAbsPath(params_.cparams.getContents(),
197                            OnlyPath(getMasterFilename()));
198 }
199
200
201 string const InsetInclude::getMasterFilename() const
202 {
203         return params_.masterFilename_;
204 }
205
206
207 bool InsetInclude::loadIfNeeded() const
208 {
209         if (params_.noload || isVerbatim())
210                 return false;
211
212         if (!IsLyXFilename(getFileName()))
213                 return false;
214
215         if (bufferlist.exists(getFileName()))
216                 return true;
217
218         // the readonly flag can/will be wrong, not anymore I think.
219         FileInfo finfo(getFileName());
220         if (!finfo.isOK())
221                 return false;
222
223         return bufferlist.readFile(getFileName(), !finfo.writable()) != 0;
224 }
225
226
227 int InsetInclude::latex(Buffer const * buffer, ostream & os,
228                         bool /*fragile*/, bool /*fs*/) const
229 {
230         string incfile(params_.cparams.getContents());
231
232         // Do nothing if no file name has been specified
233         if (incfile.empty())
234                 return 0;
235
236         if (loadIfNeeded()) {
237                 Buffer * tmp = bufferlist.getBuffer(getFileName());
238
239                 // FIXME: this should be a GUI warning
240                 if (tmp->params.textclass != buffer->params.textclass) {
241                         lyxerr << "WARNING: Included file `"
242                                << MakeDisplayPath(getFileName())
243                                << "' has textclass `"
244                                << tmp->params.getLyXTextClass().name()
245                                << "' while parent file has textclass `"
246                                << buffer->params.getLyXTextClass().name()
247                                << "'." << endl;
248                         //return 0;
249                 }
250
251                 // write it to a file (so far the complete file)
252                 string writefile = ChangeExtension(getFileName(), ".tex");
253
254                 if (!buffer->tmppath.empty()
255                     && !buffer->niceFile) {
256                         incfile = subst(incfile, '/','@');
257 #ifdef __EMX__
258                         incfile = subst(incfile, ':', '$');
259 #endif
260                         writefile = AddName(buffer->tmppath, incfile);
261                 } else
262                         writefile = getFileName();
263                 writefile = ChangeExtension(writefile, ".tex");
264                 lyxerr[Debug::LATEX] << "incfile:" << incfile << endl;
265                 lyxerr[Debug::LATEX] << "writefile:" << writefile << endl;
266
267                 tmp->markDepClean(buffer->tmppath);
268
269                 tmp->makeLaTeXFile(writefile,
270                                    OnlyPath(getMasterFilename()),
271                                    buffer->niceFile, true);
272         }
273
274         if (isVerbatim()) {
275                 os << '\\' << params_.cparams.getCmdName() << '{' << incfile << '}';
276         } else if (params_.flag == INPUT) {
277                 // \input wants file with extension (default is .tex)
278                 if (!IsLyXFilename(getFileName())) {
279                         os << '\\' << params_.cparams.getCmdName() << '{' << incfile << '}';
280                 } else {
281                         os << '\\' << params_.cparams.getCmdName() << '{'
282                            << ChangeExtension(incfile, ".tex")
283                            <<  '}';
284                 }
285         } else {
286                 // \include don't want extension and demands that the
287                 // file really have .tex
288                 os << '\\' << params_.cparams.getCmdName() << '{'
289                    << ChangeExtension(incfile, string())
290                    << '}';
291         }
292
293         return 0;
294 }
295
296
297 int InsetInclude::ascii(Buffer const *, ostream & os, int) const
298 {
299         if (isVerbatim())
300                 os << GetFileContents(getFileName());
301         return 0;
302 }
303
304
305 int InsetInclude::linuxdoc(Buffer const * buffer, ostream & os) const
306 {
307         string incfile(params_.cparams.getContents());
308
309         // Do nothing if no file name has been specified
310         if (incfile.empty())
311                 return 0;
312
313         if (loadIfNeeded()) {
314                 Buffer * tmp = bufferlist.getBuffer(getFileName());
315
316                 // write it to a file (so far the complete file)
317                 string writefile = ChangeExtension(getFileName(), ".sgml");
318                 if (!buffer->tmppath.empty() && !buffer->niceFile) {
319                         incfile = subst(incfile, '/','@');
320                         writefile = AddName(buffer->tmppath, incfile);
321                 } else
322                         writefile = getFileName();
323
324                 if (IsLyXFilename(getFileName()))
325                         writefile = ChangeExtension(writefile, ".sgml");
326
327                 lyxerr[Debug::LATEX] << "incfile:" << incfile << endl;
328                 lyxerr[Debug::LATEX] << "writefile:" << writefile << endl;
329
330                 tmp->makeLinuxDocFile(writefile, buffer->niceFile, true);
331         }
332
333         if (isVerbatim()) {
334                 os << "<![CDATA["
335                    << GetFileContents(getFileName())
336                    << "]]>";
337         } else
338                 os << '&' << include_label << ';';
339
340         return 0;
341 }
342
343
344 int InsetInclude::docbook(Buffer const * buffer, ostream & os,
345                           bool /*mixcont*/) const
346 {
347         string incfile(params_.cparams.getContents());
348
349         // Do nothing if no file name has been specified
350         if (incfile.empty())
351                 return 0;
352
353         if (loadIfNeeded()) {
354                 Buffer * tmp = bufferlist.getBuffer(getFileName());
355
356                 // write it to a file (so far the complete file)
357                 string writefile = ChangeExtension(getFileName(), ".sgml");
358                 if (!buffer->tmppath.empty() && !buffer->niceFile) {
359                         incfile = subst(incfile, '/','@');
360                         writefile = AddName(buffer->tmppath, incfile);
361                 } else
362                         writefile = getFileName();
363                 if (IsLyXFilename(getFileName()))
364                         writefile = ChangeExtension(writefile, ".sgml");
365
366                 lyxerr[Debug::LATEX] << "incfile:" << incfile << endl;
367                 lyxerr[Debug::LATEX] << "writefile:" << writefile << endl;
368
369                 tmp->makeDocBookFile(writefile, buffer->niceFile, true);
370         }
371
372         if (isVerbatim()) {
373                 os << "<inlinegraphic fileref=\""
374                    << '&' << include_label << ';'
375                    << "\" format=\"linespecific\">";
376         } else
377                 os << '&' << include_label << ';';
378
379         return 0;
380 }
381
382
383 void InsetInclude::validate(LaTeXFeatures & features) const
384 {
385
386         string incfile(params_.cparams.getContents());
387         string writefile;
388
389         Buffer const * const b = bufferlist.getBuffer(getMasterFilename());
390
391         if (b && !b->tmppath.empty() && !b->niceFile && !isVerbatim()) {
392                 incfile = subst(incfile, '/','@');
393                 writefile = AddName(b->tmppath, incfile);
394         } else
395                 writefile = getFileName();
396
397         if (IsLyXFilename(getFileName()))
398                 writefile = ChangeExtension(writefile, ".sgml");
399
400         features.includeFile(include_label, writefile);
401
402         if (isVerbatim())
403                 features.require("verbatim");
404
405         // Here we must do the fun stuff...
406         // Load the file in the include if it needs
407         // to be loaded:
408         if (loadIfNeeded()) {
409                 // a file got loaded
410                 Buffer * const tmp = bufferlist.getBuffer(getFileName());
411                 if (tmp) {
412                         if (b)
413                                 tmp->niceFile = b->niceFile;
414                         tmp->validate(features);
415                 }
416         }
417 }
418
419
420 vector<string> const InsetInclude::getLabelList() const
421 {
422         vector<string> l;
423
424         if (loadIfNeeded()) {
425                 Buffer * tmp = bufferlist.getBuffer(getFileName());
426                 tmp->setParentName("");
427                 l = tmp->getLabelList();
428                 tmp->setParentName(getMasterFilename());
429         }
430
431         return l;
432 }
433
434
435 vector<pair<string,string> > const InsetInclude::getKeys() const
436 {
437         vector<pair<string,string> > keys;
438
439         if (loadIfNeeded()) {
440                 Buffer * tmp = bufferlist.getBuffer(getFileName());
441                 tmp->setParentName("");
442                 keys = tmp->getBibkeyList();
443                 tmp->setParentName(getMasterFilename());
444         }
445
446         return keys;
447 }