mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-22 10:00:33 +00:00
Add support for document-local layout information. GUI is to follow.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@23913 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
bcf91dd85c
commit
700af7e701
@ -1,6 +1,9 @@
|
||||
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.
|
||||
|
@ -80,7 +80,7 @@ format_relation = [("0_06", [200], minor_versions("0.6" , 4)),
|
||||
("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():
|
||||
|
@ -1631,6 +1631,21 @@ def revert_protected_hfill(document):
|
||||
'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
|
||||
#
|
||||
@ -1680,10 +1695,12 @@ convert = [[277, [fix_wrong_tables]],
|
||||
[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]],
|
||||
|
@ -116,7 +116,7 @@ namespace os = support::os;
|
||||
|
||||
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;
|
||||
|
@ -506,6 +506,8 @@ string BufferParams::readToken(Lexer & lex, string const & token,
|
||||
|
||||
} 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") {
|
||||
@ -722,6 +724,15 @@ void BufferParams::writeFile(ostream & os) const
|
||||
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';
|
||||
@ -1501,6 +1512,12 @@ void BufferParams::makeDocumentClass()
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1555,6 +1572,16 @@ void BufferParams::readPreamble(Lexer & lex)
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
@ -220,6 +220,8 @@ public:
|
||||
///
|
||||
std::string preamble;
|
||||
///
|
||||
std::string local_layout;
|
||||
///
|
||||
std::string options;
|
||||
///
|
||||
std::string float_placement;
|
||||
@ -316,6 +318,8 @@ private:
|
||||
///
|
||||
void readPreamble(Lexer &);
|
||||
///
|
||||
void readLocalLayout(Lexer &);
|
||||
///
|
||||
void readLanguage(Lexer &);
|
||||
///
|
||||
void readGraphicsDriver(Lexer &);
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "support/os.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "boost/assert.hpp"
|
||||
@ -101,6 +102,8 @@ std::string translateRT(TextClass::ReadType rt)
|
||||
return "input file";
|
||||
case TextClass::MODULE:
|
||||
return "module file";
|
||||
case TextClass::VALIDATION:
|
||||
return "validation";
|
||||
}
|
||||
// shutup warning
|
||||
return string();
|
||||
@ -180,14 +183,7 @@ enum TextClassTags {
|
||||
};
|
||||
|
||||
|
||||
// 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 },
|
||||
@ -217,13 +213,35 @@ bool TextClass::read(FileName const & filename, ReadType rt)
|
||||
{ "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"
|
||||
@ -243,11 +261,71 @@ bool TextClass::read(FileName const & filename, ReadType rt)
|
||||
};
|
||||
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
|
||||
@ -316,9 +394,8 @@ bool TextClass::read(FileName const & filename, ReadType rt)
|
||||
+ 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);
|
||||
@ -482,22 +559,11 @@ bool TextClass::read(FileName const & filename, ReadType rt)
|
||||
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_
|
||||
@ -547,7 +613,7 @@ bool TextClass::read(FileName const & filename, ReadType rt)
|
||||
LYXERR(Debug::TCLASS, "Minimum TocLevel is " << min_toclevel_
|
||||
<< ", maximum is " << max_toclevel_);
|
||||
|
||||
return !error;
|
||||
return (error ? ERROR : OK);
|
||||
}
|
||||
|
||||
|
||||
|
@ -127,11 +127,25 @@ public:
|
||||
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
|
||||
@ -242,6 +256,8 @@ private:
|
||||
///////////////////////////////////////////////////////////////////
|
||||
///
|
||||
bool deleteLayout(docstring const &);
|
||||
///
|
||||
bool convertLayoutFormat(support::FileName const &, ReadType);
|
||||
/// \return true for success.
|
||||
bool readStyle(Lexer &, Layout &);
|
||||
///
|
||||
|
@ -1296,6 +1296,10 @@ void GuiDocument::classChanged()
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user