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