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