LyX file-format changes
-----------------------
+2008-03-24 Richard Heck <rgheck@comcast.net>
+ * Format incremented to 322: local layout
+
2008-03-18 Edwin Leuven <e.leuven@uva.nl>
* Format incremented to 321: drop row/col lines and ensure
consistency between cell and row/col lines.
("1_3", [221], minor_versions("1.3" , 7)),
("1_4", range(222,246), minor_versions("1.4" , 5)),
("1_5", range(246,277), minor_versions("1.5" , 2)),
- ("1_6", range(277,322), minor_versions("1.6" , 0))]
+ ("1_6", range(277,323), minor_versions("1.6" , 0))] # rgh: local layout
def formats_list():
'hspace*{\n\\backslash\nfill}\n\\end_layout\n\n\\end_inset\n\n')
+def revert_local_layout(document):
+ ' Revert local layout headers.'
+ i = 0
+ while True:
+ i = find_token(document.header, "\\begin_local_layout", i)
+ if i == -1:
+ return
+ j = find_end_of(document.header, i, "\\begin_local_layout", "\\end_local_layout")
+ if j == -1:
+ # this should not happen
+ break
+ document.header[i : j + 1] = []
+
+
+
##
# Conversion hub
#
[318, []],
[319, [convert_spaceinset, convert_hfill]],
[320, []],
- [321, [convert_tablines]]
+ [321, [convert_tablines]],
+ [322, []]
]
-revert = [[320, [revert_tablines]],
+revert = [[321, [revert_local_layout]],
+ [320, [revert_tablines]],
[319, [revert_protected_hfill]],
[318, [revert_spaceinset, revert_hfills, revert_hspace]],
[317, [remove_extra_embedded_files]],
namespace {
-int const LYX_FORMAT = 321;
+int const LYX_FORMAT = 322; // rgh: local layout
typedef map<string, bool> DepClean;
typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
} else if (token == "\\begin_preamble") {
readPreamble(lex);
+ } else if (token == "\\begin_local_layout") {
+ readLocalLayout(lex);
} else if (token == "\\begin_modules") {
readModules(lex);
} else if (token == "\\options") {
os << "\\end_modules" << '\n';
}
+ // local layout information
+ if (!local_layout.empty()) {
+ // remove '\n' from the end
+ string const tmplocal = rtrim(local_layout, "\n");
+ os << "\\begin_local_layout\n"
+ << tmplocal
+ << "\n\\end_local_layout\n";
+ }
+
// then the text parameters
if (language != ignore_language)
os << "\\language " << language->lang() << '\n';
frontend::Alert::warning(_("Read Error"), msg);
}
}
+ if (!local_layout.empty()) {
+ if (!doc_class_->read(local_layout, TextClass::MODULE)) {
+ docstring const msg = _("Error reading internal layout information");
+ frontend::Alert::warning(_("Read Error"), msg);
+ }
+ }
}
}
+void BufferParams::readLocalLayout(Lexer & lex)
+{
+ if (lex.getString() != "\\begin_local_layout")
+ lyxerr << "Error (BufferParams::readLocalLayout):"
+ "consistency check failed." << endl;
+
+ local_layout = lex.getLongString("\\end_local_layout");
+}
+
+
void BufferParams::readLanguage(Lexer & lex)
{
if (!lex.next()) return;
///
std::string preamble;
///
+ std::string local_layout;
+ ///
std::string options;
///
std::string float_placement;
///
void readPreamble(Lexer &);
///
+ void readLocalLayout(Lexer &);
+ ///
void readLanguage(Lexer &);
///
void readGraphicsDriver(Lexer &);
#include "support/os.h"
#include <algorithm>
+#include <fstream>
#include <sstream>
#include "boost/assert.hpp"
return "input file";
case TextClass::MODULE:
return "module file";
+ case TextClass::VALIDATION:
+ return "validation";
}
// shutup warning
return string();
};
-// Reads a textclass structure from file.
-bool TextClass::read(FileName const & filename, ReadType rt)
-{
- if (!filename.isReadableFile()) {
- lyxerr << "Cannot read layout file `" << filename << "'."
- << endl;
- return false;
- }
+namespace {
keyword_item textClassTags[] = {
{ "classoptions", TC_CLASSOPTIONS },
{ "titlelatextype", TC_TITLELATEXTYPE },
{ "tocdepth", TC_TOCDEPTH }
};
+
+} //namespace anon
+
+
+bool TextClass::convertLayoutFormat(support::FileName const & filename, ReadType rt)
+{
+ LYXERR(Debug::TCLASS, "Converting layout file to " << FORMAT);
+ FileName const tempfile = FileName::tempName();
+ bool success = layout2layout(filename, tempfile);
+ if (success)
+ success = read(tempfile, rt);
+ tempfile.removeFile();
+ return success;
+}
+
+bool TextClass::read(FileName const & filename, ReadType rt)
+{
+ if (!filename.isReadableFile()) {
+ lyxerr << "Cannot read layout file `" << filename << "'."
+ << endl;
+ return false;
+ }
LYXERR(Debug::TCLASS, "Reading " + translateRT(rt) + ": " +
to_utf8(makeDisplayPath(filename.absFilename())));
// Define the `empty' layout used in table cells, ert, etc. Note that
// we do this before loading any layout file, so that classes can
// override features of this layout if they should choose to do so.
- if (rt == BASECLASS) {
+ if (rt == BASECLASS && !hasLayout(emptylayout_)) {
static char const * s = "Margin Static\n"
"LatexType Paragraph\n"
"LatexName dummy\n"
};
layoutlist_.push_back(lay);
}
-
Lexer lexrc(textClassTags,
sizeof(textClassTags) / sizeof(textClassTags[0]));
lexrc.setFile(filename);
+ ReturnValues retval = read(lexrc, rt);
+
+ LYXERR(Debug::TCLASS, "Finished reading " + translateRT(rt) + ": " +
+ to_utf8(makeDisplayPath(filename.absFilename())));
+
+ if (retval != FORMAT_MISMATCH)
+ return retval == OK;
+
+ bool const worx = convertLayoutFormat(filename, rt);
+ if (!worx) {
+ lyxerr << "Unable to convert " << filename <<
+ " to format " << FORMAT << std::endl;
+ return false;
+ }
+ return true;
+}
+
+
+bool TextClass::validate(std::string const & str)
+{
+ TextClass tc;
+ return tc.read(str, VALIDATION);
+}
+
+
+bool TextClass::read(std::string const & str, ReadType rt)
+{
+ Lexer lexrc(textClassTags,
+ sizeof(textClassTags) / sizeof(textClassTags[0]));
+ istringstream is(str);
+ lexrc.setStream(is);
+ ReturnValues retval = read(lexrc, rt);
+
+ if (retval != FORMAT_MISMATCH)
+ return retval == OK;
+
+ // write the layout string to a temporary file
+ FileName const tempfile = FileName::tempName();
+ ofstream os(tempfile.toFilesystemEncoding().c_str());
+ if (!os) {
+ lyxerr << "Unable to create tempoary file in TextClass::read!!"
+ << std::endl;
+ return false;
+ }
+ os << str;
+ os.close();
+
+ // now try to convert it
+ bool const worx = convertLayoutFormat(tempfile, rt);
+ if (!worx) {
+ lyxerr << "Unable to convert internal layout information to format "
+ << FORMAT << std::endl;
+ }
+ tempfile.removeFile();
+ return worx;
+}
+
+
+// Reads a textclass structure from file.
+TextClass::ReturnValues TextClass::read(Lexer & lexrc, ReadType rt)
+{
bool error = !lexrc.isOK();
// Format of files before the 'Format' tag was introduced
+ lexrc.getString() + " is probably not valid UTF-8!";
lexrc.printError(s.c_str());
Layout lay;
- //FIXME If we're just dropping this layout, do we really
- //care whether there's an error?? Or should we just set
- //error to true, since we couldn't even read the name?
+ // Since we couldn't read the name, we just scan the rest
+ // of the style and discard it.
error = !readStyle(lexrc, lay);
} else if (hasLayout(name)) {
Layout & lay = operator[](name);
break;
}
- if (format != FORMAT) {
- LYXERR(Debug::TCLASS, "Converting layout file from format "
- << format << " to " << FORMAT);
- FileName const tempfile = FileName::tempName();
- bool success = layout2layout(filename, tempfile);
- if (success)
- read(tempfile, rt);
- tempfile.removeFile();
- return success;
- }
-
- LYXERR(Debug::TCLASS, "Finished reading " + translateRT(rt) + ": " +
- to_utf8(makeDisplayPath(filename.absFilename())));
+ if (format != FORMAT)
+ return FORMAT_MISMATCH;
if (rt != BASECLASS)
- return !error;
+ return (error ? ERROR : OK);
if (defaultlayout_.empty()) {
lyxerr << "Error: Textclass '" << name_
LYXERR(Debug::TCLASS, "Minimum TocLevel is " << min_toclevel_
<< ", maximum is " << max_toclevel_);
- return !error;
+ return (error ? ERROR : OK);
}
enum ReadType {
BASECLASS, //>This is a base class, i.e., top-level layout file
MERGE, //>This is a file included in a layout file
- MODULE //>This is a layout module
+ MODULE, //>This is a layout module
+ VALIDATION //>We're just validating
};
+ /// return values for read()
+ enum ReturnValues {
+ OK,
+ ERROR,
+ FORMAT_MISMATCH
+ };
+
/// Performs the read of the layout file.
/// \return true on success.
bool read(support::FileName const & filename, ReadType rt = BASECLASS);
+ ///
+ bool read(std::string const & str, ReadType rt = BASECLASS);
+ ///
+ ReturnValues read(Lexer & lex, ReadType rt = BASECLASS);
+ /// validates the layout information passed in str
+ static bool validate(std::string const & str);
///////////////////////////////////////////////////////////////////
// loading
///////////////////////////////////////////////////////////////////
///
bool deleteLayout(docstring const &);
+ ///
+ bool convertLayoutFormat(support::FileName const &, ReadType);
/// \return true for success.
bool readStyle(Lexer &, Layout &);
///
return;
}
}
+ // FIXME Note that by doing things this way, we load the TextClass
+ // as soon as it is selected. So, if you use the scroll wheel when
+ // sitting on the combo box, we'll load a lot of TextClass objects
+ // very quickly. This could be changed.
if (!bp_.setBaseClass(classname)) {
Alert::error(_("Error"), _("Unable to set document class."));
return;