]> git.lyx.org Git - lyx.git/blob - src/insets/insetexternal.C
Add a bunch of c_str() for string stream uses; remove lyxfunc symbol-insert.
[lyx.git] / src / insets / insetexternal.C
1 /* This file is part of
2  * ======================================================
3  * 
4  *           LyX, The Document Processor
5  *       
6  *          Copyright 1995 Matthias Ettrich
7  *          Copyright 1995-2000 The LyX Team.
8  *
9  * ====================================================== */
10
11 #include <config.h>
12
13 #ifdef __GNUG__
14 #pragma implementation
15 #endif
16
17 #include FORMS_H_LOCATION
18 #include <cstdio>
19
20 #include "insetexternal.h"
21 #include "ExternalTemplate.h"
22 #include "lyx_gui_misc.h" // CancelCloseBoxCB
23 #include "BufferView.h"
24 #include "buffer.h"
25 #include "filedlg.h"
26 #include "lyx_main.h"
27 #include "LaTeXFeatures.h"
28 #include "support/filetools.h"
29 #include "support/lstrings.h"
30 #include "support/path.h"
31 #include "support/syscall.h"
32
33 using std::endl;
34
35
36 InsetExternal::InsetExternal() 
37         : form_external(0)
38 {
39         tempname = TmpFileName();
40 }
41
42
43 InsetExternal::~InsetExternal()
44 {
45         lyx::unlink(tempname);
46 }
47
48
49 extern "C"
50 void ExternalTemplateCB(FL_OBJECT * ob, long data)
51 {
52         InsetExternal::templateCB(ob, data);
53 }
54
55
56 extern "C"
57 void ExternalBrowseCB(FL_OBJECT * ob, long data)
58 {
59         InsetExternal::browseCB(ob, data);
60 }
61
62
63 extern "C"
64 void ExternalEditCB(FL_OBJECT * ob, long data)
65 {
66         InsetExternal::editCB(ob, data);
67 }
68
69
70 extern "C"
71 void ExternalViewCB(FL_OBJECT * ob, long data)
72 {
73         InsetExternal::viewCB(ob, data);
74 }
75
76
77 extern "C"
78 void ExternalUpdateCB(FL_OBJECT * ob, long data)
79 {
80         InsetExternal::updateCB(ob, data);
81 }
82
83
84 extern "C"
85 void ExternalOKCB(FL_OBJECT * ob, long data)
86 {
87         InsetExternal::okCB(ob, data);
88 }
89
90
91 extern "C"
92 void ExternalCancelCB(FL_OBJECT * ob, long data)
93 {
94         InsetExternal::cancelCB(ob, data);
95 }
96
97
98 void InsetExternal::templateCB(FL_OBJECT * ob, long)
99 {
100         Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
101         InsetExternal * inset = holder->inset;
102         ExternalTemplate et = inset->getTemplate(inset->getCurrentTemplate());
103         // Update the help text
104         fl_clear_browser(inset->form_external->helptext);
105         fl_addto_browser(inset->form_external->helptext, et.helpText.c_str());
106         fl_set_browser_topline(inset->form_external->helptext, 0);
107 }
108
109
110 void InsetExternal::browseCB(FL_OBJECT * ob, long)
111 {
112         Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
113         InsetExternal * inset = holder->inset;
114
115         static string current_path;
116         static int once = 0;
117         LyXFileDlg fileDlg;
118         
119         string p = inset->filename;
120         string buf = MakeAbsPath(holder->view->buffer()->fileName());
121         string buf2 = OnlyPath(buf);
122         if (!p.empty()) {
123                 buf = MakeAbsPath(p, buf2);
124                 buf = OnlyPath(buf);
125         } else {
126                 buf = OnlyPath(holder->view->buffer()->fileName());
127         }
128        
129         fileDlg.SetButton(0, _("Document"), buf); 
130
131         /// Determine the template file extension
132         ExternalTemplate et = inset->getTemplate(inset->getCurrentTemplate());
133         string regexp = et.fileRegExp;
134         if (regexp.empty()) {
135                 regexp = "*";
136         }
137
138         bool error = false;
139         do {
140                 if (once) {
141                         p = fileDlg.Select(_("External inset file"),
142                                            current_path,
143                                            regexp, string());
144                 } else {
145                         p = fileDlg.Select(_("External inset file"), buf,
146                                            regexp, string());
147                 }
148
149                 if (p.empty()) return;
150
151                 buf = MakeRelPath(p, buf2);
152                 current_path = OnlyPath(p);
153                 once = 1;
154                 
155                 if (contains(p, "#") || contains(p, "~") || contains(p, "$")
156                     || contains(p, "%")) {
157                         WriteAlert(_("Filename can't contain any "
158                                      "of these characters:"),
159                                    // xgettext:no-c-format
160                                    _("'#', '~', '$' or '%'.")); 
161                         error = true;
162                 }
163         } while (error);
164
165         if (inset->form_external) 
166                 fl_set_input(inset->form_external->filename, buf.c_str());
167         
168 }
169
170
171 void InsetExternal::editCB(FL_OBJECT * ob, long)
172 {
173         Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
174         InsetExternal * inset = holder->inset;
175         inset->doApply(holder->view);
176         inset->doEdit(holder->view);
177 }
178
179
180 void InsetExternal::viewCB(FL_OBJECT * ob, long)
181 {
182         Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
183         InsetExternal * inset = holder->inset;
184         inset->doApply(holder->view);
185         inset->doView(holder->view);
186 }
187
188
189 void InsetExternal::updateCB(FL_OBJECT * ob, long)
190 {
191         Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
192         InsetExternal * inset = holder->inset;
193         inset->doApply(holder->view);
194         inset->doUpdate(holder->view);
195 }
196
197
198 void InsetExternal::okCB(FL_OBJECT * ob, long data)
199 {
200         Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
201         InsetExternal * inset = holder->inset;
202         inset->doApply(holder->view);
203         cancelCB(ob,data);
204 }
205
206
207 void InsetExternal::doApply(BufferView * bufview)
208 {
209         bool update = false;
210         if (templatename != getCurrentTemplate()) {
211                 templatename = getCurrentTemplate();
212                 update = true;
213         }
214         if (filename != fl_get_input(form_external->filename)) {
215                 filename = fl_get_input(form_external->filename);
216                 update = true;
217         }
218         if (parameters != fl_get_input(form_external->parameters)) {
219                 parameters = fl_get_input(form_external->parameters);
220                 update = true;
221         }
222
223         if (update) {
224                 // The text might have change,
225                 // so we should update the button look
226                 bufview->updateInset(this, true);
227         }
228 }
229
230
231 void InsetExternal::cancelCB(FL_OBJECT * ob, long)
232 {
233         Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
234
235         InsetExternal * inset = holder->inset;
236         // BufferView * bv = holder->view;
237
238         if (inset->form_external) {
239                 fl_hide_form(inset->form_external->form_external);
240                 fl_free_form(inset->form_external->form_external);
241                 inset->form_external = 0;
242         }
243 }
244
245
246 string const InsetExternal::EditMessage() const
247 {
248         ExternalTemplate const & et = getTemplate(templatename);
249         return doSubstitution(0, et.guiName);
250 }
251
252
253 void InsetExternal::Edit(BufferView * bv,
254                          int /*x*/, int /*y*/, unsigned int /*button*/)
255 {
256         static int ow = -1, oh;
257
258         if (bv->buffer()->isReadonly())
259                 WarnReadonly(bv->buffer()->fileName());
260
261         if (!form_external) {
262                 form_external = create_form_form_external();
263                 holder.inset = this;
264                 //              form_external->ok->u_vdata = &holder;
265                 form_external->form_external->u_vdata = &holder;
266                 fl_set_form_atclose(form_external->form_external,
267                                     CancelCloseBoxCB, 0);
268         }
269         holder.view = bv;
270         fl_addto_choice(form_external->templatechoice,
271                         getTemplateString().c_str());
272         fl_set_input(form_external->filename, filename.c_str());
273         fl_set_input(form_external->parameters, parameters.c_str());
274         if (!templatename.empty()) {
275                 fl_set_choice(form_external->templatechoice,
276                               getTemplateNumber(templatename));
277         }
278         // Update the help text
279         templateCB(form_external->templatechoice, 0);
280
281         ExternalTemplate const & et = getTemplate(templatename);
282         if (et.automaticProduction) {
283                 fl_deactivate_object(form_external->update);
284                 fl_set_object_lcol(form_external->update, FL_INACTIVE);
285         } else {
286                 fl_activate_object(form_external->update);
287                 fl_set_object_lcol(form_external->update, FL_BLACK);
288         }
289
290         if (form_external->form_external->visible) {
291                 fl_raise_form(form_external->form_external);
292         } else {
293                 fl_show_form(form_external->form_external,
294                              FL_PLACE_MOUSE | FL_FREE_SIZE,
295                              FL_FULLBORDER, _("Insert external inset"));
296                 if (ow < 0) {
297                         ow = form_external->form_external->w;
298                         oh = form_external->form_external->h;
299                 }
300                 fl_set_form_minsize(form_external->form_external, ow, oh);
301         }
302 }
303
304
305 void InsetExternal::Write(Buffer const *, std::ostream & os) const
306 {
307         os << "External " << templatename << ",\"" << filename 
308            << "\",\"" << parameters << "\"\n";
309 }
310
311
312 void InsetExternal::Read(Buffer const *, LyXLex & lex)
313 {
314         lex.EatLine();
315         string const format = lex.GetString();
316         string::size_type const pos1 = format.find(",");
317         templatename = format.substr(0, pos1);
318         string::size_type const pos2 = format.find("\",\"", pos1);
319         filename = format.substr(pos1 + 2, pos2 - (pos1 + 2));
320         parameters = format.substr(pos2 + 3, format.length() - (pos2 + 4));
321
322         lyxerr << templatename << " " << filename << " " << parameters << endl;
323 }
324
325
326 int InsetExternal::write(string const & format,
327                          Buffer const * buf, std::ostream & os) const
328 {
329         ExternalTemplate const & et = getTemplate(templatename);
330         ExternalTemplate::Formats::const_iterator cit =
331                 et.formats.find(format);
332         if (cit == et.formats.end()) {
333                 lyxerr << "External template format '" << format
334                        << "' not specified in template " << templatename
335                        << endl;
336                 return 0;
337         }
338         
339         if (et.automaticProduction) {
340                 executeCommand(doSubstitution(buf,
341                                               (*cit).second.updateCommand),
342                                buf);
343         }
344         
345         os << doSubstitution(buf, (*cit).second.product);
346         return 0; // CHECK
347 }
348
349
350 int InsetExternal::Latex(Buffer const * buf,
351                          std::ostream & os, bool, bool) const
352 {
353         return write("LaTeX", buf, os);
354 }
355
356
357 int InsetExternal::Ascii(Buffer const * buf, std::ostream & os, int) const
358 {
359         return write("Ascii", buf, os);
360 }
361
362
363 int InsetExternal::Linuxdoc(Buffer const * buf, std::ostream & os) const
364 {
365         return write("LinuxDoc", buf, os);
366 }
367
368
369 int InsetExternal::DocBook(Buffer const * buf, std::ostream & os) const
370 {
371         return write("DocBook", buf, os);
372 }
373
374
375 void InsetExternal::Validate(LaTeXFeatures & features) const
376 {
377         ExternalTemplate const & et = getTemplate(templatename);
378         ExternalTemplate::Formats::const_iterator cit =
379                 et.formats.find("LaTeX");
380         if (cit == et.formats.end()) {
381                 return;
382         }
383         
384         if (!(*cit).second.requirement.empty()) {
385                 features.require((*cit).second.requirement);
386         }
387         if (!(*cit).second.preamble.empty()) {
388                 features.externalPreambles += (*cit).second.preamble + "\n";
389         }
390 }
391
392
393 Inset * InsetExternal::Clone(Buffer const &) const
394 {
395         InsetExternal * inset = new InsetExternal();
396         inset->templatename = templatename;
397         inset->filename = filename;
398         inset->parameters = parameters;
399         return inset;
400 }
401
402
403 string const InsetExternal::getScreenLabel() const
404 {
405         if (templatename.empty()) {
406                 return _("External");
407         } else {
408                 ExternalTemplate const & et = getTemplate(templatename);
409                 return doSubstitution(0, et.guiName);
410         }
411 }
412
413
414 void InsetExternal::doUpdate(BufferView const * bv) const
415 {
416         ExternalTemplate const & et = getTemplate(getCurrentTemplate());
417         ExternalTemplate::Formats::const_iterator cit =
418                 et.formats.find("LaTeX");
419         if (cit == et.formats.end())
420                 return;
421         
422         executeCommand(doSubstitution(bv->buffer(),
423                                       (*cit).second.updateCommand),
424                        bv->buffer());
425 }
426
427
428 void InsetExternal::doView(BufferView const * bv) const
429 {
430         automaticUpdate(bv);
431         ExternalTemplate const & et = getTemplate(getCurrentTemplate());
432         executeCommand(doSubstitution(bv->buffer(), et.viewCommand),
433                        bv->buffer());
434 }
435
436
437 void InsetExternal::doEdit(BufferView const * bv) const
438 {
439         automaticUpdate(bv);
440         ExternalTemplate const & et = getTemplate(getCurrentTemplate());
441         executeCommand(doSubstitution(bv->buffer(), et.editCommand),
442                        bv->buffer());
443 }
444
445
446 void InsetExternal::executeCommand(string const & s,
447                                    Buffer const * buffer) const
448 {
449         string buf = MakeAbsPath(buffer->fileName());
450         string path = OnlyPath(buf);
451         Path p(path);
452         Systemcalls one;
453         if (lyxerr.debugging()) {
454                 lyxerr << "Executing '" << s << "' in '"
455                        << path << "'" << endl;
456         }
457         one.startscript(Systemcalls::Wait, s);
458 }
459
460
461 void InsetExternal::automaticUpdate(BufferView const * bv) const
462 {
463         ExternalTemplate const & et = getTemplate(templatename);
464         if (et.automaticProduction) {
465                 doUpdate(bv);
466         }
467 }
468
469
470 string const InsetExternal::doSubstitution(Buffer const * buffer,
471                                      string const & s) const
472 {
473         string result;
474         string const basename = ChangeExtension(filename, string());
475         result = subst(s, "$$FName", filename);
476         result = subst(result, "$$Basename", basename);
477         result = subst(result, "$$Parameters", parameters);
478         result = ReplaceEnvironmentPath(result);
479         result = subst(result, "$$Tempname", tempname);
480         result = subst(result, "$$Sysdir", system_lyxdir);
481         
482         // Handle the $$Contents(filename) syntax
483         if (contains(result, "$$Contents(\"")) {
484
485                 string::size_type const pos = result.find("$$Contents(\"");
486                 string::size_type const end = result.find("\")", pos);
487                 string const file = result.substr(pos + 12, end - (pos + 12));
488                 string contents;
489                 if (buffer) {
490                         // Make sure we are in the directory of the buffer
491                         string const buf = MakeAbsPath(buffer->fileName());
492                         string const path = OnlyPath(buf);
493                         Path p(path);
494                         contents = GetFileContents(file);
495                 } else {
496                         contents = GetFileContents(file);
497                 }
498                 result = subst(result,
499                                ("$$Contents(\"" + file + "\")").c_str(),
500                                contents);
501         }
502
503         return result;
504 }
505
506
507 string const InsetExternal::getCurrentTemplate() const
508 {
509         return getTemplateName(fl_get_choice(form_external->templatechoice));
510 }
511
512
513 ExternalTemplate const InsetExternal::getTemplate(string const & name) const
514 {
515         ExternalTemplateManager::Templates::iterator i = 
516                 ExternalTemplateManager::get().getTemplates().find(name);
517         // Make sure that the template exists in the map
518         if (i == ExternalTemplateManager::get().getTemplates().end()) {
519                 lyxerr << "Unknown external material template: "
520                        << name << endl;
521                 return ExternalTemplate();
522         }
523         return (*i).second;
524 }
525
526
527 int InsetExternal::getTemplateNumber(string const & name) const
528 {
529         int i = 1;
530         ExternalTemplateManager::Templates::const_iterator i1, i2;
531         i1 = ExternalTemplateManager::get().getTemplates().begin();
532         i2 = ExternalTemplateManager::get().getTemplates().end();
533         for (; i1 != i2; ++i1) {
534                 if ((*i1).second.lyxName == name)
535                         return i;
536                 ++i;
537         }
538         // This should never happen
539         Assert(false);
540         return 0;
541 }
542
543
544 string const InsetExternal::getTemplateName(int i) const
545 {
546         ExternalTemplateManager::Templates::const_iterator i1;
547         i1 = ExternalTemplateManager::get().getTemplates().begin();
548         for (int n = 1; n < i; ++n) {
549                 ++i1;
550         }
551         return (*i1).second.lyxName;
552 }
553
554
555 string const InsetExternal::getTemplateString() const
556 {
557         string result;
558         bool first = true;
559         ExternalTemplateManager::Templates::const_iterator i1, i2;
560         i1 = ExternalTemplateManager::get().getTemplates().begin();
561         i2 = ExternalTemplateManager::get().getTemplates().end();
562         for (; i1 != i2; ++i1) {
563                 if (!first) {
564                         result += "|";
565                 } else {
566                         first = false;
567                 }
568                 result += (*i1).second.lyxName;
569         }
570         return result;
571 }