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"
32 #include "frontends/Dialogs.h" // redrawGUI
34 #ifdef SIGC_CXX_NAMESPACES
41 InsetExternal::InsetExternal()
44 tempname = lyx::tempName(); //TmpFileName();
45 r_ = Dialogs::redrawGUI.connect(slot(this, &InsetExternal::redraw));
49 InsetExternal::~InsetExternal()
51 lyx::unlink(tempname);
56 void InsetExternal::redraw()
58 if (form_external && form_external->form_external->visible)
59 fl_redraw_form(form_external->form_external);
64 void ExternalTemplateCB(FL_OBJECT * ob, long data)
66 InsetExternal::templateCB(ob, data);
71 void ExternalBrowseCB(FL_OBJECT * ob, long data)
73 InsetExternal::browseCB(ob, data);
78 void ExternalEditCB(FL_OBJECT * ob, long data)
80 InsetExternal::editCB(ob, data);
85 void ExternalViewCB(FL_OBJECT * ob, long data)
87 InsetExternal::viewCB(ob, data);
92 void ExternalUpdateCB(FL_OBJECT * ob, long data)
94 InsetExternal::updateCB(ob, data);
99 void ExternalOKCB(FL_OBJECT * ob, long data)
101 InsetExternal::okCB(ob, data);
106 void ExternalCancelCB(FL_OBJECT * ob, long data)
108 InsetExternal::cancelCB(ob, data);
112 void InsetExternal::templateCB(FL_OBJECT * ob, long)
114 Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
115 InsetExternal * inset = holder->inset;
116 ExternalTemplate et = inset->getTemplate(inset->getCurrentTemplate());
117 // Update the help text
118 fl_clear_browser(inset->form_external->helptext);
119 fl_addto_browser(inset->form_external->helptext, et.helpText.c_str());
120 fl_set_browser_topline(inset->form_external->helptext, 0);
124 void InsetExternal::browseCB(FL_OBJECT * ob, long)
126 Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
127 InsetExternal * inset = holder->inset;
129 static string current_path;
133 string p = inset->filename;
134 string buf = MakeAbsPath(holder->view->buffer()->fileName());
135 string buf2 = OnlyPath(buf);
137 buf = MakeAbsPath(p, buf2);
140 buf = OnlyPath(holder->view->buffer()->fileName());
143 fileDlg.SetButton(0, _("Document"), buf);
145 /// Determine the template file extension
146 ExternalTemplate et = inset->getTemplate(inset->getCurrentTemplate());
147 string regexp = et.fileRegExp;
148 if (regexp.empty()) {
155 p = fileDlg.Select(_("External inset file"),
159 p = fileDlg.Select(_("External inset file"), buf,
163 if (p.empty()) return;
165 buf = MakeRelPath(p, buf2);
166 current_path = OnlyPath(p);
169 if (contains(p, "#") || contains(p, "~") || contains(p, "$")
170 || contains(p, "%")) {
171 WriteAlert(_("Filename can't contain any "
172 "of these characters:"),
173 // xgettext:no-c-format
174 _("'#', '~', '$' or '%'."));
179 if (inset->form_external)
180 fl_set_input(inset->form_external->filename, buf.c_str());
185 void InsetExternal::editCB(FL_OBJECT * ob, long)
187 Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
188 InsetExternal * inset = holder->inset;
189 inset->doApply(holder->view);
190 inset->doEdit(holder->view);
194 void InsetExternal::viewCB(FL_OBJECT * ob, long)
196 Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
197 InsetExternal * inset = holder->inset;
198 inset->doApply(holder->view);
199 inset->doView(holder->view);
203 void InsetExternal::updateCB(FL_OBJECT * ob, long)
205 Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
206 InsetExternal * inset = holder->inset;
207 inset->doApply(holder->view);
208 inset->doUpdate(holder->view);
212 void InsetExternal::okCB(FL_OBJECT * ob, long data)
214 Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
215 InsetExternal * inset = holder->inset;
216 inset->doApply(holder->view);
221 void InsetExternal::doApply(BufferView * bufview)
224 if (templatename != getCurrentTemplate()) {
225 templatename = getCurrentTemplate();
228 if (filename != fl_get_input(form_external->filename)) {
229 filename = fl_get_input(form_external->filename);
232 if (parameters != fl_get_input(form_external->parameters)) {
233 parameters = fl_get_input(form_external->parameters);
238 // The text might have change,
239 // so we should update the button look
240 bufview->updateInset(this, true);
245 void InsetExternal::cancelCB(FL_OBJECT * ob, long)
247 Holder * holder = static_cast<Holder*>(ob->form->u_vdata);
249 InsetExternal * inset = holder->inset;
250 // BufferView * bv = holder->view;
252 if (inset->form_external) {
253 fl_hide_form(inset->form_external->form_external);
254 fl_free_form(inset->form_external->form_external);
255 inset->form_external = 0;
260 string const InsetExternal::EditMessage() const
262 ExternalTemplate const & et = getTemplate(templatename);
263 return doSubstitution(0, et.guiName);
267 void InsetExternal::Edit(BufferView * bv,
268 int /*x*/, int /*y*/, unsigned int /*button*/)
270 static int ow = -1, oh;
272 if (bv->buffer()->isReadonly())
273 WarnReadonly(bv->buffer()->fileName());
275 if (!form_external) {
276 form_external = create_form_form_external();
278 // form_external->ok->u_vdata = &holder;
279 form_external->form_external->u_vdata = &holder;
280 fl_set_form_atclose(form_external->form_external,
281 CancelCloseBoxCB, 0);
284 fl_addto_choice(form_external->templatechoice,
285 getTemplateString().c_str());
286 fl_set_input(form_external->filename, filename.c_str());
287 fl_set_input(form_external->parameters, parameters.c_str());
288 if (!templatename.empty()) {
289 fl_set_choice(form_external->templatechoice,
290 getTemplateNumber(templatename));
292 // Update the help text
293 templateCB(form_external->templatechoice, 0);
295 ExternalTemplate const & et = getTemplate(templatename);
296 if (et.automaticProduction) {
297 fl_deactivate_object(form_external->update);
298 fl_set_object_lcol(form_external->update, FL_INACTIVE);
300 fl_activate_object(form_external->update);
301 fl_set_object_lcol(form_external->update, FL_BLACK);
304 if (form_external->form_external->visible) {
305 fl_raise_form(form_external->form_external);
307 fl_show_form(form_external->form_external,
308 FL_PLACE_MOUSE | FL_FREE_SIZE, FL_TRANSIENT,
309 _("Insert external inset"));
311 ow = form_external->form_external->w;
312 oh = form_external->form_external->h;
314 fl_set_form_minsize(form_external->form_external, ow, oh);
319 void InsetExternal::Write(Buffer const *, std::ostream & os) const
321 os << "External " << templatename << ",\"" << filename
322 << "\",\"" << parameters << "\"\n";
326 void InsetExternal::Read(Buffer const *, LyXLex & lex)
329 string const format = lex.GetString();
330 string::size_type const pos1 = format.find(",");
331 templatename = format.substr(0, pos1);
332 string::size_type const pos2 = format.find("\",\"", pos1);
333 filename = format.substr(pos1 + 2, pos2 - (pos1 + 2));
334 parameters = format.substr(pos2 + 3, format.length() - (pos2 + 4));
336 lyxerr[Debug::INFO] << "InsetExternal::Read: " << templatename
338 << " " << parameters << endl;
342 int InsetExternal::write(string const & format,
343 Buffer const * buf, std::ostream & os) const
345 ExternalTemplate const & et = getTemplate(templatename);
346 ExternalTemplate::Formats::const_iterator cit =
347 et.formats.find(format);
348 if (cit == et.formats.end()) {
349 lyxerr << "External template format '" << format
350 << "' not specified in template " << templatename
355 if (et.automaticProduction) {
356 executeCommand(doSubstitution(buf,
357 (*cit).second.updateCommand),
361 os << doSubstitution(buf, (*cit).second.product);
366 int InsetExternal::Latex(Buffer const * buf,
367 std::ostream & os, bool, bool) const
369 return write("LaTeX", buf, os);
373 int InsetExternal::Ascii(Buffer const * buf, std::ostream & os, int) const
375 return write("Ascii", buf, os);
379 int InsetExternal::Linuxdoc(Buffer const * buf, std::ostream & os) const
381 return write("LinuxDoc", buf, os);
385 int InsetExternal::DocBook(Buffer const * buf, std::ostream & os) const
387 return write("DocBook", buf, os);
391 void InsetExternal::Validate(LaTeXFeatures & features) const
393 ExternalTemplate const & et = getTemplate(templatename);
394 ExternalTemplate::Formats::const_iterator cit =
395 et.formats.find("LaTeX");
396 if (cit == et.formats.end()) {
400 if (!(*cit).second.requirement.empty()) {
401 features.require((*cit).second.requirement);
403 if (!(*cit).second.preamble.empty()) {
404 features.externalPreambles += (*cit).second.preamble + "\n";
409 Inset * InsetExternal::Clone(Buffer const &) const
411 InsetExternal * inset = new InsetExternal();
412 inset->templatename = templatename;
413 inset->filename = filename;
414 inset->parameters = parameters;
419 string const InsetExternal::getScreenLabel() const
421 if (templatename.empty()) {
422 return _("External");
424 ExternalTemplate const & et = getTemplate(templatename);
425 if (et.guiName.empty())
428 return doSubstitution(0, et.guiName);
433 void InsetExternal::doUpdate(BufferView const * bv) const
435 ExternalTemplate const & et = getTemplate(getCurrentTemplate());
436 ExternalTemplate::Formats::const_iterator cit =
437 et.formats.find("LaTeX");
438 if (cit == et.formats.end())
441 executeCommand(doSubstitution(bv->buffer(),
442 (*cit).second.updateCommand),
447 void InsetExternal::doView(BufferView const * bv) const
450 ExternalTemplate const & et = getTemplate(getCurrentTemplate());
451 executeCommand(doSubstitution(bv->buffer(), et.viewCommand),
456 void InsetExternal::doEdit(BufferView const * bv) const
459 ExternalTemplate const & et = getTemplate(getCurrentTemplate());
460 executeCommand(doSubstitution(bv->buffer(), et.editCommand),
465 void InsetExternal::executeCommand(string const & s,
466 Buffer const * buffer) const
468 string buf = MakeAbsPath(buffer->fileName());
469 string path = OnlyPath(buf);
472 if (lyxerr.debugging()) {
473 lyxerr << "Executing '" << s << "' in '"
474 << path << "'" << endl;
476 one.startscript(Systemcalls::Wait, s);
480 void InsetExternal::automaticUpdate(BufferView const * bv) const
482 ExternalTemplate const & et = getTemplate(templatename);
483 if (et.automaticProduction) {
489 string const InsetExternal::doSubstitution(Buffer const * buffer,
490 string const & s) const
493 string const basename = ChangeExtension(filename, string());
494 result = subst(s, "$$FName", filename);
495 result = subst(result, "$$Basename", basename);
496 result = subst(result, "$$Parameters", parameters);
497 result = ReplaceEnvironmentPath(result);
498 result = subst(result, "$$Tempname", tempname);
499 result = subst(result, "$$Sysdir", system_lyxdir);
501 // Handle the $$Contents(filename) syntax
502 if (contains(result, "$$Contents(\"")) {
504 string::size_type const pos = result.find("$$Contents(\"");
505 string::size_type const end = result.find("\")", pos);
506 string const file = result.substr(pos + 12, end - (pos + 12));
509 // Make sure we are in the directory of the buffer
510 string const buf = MakeAbsPath(buffer->fileName());
511 string const path = OnlyPath(buf);
513 contents = GetFileContents(file);
515 contents = GetFileContents(file);
517 result = subst(result,
518 ("$$Contents(\"" + file + "\")").c_str(),
526 string const InsetExternal::getCurrentTemplate() const
528 return getTemplateName(fl_get_choice(form_external->templatechoice));
532 ExternalTemplate const InsetExternal::getTemplate(string const & name) const
534 ExternalTemplateManager::Templates::iterator i =
535 ExternalTemplateManager::get().getTemplates().find(name);
536 // Make sure that the template exists in the map
537 if (i == ExternalTemplateManager::get().getTemplates().end()) {
538 lyxerr << "Unknown external material template: "
540 return ExternalTemplate();
546 int InsetExternal::getTemplateNumber(string const & name) const
549 ExternalTemplateManager::Templates::const_iterator i1, i2;
550 i1 = ExternalTemplateManager::get().getTemplates().begin();
551 i2 = ExternalTemplateManager::get().getTemplates().end();
552 for (; i1 != i2; ++i1) {
553 if ((*i1).second.lyxName == name)
557 // This should never happen
558 /// This can happen if someone sends you a lyx file that uses
559 /// external templates that are defined only on his machine
565 string const InsetExternal::getTemplateName(int i) const
567 ExternalTemplateManager::Templates::const_iterator i1;
568 i1 = ExternalTemplateManager::get().getTemplates().begin();
569 for (int n = 1; n < i; ++n) {
572 return (*i1).second.lyxName;
576 string const InsetExternal::getTemplateString() const
580 ExternalTemplateManager::Templates::const_iterator i1, i2;
581 i1 = ExternalTemplateManager::get().getTemplates().begin();
582 i2 = ExternalTemplateManager::get().getTemplates().end();
583 for (; i1 != i2; ++i1) {
589 result += (*i1).second.lyxName;