diff --git a/lib/layouts/chess.layout b/lib/layouts/chess.layout index 78ea216432..910800074a 100644 --- a/lib/layouts/chess.layout +++ b/lib/layouts/chess.layout @@ -42,6 +42,7 @@ Style Mainline LabelString "Mainline:" Newline 0 PassThru 1 + ParbreakIsNewline 1 TopSep 0.0 ParSep 0.0 LabelFont diff --git a/lib/layouts/db_lyxmacros.inc b/lib/layouts/db_lyxmacros.inc index 4b3f790b13..8db8e8fa8f 100644 --- a/lib/layouts/db_lyxmacros.inc +++ b/lib/layouts/db_lyxmacros.inc @@ -13,6 +13,7 @@ Style Code LatexType Environment LatexName screen PassThru 1 + ParbreakIsNewline 1 End Style LyX-Code diff --git a/lib/layouts/db_stdlayouts.inc b/lib/layouts/db_stdlayouts.inc index 45a654f8bc..533fc57a81 100644 --- a/lib/layouts/db_stdlayouts.inc +++ b/lib/layouts/db_stdlayouts.inc @@ -12,6 +12,7 @@ Style Literal LatexType Environment LatexName literallayout PassThru 1 + ParbreakIsNewline 1 End diff --git a/lib/layouts/elsart.layout b/lib/layouts/elsart.layout index b09230e4af..c48eff7781 100644 --- a/lib/layouts/elsart.layout +++ b/lib/layouts/elsart.layout @@ -149,6 +149,7 @@ Style Author_Email LatexType Command InTitle 1 PassThru 1 + ParbreakIsNewline 1 LatexName ead Align Center Labeltype Static @@ -169,6 +170,7 @@ Style Author_URL LatexType Command InTitle 1 PassThru 1 + ParbreakIsNewline 1 LatexName ead LatexParam "[url]" Align Center diff --git a/lib/layouts/lilypond.module b/lib/layouts/lilypond.module index 45508bab60..a01d68a682 100644 --- a/lib/layouts/lilypond.module +++ b/lib/layouts/lilypond.module @@ -28,5 +28,6 @@ InsetLayout LilyPond ForcePlain true FreeSpacing true PassThru true + ParbreakIsNewline true ForceLTR true End diff --git a/lib/layouts/linguistics.module b/lib/layouts/linguistics.module index 80772aabb7..aadaf927a0 100644 --- a/lib/layouts/linguistics.module +++ b/lib/layouts/linguistics.module @@ -75,6 +75,7 @@ InsetLayout Flex:Glosse CustomPars false ForcePlain true PassThru true + ParbreakIsNewline true FreeSpacing true ForceLTR true Requires covington @@ -103,6 +104,7 @@ InsetLayout Flex:Tri-Glosse CustomPars false ForcePlain true PassThru true + ParbreakIsNewline true FreeSpacing true ForceLTR true InToc true diff --git a/lib/layouts/literate-scrap.inc b/lib/layouts/literate-scrap.inc index 3b0017de0d..b51553606f 100644 --- a/lib/layouts/literate-scrap.inc +++ b/lib/layouts/literate-scrap.inc @@ -13,14 +13,10 @@ Style Scrap Margin First_Dynamic LatexType Paragraph LatexName dummy - NewLine 0 LeftMargin MMM - ParSep 0.4 - TopSep 0.4 - BottomSep 0.4 - ItemSep 0.4 Align Left AlignPossible Block,Left + NewLine 0 FreeSpacing 1 PassThru 1 ParbreakIsNewline 1 diff --git a/lib/layouts/noweb.module b/lib/layouts/noweb.module index cc71c338a8..aff85627a3 100644 --- a/lib/layouts/noweb.module +++ b/lib/layouts/noweb.module @@ -4,14 +4,6 @@ #DescriptionEnd #Category: literate -# Suggested style to write your code: -# Within same scrap, lines are separated by newlines (Ctrl-Return), use: -# ItemSep 0.4 -# . disavantage: must type ctrl-return every single line -# . advantage: looks better (IMHO) -# resembles more closely the produced paper doc (more WYSIWYG) -# - Format 30 OutputType literate @@ -20,14 +12,10 @@ Style Scrap Margin First_Dynamic LatexType Paragraph LatexName dummy - NewLine 0 LeftMargin MMM - ParSep 0.4 - TopSep 0.4 - BottomSep 0.4 - ItemSep 0.4 Align Left AlignPossible Block,Left + NewLine 0 FreeSpacing 1 PassThru 1 ParbreakIsNewline 1 diff --git a/lib/layouts/revtex4.layout b/lib/layouts/revtex4.layout index 15fc8dce80..87e99917cf 100644 --- a/lib/layouts/revtex4.layout +++ b/lib/layouts/revtex4.layout @@ -171,6 +171,7 @@ End Style AltAffiliation CopyStyle Affiliation PassThru 1 + ParbreakIsNewline 1 LatexName altaffiliation OptionalArgs 1 LabelString "AltAffiliation" @@ -196,6 +197,7 @@ End Style Author_Email CopyStyle Affiliation PassThru 1 + ParbreakIsNewline 1 LatexName email OptionalArgs 1 LabelString "Electronic Address:" @@ -211,6 +213,7 @@ End Style Author_URL CopyStyle Author_Email PassThru 1 + ParbreakIsNewline 1 LatexName homepage OptionalArgs 1 LabelString "URL:" diff --git a/lib/layouts/sweave.module b/lib/layouts/sweave.module index a6821ac49a..836ff73e85 100644 --- a/lib/layouts/sweave.module +++ b/lib/layouts/sweave.module @@ -22,10 +22,6 @@ Style Chunk LatexType Paragraph LatexName dummy Margin static - ParSep 0.4 - TopSep 0.4 - BottomSep 0.4 - ItemSep 0.4 Align Left AlignPossible Block, Left, Right, Center NewLine 0 @@ -59,7 +55,8 @@ InsetLayout "Sweave Options" Size Small EndFont MultiPar false - PassThru true + PassThru 1 + ParbreakIsNewline 1 FreeSpacing true ForceLTR true End @@ -79,7 +76,8 @@ InsetLayout "S/R expression" Size Small EndFont MultiPar false - PassThru true + PassThru 1 + ParbreakIsNewline 1 FreeSpacing true ForceLTR true End @@ -99,7 +97,8 @@ InsetLayout "Sweave Input File" Size Small EndFont MultiPar false - PassThru true + PassThru 1 + ParbreakIsNewline 1 FreeSpacing true ForceLTR true End diff --git a/lib/lyx2lyx/lyx2lyx_tools.py b/lib/lyx2lyx/lyx2lyx_tools.py index 426e11d969..bff4808596 100644 --- a/lib/lyx2lyx/lyx2lyx_tools.py +++ b/lib/lyx2lyx/lyx2lyx_tools.py @@ -65,7 +65,7 @@ from unicode_symbols import unicode_reps # This will accept either a list of lines or a single line. -# It is bad practice to pass something with embedded newlines, +# It is bad practice to pass something with embedded newlines, # though we will handle that. def add_to_preamble(document, text): " Add text to the preamble if it is not already there. " diff --git a/lib/lyx2lyx/lyx_2_0.py b/lib/lyx2lyx/lyx_2_0.py index 8f60458d0f..624bad9347 100644 --- a/lib/lyx2lyx/lyx_2_0.py +++ b/lib/lyx2lyx/lyx_2_0.py @@ -1952,6 +1952,142 @@ def convert_bibtex_clearpage(document): j = k + len(subst) +def check_passthru(document): + tc = document.textclass + ok = (tc == "literate-article" or tc == "literate-book" or tc == "literate-report") + if not ok: + mods = document.get_module_list() + for mod in mods: + if mod == "sweave" or mod == "noweb": + ok = True + break + return ok + + +def convert_passthru(document): + " http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg161298.html " + if not check_passthru: + return + + rx = re.compile("\\\\begin_layout \s*(\w+)") + beg = 0 + for lay in ["Chunk", "Scrap"]: + while True: + beg = find_token(document.body, "\\begin_layout " + lay, beg) + if beg == -1: + break + end = find_end_of_layout(document.body, beg) + if end == -1: + document.warning("Can't find end of layout at line " + str(beg)) + beg += 1 + continue + # we are now going to replace newline insets within this layout + # by new instances of this layout. so we have repeated layouts + # instead of newlines. + ns = beg + while True: + ns = find_token(document.body, "\\begin_inset Newline newline", ns, end) + if ns == -1: + break + ne = find_end_of_inset(document.body, ns) + if ne == -1 or ne > end: + document.warning("Can't find end of inset at line " + str(nb)) + ns += 1 + continue + if document.body[ne + 1] == "": + ne += 1 + subst = ["\\end_layout", "", "\\begin_layout " + lay] + document.body[ns:ne + 1] = subst + # now we need to adjust end, in particular, but might as well + # do ns properly, too + newlines = (ne - ns) - len(subst) + ns += newlines + 2 + end += newlines + 1 + # ok, we now want to find out if the next layout is the + # same as this one. if so, we will insert an extra copy of it + didit = False + next = find_token(document.body, "\\begin_layout", end) + if next != -1: + m = rx.match(document.body[next]) + if m: + nextlay = m.group(1) + if nextlay == lay: + subst = ["\\begin_layout " + lay, "", "\\end_layout", ""] + document.body[next:next] = subst + didit = True + beg = end + 1 + if didit: + beg += 4 # for the extra layout + + +def revert_passthru(document): + " http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg161298.html " + if not check_passthru: + return + rx = re.compile("\\\\begin_layout \s*(\w+)") + beg = 0 + for lay in ["Chunk", "Scrap"]: + while True: + beg = find_token(document.body, "\\begin_layout " + lay, beg) + if beg == -1: + break + end = find_end_of_layout(document.body, beg) + if end == -1: + document.warning("Can't find end of layout at line " + str(beg)) + beg += 1 + continue + + # we now want to find out if the next layout is the + # same as this one. but we will need to do this over and + # over again. + while True: + next = find_token(document.body, "\\begin_layout", end) + if next == -1: + break + m = rx.match(document.body[next]) + if not m: + break + nextlay = m.group(1) + if nextlay != lay: + break + # so it is the same layout again. we now want to know if it is empty. + # but first let's check and make sure there is no content between the + # two layouts. i'm not sure if that can happen or not. + for l in range(end + 1, next): + document.warning("c'" + document.body[l] + "'") + if document.body[l] != "": + document.warning("Found content between adjacent " + lay + " layouts!") + break + nextend = find_end_of_layout(document.body, next) + if nextend == -1: + document.warning("Can't find end of layout at line " + str(next)) + break + empty = True + for l in range(next + 1, nextend): + document.warning("e'" + document.body[l] + "'") + if document.body[l] != "": + empty = False + break + if empty: + # empty layouts just get removed + # should we check if it's before yet another such layout? + del document.body[next : nextend + 1] + # and we do not want to check again. we know the next layout + # should be another Chunk and should be left as is. + break + else: + # if it's not empty, then we want to insert a newline in place + # of the layout switch + subst = ["\\begin_inset Newline newline", "\\end_inset", ""] + document.body[end : next + 1] = subst + # and now we have to find the end of the new, larger layout + newend = find_end_of_layout(document.body, beg) + if newend == -1: + document.warning("Can't find end of new layout at line " + str(beg)) + break + end = newend + beg = end + 1 + ## # Conversion hub # @@ -2016,10 +2152,12 @@ convert = [[346, []], [402, [convert_bibtex_clearpage]], [403, [convert_flexnames]], [404, [convert_prettyref]], - [405, []] + [405, []], + [406, [convert_passthru]] ] -revert = [[404, []], +revert = [[405, [revert_passthru]], + [404, []], [403, [revert_refstyle]], [402, [revert_flexnames]], [401, []], diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 2d2ede3c44..bf8e496d51 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -128,7 +128,7 @@ namespace { // Do not remove the comment below, so we get merge conflict in // independent branches. Instead add your own. -int const LYX_FORMAT = 405; // vfr: author hash +int const LYX_FORMAT = 406; // rgh: passthru changes typedef map DepClean; typedef map > RefCache; diff --git a/src/Cursor.cpp b/src/Cursor.cpp index f6d10cbc97..c2b6d72989 100644 --- a/src/Cursor.cpp +++ b/src/Cursor.cpp @@ -26,6 +26,7 @@ #include "FuncCode.h" #include "FuncRequest.h" #include "Language.h" +#include "Layout.h" #include "LyXAction.h" #include "LyXRC.h" #include "Paragraph.h" @@ -2016,15 +2017,18 @@ void Cursor::errorMessage(docstring const & msg) const } -static docstring parbreak(InsetCode code) +namespace { +docstring parbreak(Cursor const * cur) { odocstringstream os; os << '\n'; - // only add blank line if we're not in an ERT or Listings inset - if (code != ERT_CODE && code != LISTINGS_CODE) + // only add blank line if we're not in a ParbreakIsNewline situation + if (!cur->inset().getLayout().parbreakIsNewline() + && !cur->paragraph().layout().parbreak_is_newline) os << '\n'; return os.str(); } +} docstring Cursor::selectionAsString(bool with_label) const @@ -2060,13 +2064,13 @@ docstring Cursor::selectionAsString(bool with_label) const // First paragraph in selection docstring result = pars[startpit]. asString(startpos, pars[startpit].size(), label) - + parbreak(inset().lyxCode()); + + parbreak(this); // The paragraphs in between (if any) for (pit_type pit = startpit + 1; pit != endpit; ++pit) { Paragraph const & par = pars[pit]; result += par.asString(0, par.size(), label) - + parbreak(inset().lyxCode()); + + parbreak(this); } // Last paragraph in selection diff --git a/src/CutAndPaste.cpp b/src/CutAndPaste.cpp index 18993152f3..9bed935d38 100644 --- a/src/CutAndPaste.cpp +++ b/src/CutAndPaste.cpp @@ -124,10 +124,9 @@ pasteSelectionHelper(Cursor & cur, ParagraphList const & parlist, // Now remove all out of the pars which is NOT allowed in the // new environment and set also another font if that is required. - // Convert newline to paragraph break in ERT inset. - // This should not be here! - InsetCode const code = target_inset->lyxCode(); - if (code == ERT_CODE || code == LISTINGS_CODE) { + // Convert newline to paragraph break in ParbreakIsNewline + if (target_inset->getLayout().parbreakIsNewline() + || pars[pit].layout().parbreak_is_newline) { for (size_t i = 0; i != insertion.size(); ++i) { for (pos_type j = 0; j != insertion[i].size(); ++j) { if (insertion[i].isNewline(j)) { diff --git a/src/Text.cpp b/src/Text.cpp index f6f75d9045..63cf1734b9 100644 --- a/src/Text.cpp +++ b/src/Text.cpp @@ -599,7 +599,6 @@ static void breakParagraph(Text & text, pit_type par_offset, pos_type pos, // end of a paragraph tmp->setPlainOrDefaultLayout(bparams.documentClass()); - // layout stays the same with latex-environments if (keep_layout) { tmp->setLayout(par.layout()); tmp->setLabelWidthString(par.params().labelWidthString()); @@ -665,7 +664,6 @@ static void breakParagraph(Text & text, pit_type par_offset, pos_type pos, par.setPlainOrDefaultLayout(bparams.documentClass()); } - // layout stays the same with latex-environments if (keep_layout) { par.setLayout(tmp->layout()); par.setLabelWidthString(tmp->params().labelWidthString()); @@ -701,9 +699,10 @@ void Text::breakParagraph(Cursor & cur, bool inverse_logic) cpar.eraseChar(cur.pos(), cur.buffer()->params().trackChanges); // What should the layout for the new paragraph be? - bool keep_layout = inverse_logic ? - !layout.isEnvironment() - : layout.isEnvironment(); + bool keep_layout = layout.isEnvironment() + || (layout.isParagraph() && layout.parbreak_is_newline); + if (inverse_logic) + keep_layout = !keep_layout; // We need to remember this before we break the paragraph, because // that invalidates the layout variable diff --git a/src/output_latex.cpp b/src/output_latex.cpp index 391ccfaee1..ea4d035367 100644 --- a/src/output_latex.cpp +++ b/src/output_latex.cpp @@ -374,14 +374,18 @@ ParagraphList::const_iterator TeXOnePar(Buffer const & buf, open_encoding_ = none; } - if (runparams.pass_thru) { + if (text.inset().getLayout().isPassThru()) { int const dist = distance(paragraphs.begin(), pit); Font const outerfont = text.outerFont(dist); - // No newline if only one paragraph in this lyxtext + // No newline before first paragraph in this lyxtext if (dist > 0) { os << '\n'; texrow.newline(); + if (!text.inset().getLayout().parbreakIsNewline()) { + os << '\n'; + texrow.newline(); + } } pit->latex(bparams, outerfont, os, texrow, @@ -389,6 +393,28 @@ ParagraphList::const_iterator TeXOnePar(Buffer const & buf, return nextpit; } + if (style.pass_thru) { + int const dist = distance(paragraphs.begin(), pit); + Font const outerfont = text.outerFont(dist); + pit->latex(bparams, outerfont, os, texrow, + runparams, start_pos, end_pos); + os << '\n'; + texrow.newline(); + if (!style.parbreak_is_newline) { + os << '\n'; + texrow.newline(); + } else if (nextpit != paragraphs.end()) { + Layout const nextstyle = text.inset().forcePlainLayout() ? + bparams.documentClass().plainLayout() : nextpit->layout(); + if (nextstyle.name() != style.name()) { + os << '\n'; + texrow.newline(); + } + } + + return nextpit; + } + // This paragraph's language Language const * const par_language = pit->getParLanguage(bparams); // The document's language