X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FVSpace.cpp;h=50fc2e50a7455d73cb466d2ecd725d1b583f355e;hb=26ba2a65838731ce639a09539f617cb0f0be3b22;hp=979498797056aaab5f5a8c96f8dcf7faa725ba2c;hpb=9d0ea8aeff32833a90b3fe64df0c5518a9e241be;p=lyx.git diff --git a/src/VSpace.cpp b/src/VSpace.cpp index 9794987970..50fc2e50a7 100644 --- a/src/VSpace.cpp +++ b/src/VSpace.cpp @@ -16,330 +16,20 @@ #include "BufferParams.h" #include "BufferView.h" #include "support/gettext.h" -#include "Length.h" -#include "Text.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" -namespace lyx { - -using support::compare; -using support::isStrDbl; -using support::ltrim; -using support::prefixIs; -using support::rtrim; - -using std::string; - - -namespace { - -/// used to return numeric values in parsing vspace -double number[4] = { 0, 0, 0, 0 }; -/// used to return unit types in parsing vspace -Length::UNIT unit[4] = { Length::UNIT_NONE, - Length::UNIT_NONE, - Length::UNIT_NONE, - Length::UNIT_NONE }; - -/// the current position in the number array -int number_index; -/// the current position in the unit array -int unit_index; - -/// skip n characters of input -inline -void lyx_advance(string & data, string::size_type n) -{ - data.erase(0, n); -} - - -/// return true when the input is at the end -inline -bool isEndOfData(string const & data) -{ - return ltrim(data).empty(); -} - - -/** - * nextToken - return the next token in the input - * @param data input string - * @return a char representing the type of token returned - * - * The possible return values are : - * + stretch indicator for glue length - * - shrink indicator for glue length - * n a numeric value (stored in number array) - * u a unit type (stored in unit array) - * E parse error - */ -char nextToken(string & data) -{ - data = ltrim(data); - - if (data.empty()) - return '\0'; - - if (data[0] == '+') { - lyx_advance(data, 1); - return '+'; - } - - if (prefixIs(data, "plus")) { - lyx_advance(data, 4); - return '+'; - } - - if (data[0] == '-') { - lyx_advance(data, 1); - return '-'; - } - - if (prefixIs(data, "minus")) { - lyx_advance(data, 5); - return '-'; - } - - string::size_type i = data.find_first_not_of("0123456789."); - - if (i != 0) { - if (number_index > 3) - return 'E'; - - string buffer; - - // we have found some number - if (i == string::npos) { - buffer = data; - i = data.size() + 1; - } else - buffer = data.substr(0, i); +using namespace std; +using namespace lyx::support; - lyx_advance(data, i); - - if (isStrDbl(buffer)) { - number[number_index] = convert(buffer); - ++number_index; - return 'n'; - } - return 'E'; - } - - i = data.find_first_not_of("abcdefghijklmnopqrstuvwxyz%"); - if (i != 0) { - if (unit_index > 3) - return 'E'; - - string buffer; - - // we have found some alphabetical string - if (i == string::npos) { - buffer = data; - i = data.size() + 1; - } else - buffer = data.substr(0, i); - - // possibly we have "mmplus" string or similar - if (buffer.size() > 5 && - (buffer.substr(2, 4) == string("plus") || - buffer.substr(2, 5) == string("minus"))) - { - lyx_advance(data, 2); - unit[unit_index] = unitFromString(buffer.substr(0, 2)); - } else { - lyx_advance(data, i); - unit[unit_index] = unitFromString(buffer); - } - - if (unit[unit_index] != Length::UNIT_NONE) { - ++unit_index; - return 'u'; - } - return 'E'; // Error - } - return 'E'; // Error -} - - -/// latex representation of a vspace -struct LaTeXLength { - char const * pattern; - int plus_val_index; - int minus_val_index; - int plus_uni_index; - int minus_uni_index; -}; - - -/// the possible formats for a vspace string -LaTeXLength table[] = { - { "nu", 0, 0, 0, 0 }, - { "nu+nu", 2, 0, 2, 0 }, - { "nu+nu-nu", 2, 3, 2, 3 }, - { "nu+-nu", 2, 2, 2, 2 }, - { "nu-nu", 0, 2, 0, 2 }, - { "nu-nu+nu", 3, 2, 3, 2 }, - { "nu-+nu", 2, 2, 2, 2 }, - { "n+nu", 2, 0, 1, 0 }, - { "n+n-nu", 2, 3, 1, 1 }, - { "n+-nu", 2, 2, 1, 1 }, - { "n-nu", 0, 2, 0, 1 }, - { "n-n+nu", 3, 2, 1, 1 }, - { "n-+nu", 2, 2, 1, 1 }, - { "", 0, 0, 0, 0 } // sentinel, must be empty -}; - - -} // namespace anon - -const char * stringFromUnit(int unit) -{ - if (unit < 0 || unit > num_units) - return 0; - return unit_name[unit]; -} - - -bool isValidGlueLength(string const & data, GlueLength * result) -{ - // This parser is table-driven. First, it constructs a "pattern" - // that describes the sequence of tokens in "data". For example, - // "n-nu" means: number, minus sign, number, unit. As we go along, - // numbers and units are stored into static arrays. Then, "pattern" - // is searched in the "table". If it is found, the associated - // table entries tell us which number and unit should go where - // in the Length structure. Example: if "data" has the "pattern" - // "nu+nu-nu", the associated table entries are "2, 3, 2, 3". - // That means, "plus_val" is the second number that was seen - // in the input, "minus_val" is the third number, and "plus_uni" - // and "minus_uni" are the second and third units, respectively. - // ("val" and "uni" are always the first items seen in "data".) - // This is the most elegant solution I could find -- a straight- - // forward approach leads to very long, tedious code that would be - // much harder to understand and maintain. (AS) - - if (data.empty()) - return true; - string buffer = ltrim(data); - - // To make isValidGlueLength recognize negative values as - // the first number this little hack is needed: - int val_sign = 1; // positive as default - switch (buffer[0]) { - case '-': - lyx_advance(buffer, 1); - val_sign = -1; - break; - case '+': - lyx_advance(buffer, 1); - break; - default: - break; - } - // end of hack - - int pattern_index = 0; - int table_index = 0; - char pattern[20]; - - number_index = 1; - unit_index = 1; // entries at index 0 are sentinels - - // construct "pattern" from "data" - while (!isEndOfData(buffer)) { - if (pattern_index > 20) - return false; - pattern[pattern_index] = nextToken(buffer); - if (pattern[pattern_index] == 'E') - return false; - ++pattern_index; - } - pattern[pattern_index] = '\0'; - - // search "pattern" in "table" - table_index = 0; - while (compare(pattern, table[table_index].pattern)) { - ++table_index; - if (!*table[table_index].pattern) - return false; - } - - // Get the values from the appropriate places. If an index - // is zero, the corresponding array value is zero or UNIT_NONE, - // so we needn't check this. - if (result) { - result->len_.value (number[1] * val_sign); - result->len_.unit (unit[1]); - result->plus_.value (number[table[table_index].plus_val_index]); - result->plus_.unit (unit [table[table_index].plus_uni_index]); - result->minus_.value(number[table[table_index].minus_val_index]); - result->minus_.unit (unit [table[table_index].minus_uni_index]); - } - return true; -} - - -bool isValidLength(string const & data, Length * result) -{ - // This is a trimmed down version of isValidGlueLength. - // The parser may seem overkill for lengths without - // glue, but since we already have it, using it is - // easier than writing something from scratch. - if (data.empty()) - return true; - - string buffer = data; - int pattern_index = 0; - char pattern[3]; - - // To make isValidLength recognize negative values - // this little hack is needed: - int val_sign = 1; // positive as default - switch (buffer[0]) { - case '-': - lyx_advance(buffer, 1); - val_sign = -1; - break; - case '+': - lyx_advance(buffer, 1); - // fall through - default: - // no action - break; - } - // end of hack - - number_index = unit_index = 1; // entries at index 0 are sentinels - - // construct "pattern" from "data" - while (!isEndOfData(buffer)) { - if (pattern_index > 2) - return false; - pattern[pattern_index] = nextToken(buffer); - if (pattern[pattern_index] == 'E') - return false; - ++pattern_index; - } - pattern[pattern_index] = '\0'; - - // only the most basic pattern is accepted here - if (compare(pattern, "nu") != 0) - return false; - - // It _was_ a correct length string. - // Store away the values we found. - if (result) { - result->val_ = number[1] * val_sign; - result->unit_ = unit[1]; - } - return true; -} +namespace lyx { // // VSpace class @@ -373,7 +63,7 @@ VSpace::VSpace(string const & data) string input = rtrim(data); - string::size_type const length = input.length(); + size_t const length = input.length(); if (length > 1 && input[length - 1] == '*') { keep_ = true; @@ -388,6 +78,10 @@ VSpace::VSpace(string const & data) 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_)) @@ -421,12 +115,30 @@ 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 VFILL: result = "vfill"; break; - case LENGTH: result = len_.asString(); break; + 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 += '*'; @@ -448,6 +160,12 @@ string const VSpace::asLatexCommand(BufferParams const & params) const 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{}"; @@ -457,9 +175,10 @@ string const VSpace::asLatexCommand(BufferParams const & params) const : "\\vspace{" + len_.asLatexString() + '}'; default: - BOOST_ASSERT(false); - return string(); + LATTEST(false); + // fall through in release mode } + return string(); } @@ -479,11 +198,17 @@ docstring const VSpace::asGUIName() const 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 = from_ascii(len_.asString()); + result = locLengthDocString(from_ascii(len_.asString())); break; } if (keep_) @@ -492,6 +217,40 @@ docstring const VSpace::asGUIName() const } +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) @@ -502,7 +261,7 @@ int VSpace::inPixels(BufferView const & bv) const case DEFSKIP: return bv.buffer().params().getDefSkip().inPixels(bv); - // This is how the skips are normally defined by LateX. + // 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; @@ -517,13 +276,20 @@ int VSpace::inPixels(BufferView const & bv) const // leave space for the vfill symbol return 3 * default_height; + case HALFLINE: + return default_height / 2; + + case FULLLINE: + return default_height; + case LENGTH: - return len_.len().inPixels(bv.workWidth()); + return bv.inPixels(len_.len()); default: - BOOST_ASSERT(false); - return 0; + LATTEST(false); + // fall through in release mode } + return 0; }