]> git.lyx.org Git - lyx.git/blob - src/insets/insetinclude.C
2001-12-28 Lars Gullik Bj�nnes <larsbj@birdstep.com>
[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 {
57         params_.cparams = p;
58         params_.masterFilename_ = b.fileName();
59         include_label = unique_id();
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         bool const ro = !finfo.writable();
222         return bufferlist.readFile(getFileName(), ro) != 0;
223 }
224
225
226 int InsetInclude::latex(Buffer const * buffer, ostream & os,
227                         bool /*fragile*/, bool /*fs*/) const
228 {
229         string incfile(params_.cparams.getContents());
230         
231         // Do nothing if no file name has been specified
232         if (incfile.empty())
233                 return 0;
234    
235         if (loadIfNeeded()) {
236                 Buffer * tmp = bufferlist.getBuffer(getFileName());
237
238                 // FIXME: this should be a GUI warning
239                 if (tmp->params.textclass != buffer->params.textclass) {
240                         lyxerr << "WARNING: Included file `"
241                                << MakeDisplayPath(getFileName())
242                                << "' has textclass `"
243                                << textclasslist.NameOfClass(tmp->params.textclass)
244                                << "' while parent file has textclass `"
245                                << textclasslist.NameOfClass(buffer->params.textclass)
246                                << "'." << endl;
247                         //return 0;
248                 }
249                 
250                 // write it to a file (so far the complete file)
251                 string writefile = ChangeExtension(getFileName(), ".tex");
252
253                 if (!buffer->tmppath.empty()
254                     && !buffer->niceFile) {
255                         incfile = subst(incfile, '/','@');
256 #ifdef __EMX__
257                         incfile = subst(incfile, ':', '$');
258 #endif
259                         writefile = AddName(buffer->tmppath, incfile);
260                 } else
261                         writefile = getFileName();
262                 writefile = ChangeExtension(writefile, ".tex");
263                 lyxerr[Debug::LATEX] << "incfile:" << incfile << endl;
264                 lyxerr[Debug::LATEX] << "writefile:" << writefile << endl;
265                 
266                 tmp->markDepClean(buffer->tmppath);
267                 
268                 tmp->makeLaTeXFile(writefile,
269                                    OnlyPath(getMasterFilename()),
270                                    buffer->niceFile, true);
271         }
272
273         if (isVerbatim()) {
274                 os << '\\' << params_.cparams.getCmdName() << '{' << incfile << '}';
275         } else if (params_.flag == INPUT) {
276                 // \input wants file with extension (default is .tex)
277                 if (!IsLyXFilename(getFileName())) {
278                         os << '\\' << params_.cparams.getCmdName() << '{' << incfile << '}';
279                 } else {
280                         os << '\\' << params_.cparams.getCmdName() << '{'
281                            << ChangeExtension(incfile, ".tex")
282                            <<  '}';
283                 }
284         } else {
285                 // \include don't want extension and demands that the
286                 // file really have .tex
287                 os << '\\' << params_.cparams.getCmdName() << '{'
288                    << ChangeExtension(incfile, string())
289                    << '}';
290         }
291
292         return 0;
293 }
294
295
296 int InsetInclude::ascii(Buffer const *, std::ostream & os, int) const
297 {
298         if (isVerbatim())
299                 os << GetFileContents(getFileName());
300         return 0;
301 }
302
303
304 int InsetInclude::linuxdoc(Buffer const * buffer, ostream & os) const
305 {
306         string incfile(params_.cparams.getContents());
307         
308         // Do nothing if no file name has been specified
309         if (incfile.empty())
310                 return 0;
311    
312         if (loadIfNeeded()) {
313                 Buffer * tmp = bufferlist.getBuffer(getFileName());
314
315                 // write it to a file (so far the complete file)
316                 string writefile = ChangeExtension(getFileName(), ".sgml");
317                 if (!buffer->tmppath.empty() && !buffer->niceFile) {
318                         incfile = subst(incfile, '/','@');
319                         writefile = AddName(buffer->tmppath, incfile);
320                 } else
321                         writefile = getFileName();
322
323                 if (IsLyXFilename(getFileName()))
324                         writefile = ChangeExtension(writefile, ".sgml");
325
326                 lyxerr[Debug::LATEX] << "incfile:" << incfile << endl;
327                 lyxerr[Debug::LATEX] << "writefile:" << writefile << endl;
328                 
329                 tmp->makeLinuxDocFile(writefile, buffer->niceFile, true);
330         }
331
332         if (isVerbatim()) {
333                 os << "<inlinegraphic fileref=\"" << '&' << include_label << ';'
334                    << "\" format=\"linespecific\">"
335                    << "</inlinegraphic>";
336         } else
337                 os << '&' << include_label << ';';
338         
339         return 0;
340 }
341
342
343 int InsetInclude::docbook(Buffer const * buffer, ostream & os) const
344 {
345         string incfile(params_.cparams.getContents());
346
347         // Do nothing if no file name has been specified
348         if (incfile.empty())
349                 return 0;
350    
351         if (loadIfNeeded()) {
352                 Buffer * tmp = bufferlist.getBuffer(getFileName());
353
354                 // write it to a file (so far the complete file)
355                 string writefile = ChangeExtension(getFileName(), ".sgml");
356                 if (!buffer->tmppath.empty() && !buffer->niceFile) {
357                         incfile = subst(incfile, '/','@');
358                         writefile = AddName(buffer->tmppath, incfile);
359                 } else
360                         writefile = getFileName();
361                 if (IsLyXFilename(getFileName()))
362                         writefile = ChangeExtension(writefile, ".sgml");
363
364                 lyxerr[Debug::LATEX] << "incfile:" << incfile << endl;
365                 lyxerr[Debug::LATEX] << "writefile:" << writefile << endl;
366                 
367                 tmp->makeDocBookFile(writefile, buffer->niceFile, true);
368         }
369
370         if (isVerbatim()) {
371                 os << "<inlinegraphic fileref=\"" << '&' << include_label << ';'
372                    << "\" format=\"linespecific\">"
373                    << "</inlinegraphic>";
374         } else
375                 os << '&' << include_label << ';';
376         
377         return 0;
378 }
379
380
381 void InsetInclude::validate(LaTeXFeatures & features) const
382 {
383
384         string incfile(params_.cparams.getContents());
385         string writefile;
386
387         Buffer const * const b = bufferlist.getBuffer(getMasterFilename());
388
389         if (b && !b->tmppath.empty() && b->niceFile) {
390                 incfile = subst(incfile, '/','@');
391                 writefile = AddName(b->tmppath, incfile);
392         } else
393                 writefile = getFileName();
394
395         if (IsLyXFilename(getFileName()))
396                 writefile = ChangeExtension(writefile, ".sgml");
397
398         features.includeFile(include_label, writefile);
399
400         if (isVerbatim())
401                 features.require("verbatim");
402
403         // Here we must do the fun stuff...
404         // Load the file in the include if it needs
405         // to be loaded:
406         if (loadIfNeeded()) {
407                 // a file got loaded
408                 Buffer const * const tmp = bufferlist.getBuffer(getFileName());
409                 if (tmp)
410                         tmp->validate(features);
411         }
412 }
413
414
415 vector<string> const InsetInclude::getLabelList() const
416 {
417         vector<string> l;
418
419         if (loadIfNeeded()) {
420                 Buffer * tmp = bufferlist.getBuffer(getFileName());
421                 tmp->setParentName("");
422                 l = tmp->getLabelList();
423                 tmp->setParentName(getMasterFilename());
424         }
425
426         return l;
427 }
428
429
430 vector<pair<string,string> > const InsetInclude::getKeys() const
431 {
432         vector<pair<string,string> > keys;
433         
434         if (loadIfNeeded()) {
435                 Buffer * tmp = bufferlist.getBuffer(getFileName());
436                 tmp->setParentName("");
437                 keys = tmp->getBibkeyList();
438                 tmp->setParentName(getMasterFilename());
439         }
440         
441         return keys;
442 }