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
20 #include "insetexternal.h"
21 #include "ExternalTemplate.h"
22 #include "lyx_gui_misc.h" // CancelCloseBoxCB
23 #include "BufferView.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"
36 InsetExternal::InsetExternal()
39 tempname = TmpFileName();
43 InsetExternal::~InsetExternal()
45 lyx::unlink(tempname);
50 void ExternalTemplateCB(FL_OBJECT * ob, long data)
52 InsetExternal::templateCB(ob, data);
57 void ExternalBrowseCB(FL_OBJECT * ob, long data)
59 InsetExternal::browseCB(ob, data);
64 void ExternalEditCB(FL_OBJECT * ob, long data)
66 InsetExternal::editCB(ob, data);
71 void ExternalViewCB(FL_OBJECT * ob, long data)
73 InsetExternal::viewCB(ob, data);
78 void ExternalUpdateCB(FL_OBJECT * ob, long data)
80 InsetExternal::updateCB(ob, data);
85 void ExternalOKCB(FL_OBJECT * ob, long data)
87 InsetExternal::okCB(ob, data);
92 void ExternalCancelCB(FL_OBJECT * ob, long data)
94 InsetExternal::cancelCB(ob, data);
98 void InsetExternal::templateCB(FL_OBJECT * ob, long)
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);
110 void InsetExternal::browseCB(FL_OBJECT * ob, long)
112 Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
113 InsetExternal * inset = holder->inset;
115 static string current_path;
119 string p = inset->filename;
120 string buf = MakeAbsPath(holder->view->buffer()->fileName());
121 string buf2 = OnlyPath(buf);
123 buf = MakeAbsPath(p, buf2);
126 buf = OnlyPath(holder->view->buffer()->fileName());
129 fileDlg.SetButton(0, _("Document"), buf);
131 /// Determine the template file extension
132 ExternalTemplate et = inset->getTemplate(inset->getCurrentTemplate());
133 string regexp = et.fileRegExp;
134 if (regexp.empty()) {
141 p = fileDlg.Select(_("External inset file"),
145 p = fileDlg.Select(_("External inset file"), buf,
149 if (p.empty()) return;
151 buf = MakeRelPath(p, buf2);
152 current_path = OnlyPath(p);
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 '%'."));
165 if (inset->form_external)
166 fl_set_input(inset->form_external->filename, buf.c_str());
171 void InsetExternal::editCB(FL_OBJECT * ob, long)
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);
180 void InsetExternal::viewCB(FL_OBJECT * ob, long)
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);
189 void InsetExternal::updateCB(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->doUpdate(holder->view);
198 void InsetExternal::okCB(FL_OBJECT * ob, long data)
200 Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
201 InsetExternal * inset = holder->inset;
202 inset->doApply(holder->view);
207 void InsetExternal::doApply(BufferView * bufview)
210 if (templatename != getCurrentTemplate()) {
211 templatename = getCurrentTemplate();
214 if (filename != fl_get_input(form_external->filename)) {
215 filename = fl_get_input(form_external->filename);
218 if (parameters != fl_get_input(form_external->parameters)) {
219 parameters = fl_get_input(form_external->parameters);
224 // The text might have change,
225 // so we should update the button look
226 bufview->updateInset(this, true);
231 void InsetExternal::cancelCB(FL_OBJECT * ob, long)
233 Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
235 InsetExternal * inset = holder->inset;
236 // BufferView * bv = holder->view;
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;
246 string const InsetExternal::EditMessage() const
248 ExternalTemplate const & et = getTemplate(templatename);
249 return doSubstitution(0, et.guiName);
253 void InsetExternal::Edit(BufferView * bv,
254 int /*x*/, int /*y*/, unsigned int /*button*/)
256 static int ow = -1, oh;
258 if (bv->buffer()->isReadonly())
259 WarnReadonly(bv->buffer()->fileName());
261 if (!form_external) {
262 form_external = create_form_form_external();
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);
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));
278 // Update the help text
279 templateCB(form_external->templatechoice, 0);
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);
286 fl_activate_object(form_external->update);
287 fl_set_object_lcol(form_external->update, FL_BLACK);
290 if (form_external->form_external->visible) {
291 fl_raise_form(form_external->form_external);
293 fl_show_form(form_external->form_external,
294 FL_PLACE_MOUSE | FL_FREE_SIZE,
295 FL_FULLBORDER, _("Insert external inset"));
297 ow = form_external->form_external->w;
298 oh = form_external->form_external->h;
300 fl_set_form_minsize(form_external->form_external, ow, oh);
305 void InsetExternal::Write(Buffer const *, std::ostream & os) const
307 os << "External " << templatename << ",\"" << filename
308 << "\",\"" << parameters << "\"\n";
312 void InsetExternal::Read(Buffer const *, LyXLex & lex)
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));
322 lyxerr << templatename << " " << filename << " " << parameters << endl;
326 int InsetExternal::write(string const & format,
327 Buffer const * buf, std::ostream & os) const
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
339 if (et.automaticProduction) {
340 executeCommand(doSubstitution(buf,
341 (*cit).second.updateCommand),
345 os << doSubstitution(buf, (*cit).second.product);
350 int InsetExternal::Latex(Buffer const * buf,
351 std::ostream & os, bool, bool) const
353 return write("LaTeX", buf, os);
357 int InsetExternal::Ascii(Buffer const * buf, std::ostream & os, int) const
359 return write("Ascii", buf, os);
363 int InsetExternal::Linuxdoc(Buffer const * buf, std::ostream & os) const
365 return write("LinuxDoc", buf, os);
369 int InsetExternal::DocBook(Buffer const * buf, std::ostream & os) const
371 return write("DocBook", buf, os);
375 void InsetExternal::Validate(LaTeXFeatures & features) const
377 ExternalTemplate const & et = getTemplate(templatename);
378 ExternalTemplate::Formats::const_iterator cit =
379 et.formats.find("LaTeX");
380 if (cit == et.formats.end()) {
384 if (!(*cit).second.requirement.empty()) {
385 features.require((*cit).second.requirement);
387 if (!(*cit).second.preamble.empty()) {
388 features.externalPreambles += (*cit).second.preamble + "\n";
393 Inset * InsetExternal::Clone(Buffer const &) const
395 InsetExternal * inset = new InsetExternal();
396 inset->templatename = templatename;
397 inset->filename = filename;
398 inset->parameters = parameters;
403 string const InsetExternal::getScreenLabel() const
405 if (templatename.empty()) {
406 return _("External");
408 ExternalTemplate const & et = getTemplate(templatename);
409 return doSubstitution(0, et.guiName);
414 void InsetExternal::doUpdate(BufferView const * bv) const
416 ExternalTemplate const & et = getTemplate(getCurrentTemplate());
417 ExternalTemplate::Formats::const_iterator cit =
418 et.formats.find("LaTeX");
419 if (cit == et.formats.end())
422 executeCommand(doSubstitution(bv->buffer(),
423 (*cit).second.updateCommand),
428 void InsetExternal::doView(BufferView const * bv) const
431 ExternalTemplate const & et = getTemplate(getCurrentTemplate());
432 executeCommand(doSubstitution(bv->buffer(), et.viewCommand),
437 void InsetExternal::doEdit(BufferView const * bv) const
440 ExternalTemplate const & et = getTemplate(getCurrentTemplate());
441 executeCommand(doSubstitution(bv->buffer(), et.editCommand),
446 void InsetExternal::executeCommand(string const & s,
447 Buffer const * buffer) const
449 string buf = MakeAbsPath(buffer->fileName());
450 string path = OnlyPath(buf);
453 if (lyxerr.debugging()) {
454 lyxerr << "Executing '" << s << "' in '"
455 << path << "'" << endl;
457 one.startscript(Systemcalls::Wait, s);
461 void InsetExternal::automaticUpdate(BufferView const * bv) const
463 ExternalTemplate const & et = getTemplate(templatename);
464 if (et.automaticProduction) {
470 string const InsetExternal::doSubstitution(Buffer const * buffer,
471 string const & s) const
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);
482 // Handle the $$Contents(filename) syntax
483 if (contains(result, "$$Contents(\"")) {
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));
490 // Make sure we are in the directory of the buffer
491 string const buf = MakeAbsPath(buffer->fileName());
492 string const path = OnlyPath(buf);
494 contents = GetFileContents(file);
496 contents = GetFileContents(file);
498 result = subst(result,
499 ("$$Contents(\"" + file + "\")").c_str(),
507 string const InsetExternal::getCurrentTemplate() const
509 return getTemplateName(fl_get_choice(form_external->templatechoice));
513 ExternalTemplate const InsetExternal::getTemplate(string const & name) const
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: "
521 return ExternalTemplate();
527 int InsetExternal::getTemplateNumber(string const & name) const
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)
538 // This should never happen
544 string const InsetExternal::getTemplateName(int i) const
546 ExternalTemplateManager::Templates::const_iterator i1;
547 i1 = ExternalTemplateManager::get().getTemplates().begin();
548 for (int n = 1; n < i; ++n) {
551 return (*i1).second.lyxName;
555 string const InsetExternal::getTemplateString() const
559 ExternalTemplateManager::Templates::const_iterator i1, i2;
560 i1 = ExternalTemplateManager::get().getTemplates().begin();
561 i2 = ExternalTemplateManager::get().getTemplates().end();
562 for (; i1 != i2; ++i1) {
568 result += (*i1).second.lyxName;