/** * \file VSpace.cpp * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * * \author Matthias Ettrich * * Full author contact details are available in file CREDITS. */ #include #include "VSpace.h" #include "Buffer.h" #include "BufferParams.h" #include "BufferView.h" #include "support/gettext.h" #include "TextMetrics.h" // for defaultRowHeight() #include "support/convert.h" #include "support/Length.h" #include "support/lstrings.h" #include "support/qstring_helpers.h" #include "support/lassert.h" using namespace std; using namespace lyx::support; namespace lyx { // // VSpace class // VSpace::VSpace() : kind_(DEFSKIP), len_(), keep_(false) {} VSpace::VSpace(VSpaceKind k) : kind_(k), len_(), keep_(false) {} VSpace::VSpace(Length const & l) : kind_(LENGTH), len_(l), keep_(false) {} VSpace::VSpace(GlueLength const & l) : kind_(LENGTH), len_(l), keep_(false) {} VSpace::VSpace(string const & data) : kind_(DEFSKIP), len_(), keep_(false) { if (data.empty()) return; string input = rtrim(data); size_t const length = input.length(); if (length > 1 && input[length - 1] == '*') { keep_ = true; input.erase(length - 1); } if (prefixIs(input, "defskip")) kind_ = DEFSKIP; else if (prefixIs(input, "smallskip")) kind_ = SMALLSKIP; else if (prefixIs(input, "medskip")) kind_ = MEDSKIP; else if (prefixIs(input, "bigskip")) kind_ = BIGSKIP; else if (prefixIs(input, "halfline")) kind_ = HALFLINE; else if (prefixIs(input, "fullline")) kind_ = FULLLINE; else if (prefixIs(input, "vfill")) kind_ = VFILL; else if (isValidGlueLength(input, &len_)) kind_ = LENGTH; else if (isStrDbl(input)) { // This last one is for reading old .lyx files // without units in added_space_top/bottom. // Let unit default to centimeters here. kind_ = LENGTH; len_ = GlueLength(Length(convert(input), Length::CM)); } } bool VSpace::operator==(VSpace const & other) const { if (kind_ != other.kind_) return false; if (kind_ != LENGTH) return this->keep_ == other.keep_; if (len_ != other.len_) return false; return keep_ == other.keep_; } string const VSpace::asLyXCommand() const { string result; switch (kind_) { case DEFSKIP: result = "defskip"; break; case SMALLSKIP: result = "smallskip"; break; case MEDSKIP: result = "medskip"; break; case BIGSKIP: result = "bigskip"; break; case HALFLINE: result = "halfline"; break; case FULLLINE: result = "fullline"; break; case VFILL: result = "vfill"; break; case LENGTH: result = len_.asString(); break; } if (keep_) result += '*'; return result; } string const VSpace::asLatexCommand(BufferParams const & params) const { switch (kind_) { case DEFSKIP: return params.getDefSkip().asLatexCommand(params); case SMALLSKIP: return keep_ ? "\\vspace*{\\smallskipamount}" : "\\smallskip{}"; case MEDSKIP: return keep_ ? "\\vspace*{\\medskipamount}" : "\\medskip{}"; case BIGSKIP: return keep_ ? "\\vspace*{\\bigskipamount}" : "\\bigskip{}"; case HALFLINE: return keep_ ? "\\vspace*{.5\\baselineskip}" : "\\vspace{.5\\baselineskip}"; case FULLLINE: return keep_ ? "\\vspace*{\\baselineskip}" : "\\vspace{\\baselineskip}"; case VFILL: return keep_ ? "\\vspace*{\\fill}" : "\\vfill{}"; case LENGTH: return keep_ ? "\\vspace*{" + len_.asLatexString() + '}' : "\\vspace{" + len_.asLatexString() + '}'; default: LATTEST(false); // fall through in release mode } return string(); } docstring const VSpace::asGUIName() const { docstring result; switch (kind_) { case DEFSKIP: result = _("Default skip"); break; case SMALLSKIP: result = _("Small skip"); break; case MEDSKIP: result = _("Medium skip"); break; case BIGSKIP: result = _("Big skip"); break; case HALFLINE: result = _("Half line height"); break; case FULLLINE: result = _("Line height"); break; case VFILL: result = _("Vertical fill"); break; case LENGTH: result = locLengthDocString(from_ascii(len_.asString())); break; } if (keep_) result += ", " + _("protected"); return result; } string VSpace::asHTMLLength() const { string result; switch (kind_) { case DEFSKIP: result = "2ex"; break; case SMALLSKIP: result = "1ex"; break; case MEDSKIP: result = "3ex"; break; case BIGSKIP: result = "5ex"; break; case HALFLINE: result = "0.6em"; break; case FULLLINE: result = "1.2em"; break; case LENGTH: { Length tmp = len_.len(); if (tmp.value() > 0) result = tmp.asHTMLString(); } case VFILL: break; } return result; } int VSpace::inPixels(BufferView const & bv) const { // Height of a normal line in pixels (zoom factor considered) int const default_height = defaultRowHeight(); switch (kind_) { case DEFSKIP: return bv.buffer().params().getDefSkip().inPixels(bv); // This is how the skips are normally defined by LaTeX. // But there should be some way to change this per document. case SMALLSKIP: return default_height / 4; case MEDSKIP: return default_height / 2; case BIGSKIP: return default_height; case VFILL: // leave space for the vfill symbol return 3 * default_height; case HALFLINE: return default_height / 2; case FULLLINE: return default_height; case LENGTH: return bv.inPixels(len_.len()); default: LATTEST(false); // fall through in release mode } return 0; } } // namespace lyx