diff --git a/ChangeLog b/ChangeLog index b19c7e1181..2ee3918fd1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,41 @@ +2000-08-30 Dekel Tsur + + * src/converter.[Ch]: New file for converting between different + formats. + + * src/export.[Ch]: New file for exporting a LyX file to different + formats. + + * src/lyx_cb.C: Remove many functions when NEW_EXPORT is defined: + MenuRunLaTeX, MakeLaTeXOutput, RunScript, CreatePostscript, + PreviewPostscript, PreviewDVI, AskOverwrite, MenuMakeLaTeX, + MenuMakeLinuxDoc, MenuMakeDocBook, MenuMakeHTML, + MenuMakeHTML_LinuxDoc, MenuMakeHTML_DocBook, RunLinuxDoc, + RunDocBook, MenuExport. + + * src/lyxfunc.C (Dispatch): Use the Exporter::Export and + Exporter::Preview methods if NEW_EXPORT is defined. + + * src/buffer.C (Dispatch): Use Exporter::Export. + + * src/lyxrc.C: Added new tags: \converter and \viewer. + + * src/commandtags.h + * src/LyXAction.C: Define new lyx-function: buffer-update. + Remove obsolete buffer-typeset,buffer-typeset-ps & buffer-view-ps + when NEW_EXPORT is defined. + + * src/MenuBackend.C: Added new tags: updateformats and viewformats. + + * src/frontends/xforms/Menubar_pimpl.C (add_formats) New method. + + * lib/ui/default.ui: Added submenus "view" and "update" to the + "file" menu. + + * src/filetools.C (GetExtension): New function. + + * src/LaTeX.C (LaTeX): Add "-pdf" to depfile if pdflatex is used. + 2000-08-29 Allan Rae * lib/bind/xemacs.bind: update a binding due to Juergen's recent work diff --git a/lib/ui/default.ui b/lib/ui/default.ui index 5a4e1e6475..3e3ab07dce 100644 --- a/lib/ui/default.ui +++ b/lib/ui/default.ui @@ -34,8 +34,10 @@ Menuset Separator Item "View dvi|d" "buffer-view" Item "View Postscript|w" "buffer-view-ps" + Submenu "View" "view" Item "Update dvi|v" "buffer-typeset" Item "Update Postscript|U" "buffer-typeset-ps" + Submenu "Update" "update" OptItem "Build program|B" "build-program" Separator Item "Print...|P" "buffer-print" @@ -60,6 +62,14 @@ Menuset Lastfiles End + Menu "view" + ViewFormats + End + + Menu "update" + UpdateFormats + End + Menu "import" Item "LaTeX|L" "buffer-import latex" Item "Ascii text as lines|A" "buffer-import ascii" @@ -68,6 +78,7 @@ Menuset End Menu "export" + ExportFormats OptItem "as LaTeX|L" "buffer-export latex" OptItem "as LinuxDoc|L" "buffer-export linuxdoc" OptItem "as DocBook|B" "buffer-export docbook" diff --git a/src/LaTeX.C b/src/LaTeX.C index 94af204a5f..36de5a4b0c 100644 --- a/src/LaTeX.C +++ b/src/LaTeX.C @@ -71,6 +71,8 @@ LaTeX::LaTeX(string const & latex, string const & f, string const & p) { num_errors = 0; depfile = file + ".dep"; + if (prefixIs(cmd, "pdf")) // Do we use pdflatex ? + depfile += "-pdf"; } diff --git a/src/LyXAction.C b/src/LyXAction.C index bd8d6bce31..685cd8599c 100644 --- a/src/LyXAction.C +++ b/src/LyXAction.C @@ -149,6 +149,10 @@ void LyXAction::init() N_("Switch to an open document"), ReadOnly }, { LFUN_READ_ONLY_TOGGLE, "buffer-toggle-read-only", N_("Toggle read-only"), ReadOnly }, +#ifdef NEW_EXPORT + { LFUN_UPDATE, "buffer-update", N_("Update"), ReadOnly }, + { LFUN_PREVIEW, "buffer-view", N_("View") , ReadOnly }, +#else { LFUN_RUNLATEX, "buffer-typeset", N_("Update DVI"), ReadOnly }, { LFUN_RUNDVIPS, "buffer-typeset-ps", @@ -156,6 +160,7 @@ void LyXAction::init() { LFUN_PREVIEW, "buffer-view", N_("View DVI") , ReadOnly }, { LFUN_PREVIEWPS, "buffer-view-ps", N_("View PostScript") , ReadOnly }, +#endif { LFUN_MENUWRITE, "buffer-write", N_("Save"), ReadOnly }, { LFUN_MENUWRITEAS, "buffer-write-as", N_("Save As"), ReadOnly }, diff --git a/src/LyXSendto.C b/src/LyXSendto.C index 8deb0ad036..1c007a81a3 100644 --- a/src/LyXSendto.C +++ b/src/LyXSendto.C @@ -13,6 +13,7 @@ #include "gettext.h" //#include "lyx_cb.h" #include "bufferview_funcs.h" +#include "exporter.h" extern FD_form_sendto * fd_form_sendto; extern BufferView * current_view; @@ -56,6 +57,7 @@ void SendtoApplyCB(FL_OBJECT *, long) if (command.empty()) return; Buffer * buffer = current_view->buffer(); +#ifndef NEW_EXPORT if (fl_get_button(fd_form_sendto->radio_ftype_dvi) || fl_get_button(fd_form_sendto->radio_ftype_ps)) { ProhibitInput(current_view); @@ -66,6 +68,7 @@ void SendtoApplyCB(FL_OBJECT *, long) } AllowInput(current_view); } +#endif string ftypeext; if (fl_get_button(fd_form_sendto->radio_ftype_lyx)) ftypeext = ".lyx"; @@ -76,10 +79,16 @@ void SendtoApplyCB(FL_OBJECT *, long) else if (fl_get_button(fd_form_sendto->radio_ftype_ascii)) ftypeext = ".txt"; else { +#ifdef NEW_EXPORT + ftypeext = ".ps"; + if (!Exporter::Export(buffer, "ps", true)) + return; +#else ftypeext = ".ps_tmp"; if (!CreatePostscript(buffer, true)) { return; } +#endif } string fname = OnlyFilename(ChangeExtension(buffer->getLatexName(), diff --git a/src/Makefile.am b/src/Makefile.am index c4df32fd58..0623dc00f9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -109,6 +109,8 @@ lyx_SOURCES = \ combox.h \ commandtags.h \ config.h.in \ + converter.C \ + converter.h \ counters.C \ counters.h \ credits.C \ @@ -119,6 +121,8 @@ lyx_SOURCES = \ debug.h \ encoding.C \ encoding.h \ + exporter.C \ + exporter.h \ ext_l10n.h \ figure.h \ filedlg.C \ diff --git a/src/MenuBackend.C b/src/MenuBackend.C index f4ff0ac0bb..3d3360853b 100644 --- a/src/MenuBackend.C +++ b/src/MenuBackend.C @@ -38,6 +38,9 @@ MenuItem::MenuItem(Kind kind, string const & label, case Separator: case Documents: case Lastfiles: + case ViewFormats: + case UpdateFormats: + case ExportFormats: break; case Command: action_ = lyxaction.LookupFunc(command); @@ -70,21 +73,27 @@ Menu & Menu::read(LyXLex & lex) md_item = 1, md_documents, md_endmenu, + md_exportformats, md_lastfiles, md_optitem, md_submenu, md_separator, + md_updateformats, + md_viewformats, md_last }; struct keyword_item menutags[md_last-1] = { { "documents", md_documents }, { "end", md_endmenu }, + { "exportformats", md_exportformats }, { "item", md_item }, { "lastfiles", md_lastfiles }, { "optitem", md_optitem }, { "separator", md_separator }, - { "submenu", md_submenu } + { "submenu", md_submenu }, + { "updateformats", md_updateformats }, + { "viewformats", md_viewformats } }; lex.pushTable(menutags, md_last - 1); @@ -120,6 +129,15 @@ Menu & Menu::read(LyXLex & lex) case md_documents: add(MenuItem(MenuItem::Documents)); break; + case md_viewformats: + add(MenuItem(MenuItem::ViewFormats)); + break; + case md_updateformats: + add(MenuItem(MenuItem::UpdateFormats)); + break; + case md_exportformats: + add(MenuItem(MenuItem::ExportFormats)); + break; case md_submenu: { lex.next(); char * tmp = strdup(lex.GetString().c_str()); diff --git a/src/MenuBackend.h b/src/MenuBackend.h index 29e004bf98..c5621a3c39 100644 --- a/src/MenuBackend.h +++ b/src/MenuBackend.h @@ -40,7 +40,16 @@ public: Lastfiles, /** This is the list of opened Documents, typically for the Documents menu. */ - Documents + Documents, + /** This is a list of viewable formats + typically for the Documents menu. */ + ViewFormats, + /** This is a list of updatable formats + typically for the Documents menu. */ + UpdateFormats, + /** This is a list of exportable formats + typically for the Documents menu. */ + ExportFormats }; /// Create a Command type MenuItem MenuItem(Kind kind, diff --git a/src/WorkArea.C b/src/WorkArea.C index 83f343228c..02f5e97e70 100644 --- a/src/WorkArea.C +++ b/src/WorkArea.C @@ -21,7 +21,10 @@ #include "BufferView.h" #include "LyXView.h" #include "lyxfunc.h" + +#if FL_REVISION < 89 #include "lyxlookup.h" +#endif using std::endl; @@ -319,7 +322,7 @@ int WorkArea::work_area_handler(FL_OBJECT * ob, int event, break; case FL_KEYBOARD: { - lyxerr[Debug::KEY] << "Workarea event: KEYBOARD"; + lyxerr[Debug::KEY] << "Workarea event: KEYBOARD" << endl; KeySym keysym = 0; char dummy[1]; @@ -352,6 +355,8 @@ int WorkArea::work_area_handler(FL_OBJECT * ob, int event, } KeySym ret_key = keysym; #else + // Ok, this is a bit simplistic...seems that the rules + // need to be a bit more... if (!key) break; KeySym ret_key = (keysym ? keysym : key); #endif diff --git a/src/buffer.C b/src/buffer.C index 536f3c165a..0f30d09da4 100644 --- a/src/buffer.C +++ b/src/buffer.C @@ -87,6 +87,7 @@ #include "lyx_gui_misc.h" // WarnReadonly() #include "frontends/Dialogs.h" #include "encoding.h" +#include "exporter.h" using std::ostream; using std::ofstream; @@ -106,7 +107,9 @@ using std::istringstream; // all these externs should eventually be removed. extern BufferList bufferlist; +#ifndef NEW_EXPORT extern void MenuExport(Buffer *, string const &); +#endif extern LyXAction lyxaction; @@ -3318,6 +3321,8 @@ void Buffer::SimpleDocBookOnePar(ostream & os, string & extra, int Buffer::runLaTeX() { +#ifndef NEW_EXPORT + if (!users->text) return 0; ProhibitInput(users); @@ -3376,6 +3381,7 @@ int Buffer::runLaTeX() AllowInput(users); return latex.getNumErrors(); +#endif } @@ -3839,7 +3845,11 @@ bool Buffer::Dispatch(int action, string const & argument) bool dispatched = true; switch (action) { case LFUN_EXPORT: +#ifdef NEW_EXPORT + Exporter::Export(this, argument, false); +#else MenuExport(this, argument); +#endif break; default: diff --git a/src/commandtags.h b/src/commandtags.h index e93efe41f2..18b5e8a834 100644 --- a/src/commandtags.h +++ b/src/commandtags.h @@ -12,6 +12,8 @@ #include +//#define NEW_EXPORT 1 + /** These are all the lyxfunctions (as enums). Please add new functions at the end of the enum, right before LFUN_LASTACTION. @@ -27,11 +29,15 @@ enum kb_action { LFUN_MENUWRITEAS, LFUN_MENUPRINT, LFUN_MENUSENDTO, +#ifndef NEW_EXPORT LFUN_RUNLATEX, +#endif LFUN_BUILDPROG, // 10 LFUN_TOCVIEW, LFUN_PREVIEW, +#ifndef NEW_EXPORT LFUN_PREVIEWPS, +#endif LFUN_CLOSEBUFFER, LFUN_BUFFER_PRINT, // ARRae 20000313 LFUN_PRINTER_PARAMS_GET, // ARRae 20000313 @@ -191,7 +197,9 @@ enum kb_action { LFUN_BACKSPACE_SKIP, // 170 LFUN_DELETE_SKIP, LFUN_MENUNEWTMPLT, // Asger 1997-02-02 +#ifndef NEW_EXPORT LFUN_RUNDVIPS, // Asger 1997-02-02 +#endif LFUN_MENURELOAD, // Asger 1997-02-02 LFUN_FAX, // Asger 1997-02-10 LFUN_RECONFIGURE, // Asger 1997-02-14 @@ -272,6 +280,7 @@ enum kb_action { LFUN_TABULAR_FEATURE, // Jug 20000728 LFUN_LAYOUT_TABULAR, // Jug 20000731 LFUN_SCROLL_INSET, // Jug 20000801 + LFUN_UPDATE, // Dekel 20000805 LFUN_INDEX_INSERT, // Angus 20000803 LFUN_REF_CREATE, // Angus 20000807 LFUN_SCREEN_FONT_UPDATE, // ARRae 20000813 diff --git a/src/converter.C b/src/converter.C new file mode 100644 index 0000000000..cf38de44bf --- /dev/null +++ b/src/converter.C @@ -0,0 +1,406 @@ +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright 1995 Matthias Ettrich + * Copyright 1995-2000 The LyX Team. + * + * ====================================================== */ + +#include + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include +#include +#include +#include + +#include "converter.h" +#include "lyxrc.h" +#include "support/syscall.h" +#include "support/path.h" +#include "debug.h" +#include "buffer.h" + +#include "bufferview_funcs.h" +#include "LaTeX.h" +#include "LyXView.h" +#include "minibuffer.h" +#include "lyx_gui_misc.h" + +using std::map; +using std::vector; +using std::queue; +using std::stack; + +extern void ShowMessage(Buffer * buf, + string const & msg1, + string const & msg2 = string(), + string const & msg3 = string(), int delay = 6); + +////////////////////////////////////////////////////////////////////////////// + +map Formats::formats; +vector Converter::commands; + +////////////////////////////////////////////////////////////////////////////// + +Format::Format(string const & n) : name(n), in_degree(0) +{ + struct Item { + char const * name; + char const * prettyname; + }; + Item items[] = { + { "tex", "LaTeX" }, + { "dvi", "DVI" }, + { "ps", "PostScript" }, + { "txt", "Ascii" }, + { "html", "HTML" }, + { "pdf", "PDF" }, + { 0, 0} + }; + + prettyname = n; + for (int i = 0; items[i].name != 0; ++i) + if (items[i].name == n) { + prettyname = items[i].prettyname; + break; + } +} + +void Formats::Add(string const & name) +{ + if (formats.find(name) == formats.end()) + formats[name] = Format(name); +} + +void Formats::SetViewer(string const & name, string const & command) +{ + Add(name); + Format * f = GetFormat(name); + if (!f->viewer.empty()) + lyxerr << "Error: a viewer for " << name + << " is already defined!" << endl; + else + f->viewer = command; +} + + +bool Formats::View(string const & filename) +{ + string extension = GetExtension(filename); + Format * format = GetFormat(extension); + if (!format || format->viewer.empty()) { + WriteAlert(_("Can not view file"), + _("No information for viewing ") + + Formats::PrettyName(extension)); + return false; + } + + string command = format->viewer; + command = subst(command, "$$FName", filename); +#ifndef __EMX__ + command += " &"; +#else + // OS/2 cmd.exe has another use for '&' + // This is not NLS safe, but it's OK, I think. + string sh = OnlyFilename(GetEnvPath("EMXSHELL")); + if (sh.empty()) { + // COMSPEC is set, unless user unsets + sh = OnlyFilename(GetEnvPath("COMSPEC")); + if (sh.empty()) + sh = "cmd.exe"; + } + sh = lowercase(sh); + if (contains(sh, "cmd.exe") + || contains(sh, "4os2.exe")) + command = "start /min/n " + command; + else + command += " &"; +#endif + lyxerr << "Executing command: " << command << endl; + //ShowMessage(buffer, _("Executing command:"), command); + Systemcalls one; + int res = one.startscript(Systemcalls::System, command); + + if (res) { + WriteAlert(_("Can not view file"), + _("Error while executing"), + command.substr(0, 50)); + return false; + } + return true; +} + + +Format * Formats::GetFormat(string const & name) +{ + map::iterator it = formats.find(name); + if (it != formats.end()) + return &(*it).second; + else + return 0; +} + +string Formats::PrettyName(string const & name) +{ + + string format; + Converter::SplitFormat(name, format); + Format * f = GetFormat(format); + if (f) + return f->prettyname; + else + return format; +} + +////////////////////////////////////////////////////////////////////////////// +void Converter::Add(string const & from, string const & to, + string const & command, string const & flags) +{ + for (vector::const_iterator cit = commands.begin(); + cit != commands.end(); ++cit) + if ((*cit).from == from && (*cit).to == to) { + lyxerr << "Error: Convertor from " << from + << " to " << to + << " already exists!" << endl; + return; + } + bool original_dir = flags == "origdir"; + commands.push_back(Command(from, to, command, original_dir)); + + Formats::Add(from); + Formats::Add(to); + ++Formats::GetFormat(to)->in_degree; +} + +vector< pair > +Converter::GetReachable(string const & from, bool only_viewable) +{ + vector< pair > result; + Format * format = Formats::GetFormat(from); + if (!format) + return result; + + int sort_start = 0; + if (!only_viewable || !format->viewer.empty()) { + result.push_back(pair(from, format->prettyname)); + sort_start = 1; + } + + queue< vector::iterator > Q; + for (vector::iterator it = commands.begin(); + it != commands.end(); ++it) + if ((*it).from == from) { + Q.push(it); + (*it).visited = true; + } else + (*it).visited = false; + + while (!Q.empty()) { + vector::iterator it = Q.front(); + format = Formats::GetFormat((*it).to); + string name = format->name; + string prettyname = format->prettyname; + if (format->in_degree > 1) { + name += ":" + (*it).from; + string tmp; + split((*it).command, tmp, ' '); + prettyname += _("(using ") + tmp + ")"; + } + if (!only_viewable || !format->viewer.empty()) + result.push_back(pair(name, prettyname)); + Q.pop(); + for (vector::iterator it2 = commands.begin(); + it2 != commands.end(); ++it2) + if (!(*it2).visited && (*it).to == (*it2).from) { + Q.push(it2); + (*it2).visited = true; + } + } + + sort(result.begin() + sort_start, result.end()); + return result; +} + + +bool Converter::convert(Buffer * buffer, string const & from_file, + string const & to_format) + +{ + string using_format, format; + using_format = SplitFormat(to_format, format); + string from_format = GetExtension(from_file); + if (from_format == format) + return true; + + queue< vector::iterator > Q; + for (vector::iterator it = commands.begin(); + it != commands.end(); ++it) + if ((*it).from == from_format) { + Q.push(it); + (*it).visited = true; + (*it).previous = commands.end(); + } else + (*it).visited = false; + + if (Q.empty()) { + WriteAlert(_("Can not convert file"), + ("Unknown format ") + from_format); + return false; + } + + bool found = false; + vector::iterator it; + while (!Q.empty()) { + it = Q.front(); + if ((*it).to == format && + (using_format.empty() || using_format == (*it).from)) { + found = true; + break; + } + Q.pop(); + for (vector::iterator it2 = commands.begin(); + it2 != commands.end(); ++it2) + if (!(*it2).visited && (*it).to == (*it2).from) { + Q.push(it2); + (*it2).visited = true; + (*it2).previous = it; + } + } + + if (!found) { + WriteAlert(_("Can not convert file"), + _("No information for converting from ") + + Formats::PrettyName(from_format) + _(" to ") + + Formats::PrettyName(to_format)); + return false; + } + + stack< vector::iterator > S; + while (it != commands.end()) { + S.push(it); + it = (*it).previous; + } + + //Path p(OnlyPath(buffer->fileName())); + Path p(OnlyPath(from_file)); + + string basename = ChangeExtension(from_file, ""); + while (!S.empty()) { + it = S.top(); + S.pop(); + lyxerr << "Converting from " + << (*it).from << " to " << (*it).to << endl; + + if ((*it).from == "tex" && + ( (*it).to == "dvi" || (*it).to == "pdf") ) { + lyxrc.pdf_mode = (*it).to == "pdf"; + if (!runLaTeX(buffer, (*it).command)) + return false; + } else { + string infile = ChangeExtension(from_file, (*it).from); + if (!(*it).original_dir) + infile = OnlyFilename(infile); + string outfile = ChangeExtension(infile, (*it).to); + + string command = (*it).command; + command = subst(command, "$$FName", infile); + command = subst(command, "$$BaseName", basename); + command = subst(command, "$$OutName", outfile); + lyxerr << "Calling " << command << endl; + ShowMessage(buffer, _("Executing command:"), command); + + Systemcalls one; + int res; + if ((*it).original_dir) { + Path p(buffer->filepath); + res = one.startscript(Systemcalls::System, command); + } else + res = one.startscript(Systemcalls::System, command); + if (res) { + WriteAlert(_("Can not convert file"), + "Error while executing", + command.substr(0, 50)); + return false; + } + } + } + + return true; +} + + +string Converter::SplitFormat(string const & str, string & format) +{ + string using_format = split(str, format, ':'); + if (format.empty()) + format = "dvi"; + return using_format; +} + +bool Converter::runLaTeX(Buffer * buffer, string const & command) +{ + + BufferView * bv = buffer->getUser(); + + if (!bv->text) return 0; + + ProhibitInput(bv); + + string name = buffer->getLatexName(); + + bv->owner()->getMiniBuffer()->Set(_("Running LaTeX...")); + + // Remove all error insets + bool a = bv->removeAutoInsets(); + + // do the LaTex run(s) + TeXErrors terr; + LaTeX latex(command, name, buffer->filepath); + int result = latex.run(terr, + bv->owner()->getMiniBuffer()); // running latex + + if ((result & LaTeX::ERRORS)) { + // Insert all errors as errors boxes + bv->insertErrors(terr); + } + + // if we removed error insets before we ran LaTeX or if we inserted + // error insets after we ran LaTeX this must be run: + if (a || (result & LaTeX::ERRORS)){ + bv->redraw(); + bv->fitCursor(); + //bv->updateScrollbar(); + } + + // check return value from latex.run(). + if ((result & LaTeX::NO_LOGFILE)) { + WriteAlert(_("LaTeX did not work!"), + _("Missing log file:"), name); + } else if ((result & LaTeX::ERRORS)) { + int num_errors = latex.getNumErrors(); + string s; + string t; + if (num_errors == 1) { + s = _("One error detected"); + t = _("You should try to fix it."); + } else { + s = tostr(num_errors); + s += _(" errors detected."); + t = _("You should try to fix them."); + } + WriteAlert(_("There were errors during the LaTeX run."), + s, t); + } + AllowInput(bv); + + return (result & (LaTeX::NO_LOGFILE | LaTeX::ERRORS)) == 0; + +} + diff --git a/src/converter.h b/src/converter.h new file mode 100644 index 0000000000..02588fee2b --- /dev/null +++ b/src/converter.h @@ -0,0 +1,107 @@ +// -*- C++ -*- +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright 1995 Matthias Ettrich + * Copyright 1995-2000 The LyX Team. + * + * ====================================================== */ + +#ifndef CONVERTER_H +#define CONVERTER_H + +#ifdef __GNUG__ +#pragma interface +#endif + +#include +#include +#include "LString.h" + +class Buffer; + +struct Command { + Command(string const & f, string const & t, string const & c, + bool o) + : from(f), to(t), command(c), original_dir(o) {} + /// + string from; + /// + string to; + /// + string command; + /// + bool original_dir; + /// + bool visited; + /// + std::vector::iterator previous; +}; + +class Format { +public: + Format() : in_degree(0) {} + /// + Format(string const & n); + /// + string name; + /// + string prettyname; + /// + string viewer; + /// + int in_degree; +}; + +class Formats { +public: + /// + static + void Add(string const & name); + /// + static + void SetViewer(string const & name, string const & command); + /// + static + bool View(string const & filename); + /// + static + Format * GetFormat(string const & name); + /// + static + string PrettyName(string const & name); +private: + /// + static + std::map formats; +}; + +class Converter { +public: + /// + static + void Add(string const & from, string const & to, + string const & command, string const & flags); + /// + static + std::vector > GetReachable(string const & from, + bool only_viewable = false); + /// + static + bool convert(Buffer * buffer, string const & from_file, + string const & to_format); + /// + static + string SplitFormat(string const & str, string & format); +private: + /// + static + bool runLaTeX(Buffer * buffer, string const & command); + /// + static + std::vector commands; +}; + +#endif diff --git a/src/exporter.C b/src/exporter.C new file mode 100644 index 0000000000..3d29b191ac --- /dev/null +++ b/src/exporter.C @@ -0,0 +1,111 @@ +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright 1995 Matthias Ettrich + * Copyright 1995-2000 The LyX Team. + * + * ====================================================== */ + +#include + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include +#include + +#include "exporter.h" +#include "converter.h" + +#include "buffer.h" +#include "support/path.h" + + +using std::vector; +using std::pair; + +extern void ShowMessage(Buffer * buf, + string const & msg1, + string const & msg2 = string(), + string const & msg3 = string(), int delay = 6); + +bool Exporter::Export(Buffer * buffer, string const & format0, + bool put_in_tempdir) +{ + string using_format, format; + using_format = Converter::SplitFormat(format0, format); + + string filename = buffer->fileName(); + string backend_format = BufferExtension(buffer); + bool only_backend = backend_format == format; + + //string file = buffer->getLatexName(true); + string file = filename; + if (!buffer->tmppath.empty()) + file = AddName(buffer->tmppath, file); + file = ChangeExtension(file, backend_format); + + if (buffer->isLinuxDoc()) + buffer->makeLinuxDocFile(file, only_backend); + else if (only_backend) + buffer->makeLaTeXFile(file, string(), true); + else + buffer->makeLaTeXFile(file, buffer->filepath, false); + + bool return_value = Converter::convert(buffer, file, format0); + if (!return_value) + return false; + + if (!put_in_tempdir) { + file = ChangeExtension(file, format); + string outfile = ChangeExtension(filename, format); + if (file != outfile) + rename(file.c_str(), outfile.c_str()); + + ShowMessage(buffer, + _("Document exported as ") + + Formats::PrettyName(format) + + _(" to file `") + + MakeDisplayPath(outfile) +'\''); + } + return true; +} + + +bool Exporter::Preview(Buffer * buffer, string const & format0) +{ + if (!Export(buffer, format0, true)) + return false; + + string format; + Converter::SplitFormat(format0, format); + + string filename = buffer->fileName(); + if (!buffer->tmppath.empty()) + filename = AddName(buffer->tmppath, filename); + filename = ChangeExtension(filename, format); + return Formats::View(filename); +} + + +vector > Exporter::GetExportableFormats(Buffer * buffer) +{ + return Converter::GetReachable(BufferExtension(buffer), false); +} + + +vector > Exporter::GetViewableFormats(Buffer * buffer) +{ + return Converter::GetReachable(BufferExtension(buffer), true); +} + +string Exporter::BufferExtension(Buffer * buffer) +{ + if (buffer->isLinuxDoc()) + return "sgml"; + else + return "tex"; +} diff --git a/src/exporter.h b/src/exporter.h new file mode 100644 index 0000000000..ce57770b2e --- /dev/null +++ b/src/exporter.h @@ -0,0 +1,46 @@ +// -*- C++ -*- +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright 1995 Matthias Ettrich + * Copyright 1995-2000 The LyX Team. + * + * ====================================================== */ + +#ifndef EXPORTER_H +#define EXPORTER_H + +#ifdef __GNUG__ +#pragma interface +#endif + +#include +#include "LString.h" + +class Buffer; + +class Exporter { +public: + /// + static + bool Export(Buffer * buffer, string const & format, + bool put_in_tempdir); + /// + static + bool Preview(Buffer * buffer, string const & format); + /// + static + std::vector > GetExportableFormats(Buffer * buffer); + /// + static + std::vector > GetViewableFormats(Buffer * buffer); + /// + static + string BufferExtension(Buffer * buffer); +}; + +//#define NEW_EXPORT 1 + +#endif diff --git a/src/frontends/Liason.C b/src/frontends/Liason.C index b528bfe2b1..35c1513158 100644 --- a/src/frontends/Liason.C +++ b/src/frontends/Liason.C @@ -24,6 +24,7 @@ #include "support/lstrings.h" #include "support/filetools.h" #include "support/path.h" +#include "exporter.h" #include "minibuffer.h" extern LyXRC lyxrc; @@ -171,6 +172,7 @@ bool printBuffer(Buffer * buffer, PrinterParams const & pp) } Path p(path); +#ifndef NEW_EXPORT // there are three cases here: // 1. we print to a file // 2. we print direct to a printer @@ -207,6 +209,7 @@ bool printBuffer(Buffer * buffer, PrinterParams const & pp) result = RunScript(buffer, false, command); break; } +#endif return result; } diff --git a/src/frontends/xforms/Menubar_pimpl.C b/src/frontends/xforms/Menubar_pimpl.C index 3e5b32d1cd..54ce4c9f70 100644 --- a/src/frontends/xforms/Menubar_pimpl.C +++ b/src/frontends/xforms/Menubar_pimpl.C @@ -28,6 +28,7 @@ #include "LyXView.h" #include "MenuBackend.h" #include "Menubar_pimpl.h" +#include "exporter.h" using std::endl; @@ -268,6 +269,30 @@ void Menubar::Pimpl::add_documents(int menu, string const & extra_label, } +void Menubar::Pimpl::add_formats(int menu, string const & extra_label, + std::vector & /*smn*/, + StrPool & strpool, + kb_action action, bool viewable) +{ + std::vector > names = + viewable + ? Exporter::GetViewableFormats(owner_->buffer()) + : Exporter::GetExportableFormats(owner_->buffer()); + + for (std::vector >::const_iterator cit = names.begin(); + cit != names.end() ; ++cit) { + int action2 = + lyxaction.getPseudoAction(action, (*cit).first); + string label = (*cit).second + + "%x" + tostr(action2); + if ((cit + 1) == names.end()) + label += extra_label; + + fl_addtopup(menu, strpool.add(label)); + } +} + + int Menubar::Pimpl::create_submenu(Window win, LyXView * view, string const & menu_name, std::vector & smn, StrPool & strpool) @@ -403,11 +428,25 @@ int Menubar::Pimpl::create_submenu(Window win, LyXView * view, add_documents(menu, extra_label, smn, strpool); break; - case MenuItem::Lastfiles: add_lastfiles(menu, extra_label, smn, strpool); break; + case MenuItem::ViewFormats: + add_formats(menu, extra_label, smn, strpool, + LFUN_PREVIEW, true); + break; + + case MenuItem::UpdateFormats: + add_formats(menu, extra_label, smn, strpool, + LFUN_UPDATE, true); + break; + + case MenuItem::ExportFormats: + add_formats(menu, extra_label, smn, strpool, + LFUN_EXPORT, false); + break; + } } return menu; diff --git a/src/frontends/xforms/Menubar_pimpl.h b/src/frontends/xforms/Menubar_pimpl.h index 0b4a472264..2a54412bed 100644 --- a/src/frontends/xforms/Menubar_pimpl.h +++ b/src/frontends/xforms/Menubar_pimpl.h @@ -21,6 +21,7 @@ #include #include "LString.h" #include "frontends/Menubar.h" +#include "commandtags.h" #include FORMS_H_LOCATION class LyXView; class MenuBackend; @@ -56,6 +57,11 @@ public: */ void add_documents(int menu, string const & extra_label, std::vector & smn, StrPool & strpool); + /// Add to "menu" the list of exportable/viewable formats + /// (add "extra_label" to the last entry) + void add_formats(int menu, string const & extra_label, + std::vector & smn, StrPool & strpool, + kb_action action, bool viewable); /// int create_submenu(Window win, LyXView * view, string const & menuname, diff --git a/src/lyx_cb.C b/src/lyx_cb.C index 44998546b2..c5e2f5fb0d 100644 --- a/src/lyx_cb.C +++ b/src/lyx_cb.C @@ -43,6 +43,7 @@ #include "lyxrc.h" #include "lyxtext.h" #include "CutAndPaste.h" +#include "exporter.h" using std::ifstream; using std::copy; @@ -297,7 +298,7 @@ bool MenuWriteAs(Buffer * buffer) return true; } - +#ifndef NEW_EXPORT int MenuRunLaTeX(Buffer * buffer) { int ret = 0; @@ -326,7 +327,7 @@ int MenuRunLaTeX(Buffer * buffer) } return ret; } - +#endif int MenuBuildProg(Buffer * buffer) { @@ -388,7 +389,7 @@ int MenuRunChktex(Buffer * buffer) return ret; } - +#ifndef NEW_EXPORT int MakeLaTeXOutput(Buffer * buffer) { // Who cares? @@ -601,7 +602,7 @@ bool PreviewPostscript(Buffer * buffer) AllowInput(current_view); return ret; } - +#endif void MenuFax(Buffer * buffer) { @@ -609,6 +610,15 @@ void MenuFax(Buffer * buffer) //if (!bv->text) // return; +#ifdef NEW_EXPORT + // Generate postscript file + if (!Exporter::Export(buffer, "ps", true)) + return; + + // Send fax + string ps = OnlyFilename(ChangeExtension (buffer->fileName(), + ".ps")); +#else // Generate postscript file if (!CreatePostscript(buffer, true)) { return; @@ -617,6 +627,7 @@ void MenuFax(Buffer * buffer) // Send fax string ps = OnlyFilename(ChangeExtension (buffer->fileName(), ".ps_tmp")); +#endif string path = OnlyPath (buffer->fileName()); if (lyxrc.use_tempdir || (IsDirWriteable(path) < 1)) { path = buffer->tmppath; @@ -631,6 +642,7 @@ void MenuFax(Buffer * buffer) } +#ifndef NEW_EXPORT // Returns false if we fail bool PreviewDVI(Buffer * buffer) { @@ -952,6 +964,7 @@ void MenuExport(Buffer * buffer, string const & extyp) ShowMessage(buffer, _("Unknown export type: ") + extyp); } } +#endif void QuitLyX() @@ -1169,7 +1182,7 @@ void LayoutsCB(int sel, void *) tmp.c_str()); } - +#ifndef NEW_EXPORT /* * SGML Linuxdoc support: * (flag == 0) make TeX output @@ -1287,7 +1300,7 @@ int RunDocBook(int flag, string const & filename) current_view->buffer()->redraw(); return errorcode; } - +#endif void MenuLayoutCharacter() { diff --git a/src/lyxfunc.C b/src/lyxfunc.C index 32984cbd0c..79d0dc66a0 100644 --- a/src/lyxfunc.C +++ b/src/lyxfunc.C @@ -92,6 +92,7 @@ using std::istringstream; #include "menus.h" #endif #include "FloatList.h" +#include "exporter.h" #include "FontLoader.h" #include "TextCache.h" @@ -112,15 +113,21 @@ extern kb_keymap * toplevel_keymap; extern bool MenuWrite(Buffer *); extern bool MenuWriteAs(Buffer *); +#ifdef NEW_MENUBAR extern int MenuRunLaTeX(Buffer *); +#endif extern int MenuBuildProg(Buffer *); extern int MenuRunChktex(Buffer *); +#ifndef NEW_EXPORT extern bool CreatePostscript(Buffer *, bool); +#endif extern void MenuPrint(Buffer *); extern void MenuSendto(); extern void QuitLyX(); extern void MenuFax(Buffer *); +#ifndef NEW_EXPORT extern void MenuExport(Buffer *, string const &); +#endif extern void show_symbols_form(LyXFunc *); extern LyXAction lyxaction; @@ -128,8 +135,10 @@ extern LyXAction lyxaction; extern tex_accent_struct get_accent(kb_action action); extern void AutoSave(BufferView *); +#ifndef NEW_EXPORT extern bool PreviewDVI(Buffer *); extern bool PreviewPostscript(Buffer *); +#endif extern void MenuInsertLabel(char const *); extern void MenuLayoutCharacter(); extern void MenuLayoutParagraph(); @@ -486,6 +495,7 @@ LyXFunc::func_status LyXFunc::getStatus(int ac) const static bool noLaTeX = lyxrc.latex_command == "none"; bool disable = false; switch (action) { +#ifndef NEW_EXPORT case LFUN_PREVIEW: disable = noLaTeX || lyxrc.view_dvi_command == "none"; break; @@ -496,6 +506,7 @@ LyXFunc::func_status LyXFunc::getStatus(int ac) const case LFUN_RUNDVIPS: disable = noLaTeX; break; +#endif case LFUN_MENUPRINT: disable = noLaTeX || lyxrc.print_command == "none"; break; @@ -508,6 +519,7 @@ LyXFunc::func_status LyXFunc::getStatus(int ac) const else if (argument == "linuxdoc") disable = lyxrc.linuxdoc_to_lyx_command == "none"; break; +#ifndef NEW_EXPORT case LFUN_EXPORT: if (argument == "latex") disable = (! buf->isLatex() && ! buf->isLiterate()) ; @@ -527,6 +539,7 @@ LyXFunc::func_status LyXFunc::getStatus(int ac) const else if (argument == "custom") disable = (! buf->isLatex() && ! buf->isLiterate()); break; +#endif case LFUN_UNDO: disable = buf->undostack.empty(); break; @@ -963,6 +976,15 @@ string LyXFunc::Dispatch(int ac, reloadBuffer(); break; +#ifdef NEW_EXPORT + case LFUN_UPDATE: + Exporter::Export(owner->buffer(), argument, true); + break; + + case LFUN_PREVIEW: + Exporter::Preview(owner->buffer(), argument); + break; +#else case LFUN_PREVIEW: PreviewDVI(owner->buffer()); break; @@ -974,6 +996,11 @@ string LyXFunc::Dispatch(int ac, case LFUN_RUNLATEX: MenuRunLaTeX(owner->buffer()); break; + + case LFUN_RUNDVIPS: + CreatePostscript(owner->buffer(), false); + break; +#endif case LFUN_BUILDPROG: MenuBuildProg(owner->buffer()); @@ -982,11 +1009,7 @@ string LyXFunc::Dispatch(int ac, case LFUN_RUNCHKTEX: MenuRunChktex(owner->buffer()); break; - - case LFUN_RUNDVIPS: - CreatePostscript(owner->buffer(), false); - break; - + case LFUN_MENUPRINT: owner->getDialogs()->showPrint(); break; @@ -996,7 +1019,11 @@ string LyXFunc::Dispatch(int ac, break; case LFUN_EXPORT: +#ifdef NEW_EXPORT + Exporter::Export(owner->buffer(), argument, false); +#else MenuExport(owner->buffer(), argument); +#endif break; case LFUN_IMPORT: diff --git a/src/lyxrc.C b/src/lyxrc.C index 414080eae2..8a50c1cdb7 100644 --- a/src/lyxrc.C +++ b/src/lyxrc.C @@ -30,6 +30,7 @@ #include "support/path.h" #include "support/filetools.h" #include "lyxtext.h" +#include "converter.h" using std::ostream; using std::ofstream; @@ -155,6 +156,8 @@ enum LyXRCTags { RC_DOCBOOK_TO_HTML_COMMAND, RC_DOCBOOK_TO_PDF_COMMAND, RC_WHEEL_JUMP, + RC_CONVERTER, + RC_VIEWER, RC_NEW_ASK_FILENAME, RC_LAST }; @@ -176,6 +179,7 @@ keyword_item lyxrcTags[] = { { "\\build_error_filter", RC_BUILD_ERROR_FILTER }, { "\\check_lastfiles", RC_CHECKLASTFILES }, { "\\chktex_command", RC_CHKTEX_COMMAND }, + { "\\converter", RC_CONVERTER }, { "\\cursor_follows_scrollbar", RC_CURSOR_FOLLOWS_SCROLLBAR }, { "\\custom_export_command", RC_CUSTOM_EXPORT_COMMAND }, { "\\custom_export_format", RC_CUSTOM_EXPORT_FORMAT }, @@ -270,6 +274,7 @@ keyword_item lyxrcTags[] = { { "\\view_pdf_command", RC_VIEWPDF_COMMAND }, { "\\view_ps_command", RC_VIEWPS_COMMAND }, { "\\view_pspic_command", RC_VIEWPSPIC_COMMAND }, + { "\\viewer" ,RC_VIEWER}, { "\\wheel_jump", RC_WHEEL_JUMP } }; @@ -1106,6 +1111,34 @@ int LyXRC::read(string const & filename) if ( lexrc.next()) new_ask_filename = lexrc.GetBool(); break; + case RC_CONVERTER: + { + string from, to, command, flags; + if (lexrc.next()) + from = lexrc.GetString(); + if (lexrc.next()) + to = lexrc.GetString(); + if (lexrc.next()) + command = lexrc.GetString(); + if (lexrc.next()) + flags = lexrc.GetString(); + command = subst(command, "$$FName", "'$$FName'"); + command = subst(command, "$$BaseName", "'$$BaseName'"); + command = subst(command, "$$OutName", "'$$OutName'"); + Converter::Add(from, to, command, flags); + break; + } + case RC_VIEWER: + { + string format, command; + if (lexrc.next()) + format = lexrc.GetString(); + if (lexrc.next()) + command = lexrc.GetString(); + command = subst(command, "$$FName", "'$$FName'"); + Formats::SetViewer(format, command); + break; + } case RC_LAST: break; // this is just a dummy } diff --git a/src/menus.C b/src/menus.C index e0e1dc9104..b6c24b3b59 100644 --- a/src/menus.C +++ b/src/menus.C @@ -51,10 +51,12 @@ #include "insets/insetref.h" #include "insets/insettabular.h" #include "tabular.h" +#include "exporter.h" #include "frontends/Dialogs.h" using std::vector; +using std::pair; using std::endl; using std::max; using std::min; @@ -499,9 +501,22 @@ void Menus::ShowFileMenu(FL_OBJECT * ob, long) fl_setpup_shortcut(SubFileImport, 34, scex(_("FIM|Dd#d#D"))); // Export sub-menu - +#ifdef NEW_EXPORT + int SubFileExport = fl_defpup(FL_ObjWin(ob), + _("Export%t")); + vector > formats = + Exporter::GetExportableFormats(tmpbuffer); + for (vector >::size_type i = 0; + i < formats.size(); ++i) { + string entry = _("as ") + + formats[i].second + + "%x" + tostr(1000+i); + fl_addtopup(SubFileExport, entry.c_str()); + } +#else // remember to make this handle linuxdoc too. // and now docbook also. + int SubFileExport = 0; if (!LinuxDoc && !DocBook) SubFileExport= fl_defpup(FL_ObjWin(ob), @@ -528,7 +543,6 @@ void Menus::ShowFileMenu(FL_OBJECT * ob, long) "|as PostScript...%x42" "|as Ascii Text...%x43" "|as HTML...%x44")); - fl_setpup_shortcut(SubFileExport, 40, scex(_("FEX|Ll#l#L"))); fl_setpup_shortcut(SubFileExport, 41, scex(_("FEX|Dd#d#D"))); fl_setpup_shortcut(SubFileExport, 42, scex(_("FEX|Pp#p#P"))); @@ -538,6 +552,7 @@ void Menus::ShowFileMenu(FL_OBJECT * ob, long) if (!LinuxDoc && !DocBook) { fl_setpup_shortcut(SubFileExport, 45, scex(_("FEX|mM#m#M"))); } +#endif int FileMenu = fl_defpup(FL_ObjWin(ob), _("New..." @@ -605,6 +620,7 @@ void Menus::ShowFileMenu(FL_OBJECT * ob, long) if ( lyxrc.linuxdoc_to_lyx_command == "none") fl_setpup_mode(SubFileImport, 34, FL_PUP_GREY); +#ifndef NEW_EXPORT if (!hasLaTeX) { // Disable export dvi and export postscript fl_setpup_mode(SubFileExport, 41, FL_PUP_GREY); @@ -617,6 +633,7 @@ void Menus::ShowFileMenu(FL_OBJECT * ob, long) // Disable export HTML fl_setpup_mode(SubFileExport, 44, FL_PUP_GREY); } +#endif // xgettext:no-c-format fl_addtopup(FileMenu, _("|Import%m"), SubFileImport); @@ -660,10 +677,17 @@ void Menus::ShowFileMenu(FL_OBJECT * ob, long) case 5: tmpfunc->Dispatch(LFUN_MENUWRITE); break; case 6: tmpfunc->Dispatch(LFUN_MENUWRITEAS); break; case 7: tmpfunc->Dispatch(LFUN_MENURELOAD); break; +#ifdef NEW_EXPORT + case 8: tmpfunc->Dispatch(LFUN_PREVIEW, "dvi"); break; + case 9: tmpfunc->Dispatch(LFUN_PREVIEW, "ps"); break; + case 10: tmpfunc->Dispatch(LFUN_UPDATE, "dvi"); break; + case 11: tmpfunc->Dispatch(LFUN_UPDATE, "ps"); break; +#else case 8: tmpfunc->Dispatch(LFUN_PREVIEW); break; case 9: tmpfunc->Dispatch(LFUN_PREVIEWPS); break; case 10: tmpfunc->Dispatch(LFUN_RUNLATEX); break; case 11: tmpfunc->Dispatch(LFUN_RUNDVIPS); break; +#endif case 12: tmpfunc->Dispatch(LFUN_BUILDPROG); break; case 13: tmpfunc->Dispatch(LFUN_MENUPRINT); break; case 14: tmpfunc->Dispatch(LFUN_FAX); break; @@ -678,6 +702,20 @@ void Menus::ShowFileMenu(FL_OBJECT * ob, long) break; case 34: tmpfunc->Dispatch(LFUN_IMPORT, "linuxdoc"); break; +#ifdef NEW_EXPORT + case 18: + tmpfunc->Dispatch(LFUN_QUIT); + break; + default: + if (choice >= 1000) + tmpfunc->Dispatch(LFUN_EXPORT, + formats[choice-1000].first.c_str()); + else + men->currentView() + ->buffer(bufferlist + .loadLyXFile((*lastfiles)[choice - 18])); + break; +#else case 16: // export menu case 40: if (!LinuxDoc && !DocBook) @@ -705,6 +743,7 @@ void Menus::ShowFileMenu(FL_OBJECT * ob, long) ->buffer(bufferlist .loadLyXFile((*lastfiles)[choice - 18])); break; +#endif } fl_freepup(SubFileImport); fl_freepup(SubFileExport); diff --git a/src/support/filetools.C b/src/support/filetools.C index b0905d6935..85f5d826d5 100644 --- a/src/support/filetools.C +++ b/src/support/filetools.C @@ -957,6 +957,18 @@ ChangeExtension(string const & oldname, string const & extension) return CleanupPath(oldname.substr(0, last_dot) + ext); } +/// Return the extension of the file (not including the .) +string GetExtension(string const & name) +{ + string::size_type last_slash = name.rfind('/'); + string::size_type last_dot = name.rfind('.'); + if (last_dot != string::npos && + (last_slash == string::npos || last_dot > last_slash)) + return name.substr(last_dot + 1, + name.length() - (last_dot + 1)); + else + return string(); +} // Creates a nice compact path for displaying string const diff --git a/src/support/filetools.h b/src/support/filetools.h index eadc53306e..24dc32bab9 100644 --- a/src/support/filetools.h +++ b/src/support/filetools.h @@ -139,6 +139,9 @@ string const AddPath(string const & path, string const & path2); string const ChangeExtension(string const & oldname, string const & extension); +/// Return the extension of the file (not including the .) +string GetExtension(string const & name); + /// Create absolute path. If impossible, don't do anything string const ExpandPath(string const & path);