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