1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1995 Matthias Ettrich
7 * Copyright 1995-2000 The LyX Team.
9 * ====================================================== */
14 #pragma implementation
17 #include FORMS_H_LOCATION
21 #include "insetexternal.h"
22 #include "ExternalTemplate.h"
23 #include "lyx_gui_misc.h" // CancelCloseBoxCB
24 #include "BufferView.h"
26 #include "frontends/FileDialog.h"
28 #include "LaTeXFeatures.h"
29 #include "support/filetools.h"
30 #include "support/lstrings.h"
31 #include "support/path.h"
32 #include "support/syscall.h"
33 #include "frontends/Dialogs.h" // redrawGUI
35 #ifdef SIGC_CXX_NAMESPACES
43 InsetExternal::InsetExternal()
46 tempname = lyx::tempName(string(), "lyxext");
47 r_ = Dialogs::redrawGUI.connect(slot(this, &InsetExternal::redraw));
51 InsetExternal::~InsetExternal()
53 lyx::unlink(tempname);
58 void InsetExternal::redraw()
60 if (form_external && form_external->form_external->visible)
61 fl_redraw_form(form_external->form_external);
66 void ExternalTemplateCB(FL_OBJECT * ob, long data)
68 InsetExternal::templateCB(ob, data);
73 void ExternalBrowseCB(FL_OBJECT * ob, long data)
75 InsetExternal::browseCB(ob, data);
80 void ExternalEditCB(FL_OBJECT * ob, long data)
82 InsetExternal::editCB(ob, data);
87 void ExternalViewCB(FL_OBJECT * ob, long data)
89 InsetExternal::viewCB(ob, data);
94 void ExternalUpdateCB(FL_OBJECT * ob, long data)
96 InsetExternal::updateCB(ob, data);
101 void ExternalOKCB(FL_OBJECT * ob, long data)
103 InsetExternal::okCB(ob, data);
108 void ExternalCancelCB(FL_OBJECT * ob, long data)
110 InsetExternal::cancelCB(ob, data);
114 void InsetExternal::templateCB(FL_OBJECT * ob, long)
116 Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
117 InsetExternal * inset = holder->inset;
118 ExternalTemplate et = inset->getTemplate(inset->getCurrentTemplate());
119 // Update the help text
120 fl_clear_browser(inset->form_external->helptext);
121 fl_addto_browser(inset->form_external->helptext, et.helpText.c_str());
122 fl_set_browser_topline(inset->form_external->helptext, 0);
126 void InsetExternal::browseCB(FL_OBJECT * ob, long)
128 Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
129 InsetExternal * inset = holder->inset;
131 static string current_path;
134 string p = inset->filename;
135 string buf = MakeAbsPath(holder->view->buffer()->fileName());
136 string buf2 = OnlyPath(buf);
138 buf = MakeAbsPath(p, buf2);
141 buf = OnlyPath(holder->view->buffer()->fileName());
144 FileDialog fileDlg(holder->view->owner(), _("Select external file"),
145 LFUN_SELECT_FILE_SYNC,
146 make_pair(string(_("Document")), string(buf)));
148 // FIXME: should have "nice name" for file type e.g. "Xfig files"
150 /// Determine the template file extension
151 ExternalTemplate et = inset->getTemplate(inset->getCurrentTemplate());
152 string regexp = et.fileRegExp;
153 if (regexp.empty()) {
161 string const path = (once) ? current_path : buf;
162 FileDialog::Result result = fileDlg.Select(path, regexp);
164 if (result.second.empty())
167 string p = result.second;
169 buf = MakeRelPath(p, buf2);
170 current_path = OnlyPath(p);
173 if (contains(p, "#") || contains(p, "~") || contains(p, "$")
174 || contains(p, "%")) {
175 WriteAlert(_("Filename can't contain any "
176 "of these characters:"),
177 // xgettext:no-c-format
178 _("'#', '~', '$' or '%'."));
183 if (inset->form_external)
184 fl_set_input(inset->form_external->filename, buf.c_str());
189 void InsetExternal::editCB(FL_OBJECT * ob, long)
191 Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
192 InsetExternal * inset = holder->inset;
193 inset->doApply(holder->view);
194 inset->doEdit(holder->view);
198 void InsetExternal::viewCB(FL_OBJECT * ob, long)
200 Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
201 InsetExternal * inset = holder->inset;
202 inset->doApply(holder->view);
203 inset->doView(holder->view);
207 void InsetExternal::updateCB(FL_OBJECT * ob, long)
209 Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
210 InsetExternal * inset = holder->inset;
211 inset->doApply(holder->view);
212 inset->doUpdate(holder->view);
216 void InsetExternal::okCB(FL_OBJECT * ob, long data)
218 Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
219 InsetExternal * inset = holder->inset;
220 inset->doApply(holder->view);
225 void InsetExternal::doApply(BufferView * bufview)
228 if (templatename != getCurrentTemplate()) {
229 templatename = getCurrentTemplate();
232 if (filename != fl_get_input(form_external->filename)) {
233 filename = fl_get_input(form_external->filename);
236 if (parameters != fl_get_input(form_external->parameters)) {
237 parameters = fl_get_input(form_external->parameters);
242 // The text might have change,
243 // so we should update the button look
244 bufview->updateInset(this, true);
249 void InsetExternal::cancelCB(FL_OBJECT * ob, long)
251 Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
253 InsetExternal * inset = holder->inset;
254 // BufferView * bv = holder->view;
256 if (inset->form_external) {
257 fl_hide_form(inset->form_external->form_external);
258 fl_free_form(inset->form_external->form_external);
259 inset->form_external = 0;
264 string const InsetExternal::EditMessage() const
266 ExternalTemplate const & et = getTemplate(templatename);
267 return doSubstitution(0, et.guiName);
271 void InsetExternal::Edit(BufferView * bv,
272 int /*x*/, int /*y*/, unsigned int /*button*/)
274 static int ow = -1, oh;
276 if (bv->buffer()->isReadonly())
277 WarnReadonly(bv->buffer()->fileName());
279 if (!form_external) {
280 form_external = create_form_form_external();
282 // form_external->ok->u_vdata = &holder;
283 form_external->form_external->u_vdata = &holder;
284 fl_set_form_atclose(form_external->form_external,
285 CancelCloseBoxCB, 0);
288 fl_addto_choice(form_external->templatechoice,
289 getTemplateString().c_str());
290 fl_set_input(form_external->filename, filename.c_str());
291 fl_set_input(form_external->parameters, parameters.c_str());
292 if (!templatename.empty()) {
293 fl_set_choice(form_external->templatechoice,
294 getTemplateNumber(templatename));
296 // Update the help text
297 templateCB(form_external->templatechoice, 0);
299 ExternalTemplate const & et = getTemplate(templatename);
300 if (et.automaticProduction) {
301 fl_deactivate_object(form_external->update);
302 fl_set_object_lcol(form_external->update, FL_INACTIVE);
304 fl_activate_object(form_external->update);
305 fl_set_object_lcol(form_external->update, FL_BLACK);
308 if (form_external->form_external->visible) {
309 fl_raise_form(form_external->form_external);
311 fl_show_form(form_external->form_external,
312 FL_PLACE_MOUSE | FL_FREE_SIZE, FL_TRANSIENT,
313 _("Insert external inset"));
315 ow = form_external->form_external->w;
316 oh = form_external->form_external->h;
318 fl_set_form_minsize(form_external->form_external, ow, oh);
323 void InsetExternal::Write(Buffer const *, std::ostream & os) const
325 os << "External " << templatename << ",\"" << filename
326 << "\",\"" << parameters << "\"\n";
330 void InsetExternal::Read(Buffer const *, LyXLex & lex)
333 string const format = lex.GetString();
334 string::size_type const pos1 = format.find(",");
335 templatename = format.substr(0, pos1);
336 string::size_type const pos2 = format.find("\",\"", pos1);
337 filename = format.substr(pos1 + 2, pos2 - (pos1 + 2));
338 parameters = format.substr(pos2 + 3, format.length() - (pos2 + 4));
340 lyxerr[Debug::INFO] << "InsetExternal::Read: " << templatename
342 << " " << parameters << endl;
346 int InsetExternal::write(string const & format,
347 Buffer const * buf, std::ostream & os) const
349 ExternalTemplate const & et = getTemplate(templatename);
350 ExternalTemplate::Formats::const_iterator cit =
351 et.formats.find(format);
352 if (cit == et.formats.end()) {
353 lyxerr << "External template format '" << format
354 << "' not specified in template " << templatename
359 if (et.automaticProduction) {
360 executeCommand(doSubstitution(buf,
361 (*cit).second.updateCommand),
365 os << doSubstitution(buf, (*cit).second.product);
370 int InsetExternal::Latex(Buffer const * buf,
371 std::ostream & os, bool, bool) const
373 return write("LaTeX", buf, os);
377 int InsetExternal::Ascii(Buffer const * buf, std::ostream & os, int) const
379 return write("Ascii", buf, os);
383 int InsetExternal::Linuxdoc(Buffer const * buf, std::ostream & os) const
385 return write("LinuxDoc", buf, os);
389 int InsetExternal::DocBook(Buffer const * buf, std::ostream & os) const
391 return write("DocBook", buf, os);
395 void InsetExternal::Validate(LaTeXFeatures & features) const
397 ExternalTemplate const & et = getTemplate(templatename);
398 ExternalTemplate::Formats::const_iterator cit =
399 et.formats.find("LaTeX");
400 if (cit == et.formats.end()) {
404 if (!(*cit).second.requirement.empty()) {
405 features.require((*cit).second.requirement);
407 if (!(*cit).second.preamble.empty()) {
408 features.externalPreambles += (*cit).second.preamble + "\n";
413 Inset * InsetExternal::Clone(Buffer const &) const
415 InsetExternal * inset = new InsetExternal();
416 inset->templatename = templatename;
417 inset->filename = filename;
418 inset->parameters = parameters;
423 string const InsetExternal::getScreenLabel() const
425 if (templatename.empty()) {
426 return _("External");
428 ExternalTemplate const & et = getTemplate(templatename);
429 if (et.guiName.empty())
432 return doSubstitution(0, et.guiName);
437 void InsetExternal::doUpdate(BufferView const * bv) const
439 ExternalTemplate const & et = getTemplate(getCurrentTemplate());
440 ExternalTemplate::Formats::const_iterator cit =
441 et.formats.find("LaTeX");
442 if (cit == et.formats.end())
445 executeCommand(doSubstitution(bv->buffer(),
446 (*cit).second.updateCommand),
451 void InsetExternal::doView(BufferView const * bv) const
454 ExternalTemplate const & et = getTemplate(getCurrentTemplate());
455 executeCommand(doSubstitution(bv->buffer(), et.viewCommand),
460 void InsetExternal::doEdit(BufferView const * bv) const
463 ExternalTemplate const & et = getTemplate(getCurrentTemplate());
464 executeCommand(doSubstitution(bv->buffer(), et.editCommand),
469 void InsetExternal::executeCommand(string const & s,
470 Buffer const * buffer) const
472 string buf = MakeAbsPath(buffer->fileName());
473 string path = OnlyPath(buf);
476 if (lyxerr.debugging()) {
477 lyxerr << "Executing '" << s << "' in '"
478 << path << "'" << endl;
480 one.startscript(Systemcalls::Wait, s);
484 void InsetExternal::automaticUpdate(BufferView const * bv) const
486 ExternalTemplate const & et = getTemplate(templatename);
487 if (et.automaticProduction) {
493 string const InsetExternal::doSubstitution(Buffer const * buffer,
494 string const & s) const
497 string const basename = ChangeExtension(filename, string());
498 result = subst(s, "$$FName", filename);
499 result = subst(result, "$$Basename", basename);
500 result = subst(result, "$$Parameters", parameters);
501 result = ReplaceEnvironmentPath(result);
502 result = subst(result, "$$Tempname", tempname);
503 result = subst(result, "$$Sysdir", system_lyxdir);
505 // Handle the $$Contents(filename) syntax
506 if (contains(result, "$$Contents(\"")) {
508 string::size_type const pos = result.find("$$Contents(\"");
509 string::size_type const end = result.find("\")", pos);
510 string const file = result.substr(pos + 12, end - (pos + 12));
513 // Make sure we are in the directory of the buffer
514 string const buf = MakeAbsPath(buffer->fileName());
515 string const path = OnlyPath(buf);
517 contents = GetFileContents(file);
519 contents = GetFileContents(file);
521 result = subst(result,
522 ("$$Contents(\"" + file + "\")").c_str(),
530 string const InsetExternal::getCurrentTemplate() const
532 return getTemplateName(fl_get_choice(form_external->templatechoice));
536 ExternalTemplate const InsetExternal::getTemplate(string const & name) const
538 ExternalTemplateManager::Templates::iterator i =
539 ExternalTemplateManager::get().getTemplates().find(name);
540 // Make sure that the template exists in the map
541 if (i == ExternalTemplateManager::get().getTemplates().end()) {
542 lyxerr << "Unknown external material template: "
544 return ExternalTemplate();
550 int InsetExternal::getTemplateNumber(string const & name) const
553 ExternalTemplateManager::Templates::const_iterator i1, i2;
554 i1 = ExternalTemplateManager::get().getTemplates().begin();
555 i2 = ExternalTemplateManager::get().getTemplates().end();
556 for (; i1 != i2; ++i1) {
557 if ((*i1).second.lyxName == name)
561 // This should never happen
562 /// This can happen if someone sends you a lyx file that uses
563 /// external templates that are defined only on his machine
569 string const InsetExternal::getTemplateName(int i) const
571 ExternalTemplateManager::Templates::const_iterator i1;
572 i1 = ExternalTemplateManager::get().getTemplates().begin();
573 for (int n = 1; n < i; ++n) {
576 return (*i1).second.lyxName;
580 string const InsetExternal::getTemplateString() const
584 ExternalTemplateManager::Templates::const_iterator i1, i2;
585 i1 = ExternalTemplateManager::get().getTemplates().begin();
586 i2 = ExternalTemplateManager::get().getTemplates().end();
587 for (; i1 != i2; ++i1) {
593 result += (*i1).second.lyxName;