X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ffrontends%2Fxforms%2Fxforms_helpers.C;h=50fb6409d4fb85485fd65cbb49a8008bd56552fa;hb=37e82a546392d43f787826b85481a11f2a27af15;hp=f006a593641c1e592117bc743562a4f829f7ac9f;hpb=f7ba7c8e9f3dcd2a5de79c7e93bf8edeec3b8e35;p=lyx.git diff --git a/src/frontends/xforms/xforms_helpers.C b/src/frontends/xforms/xforms_helpers.C index f006a59364..50fb6409d4 100644 --- a/src/frontends/xforms/xforms_helpers.C +++ b/src/frontends/xforms/xforms_helpers.C @@ -1,68 +1,94 @@ /** * \file xforms_helpers.C - * Copyright 2000-2002 The LyX Team. - * See the file COPYING. + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. * - * \author Angus Leeming, a.leeming@ic.ac.uk + * \author Angus Leeming + * + * Full author contact details are available in file CREDITS. */ #include -#include FORMS_H_LOCATION - -#include // ofstream -#include - -#ifdef __GNUG_ -#pragma implementation -#endif - #include "xforms_helpers.h" -#include "lyxlex.h" + +#include "debug.h" #include "gettext.h" -#include "lyxlength.h" +#include "lengthcommon.h" #include "lyxgluelength.h" -#include "support/LAssert.h" +#include "lyxlex.h" + #include "support/FileInfo.h" #include "support/filetools.h" #include "support/lstrings.h" // frontStrip, strip +#include "support/tostr.h" + +#include "lyx_forms.h" +#include "combox.h" + +#include + +#include + +using std::make_pair; using std::ofstream; -using std::pair; using std::vector; +using std::string; -// Extract shortcut from | string -char const * flyx_shortcut_extract(char const * sc) -{ - // Find '|' in the sc and return the string after that. - register char const * sd = sc; - while (sd[0]!= 0 && sd[0] != '|') ++sd; +namespace lyx { + +using support::AbsolutePath; +using support::FileInfo; +using support::isStrDbl; +using support::OnlyPath; +using support::subst; +using support::trim; - if (sd[0] == '|') { - ++sd; - return sd; +namespace frontend { + +std::string const buildChoiceLengthString() +{ + string data; + for (int i = 0; i != num_units; ++i) { + if (i != 0) + data += "|"; + data += subst(unit_name_gui[i], "%", "%%"); } - return ""; + return data; } -// Extract identifier from | string -char const * flyx_ident_extract(char const * sc) +bool isActive(FL_OBJECT * ob) { - register char const * se = sc; - while (se[0]!= 0 && se[0] != '|') ++se; + return ob && ob->active > 0; +} - if (se[0] == 0) return sc; - char * sb = new char[se - sc + 1]; - int index = 0; - register char const * sd = sc; - while (sd != se) { - sb[index] = sd[0]; - ++index; ++sd; - } - sb[index] = 0; - return sb; +std::pair parse_shortcut(string const & str) +{ + string::size_type i = str.find_first_of("&"); + if (i == string::npos || i == str.length() - 1) + return make_pair(str, string()); + + // FIXME: handle && + + string::value_type c = str[i + 1]; + return make_pair(str.substr(0, i) + str.substr(i + 1), + string("#") + c); +} + + +// A wrapper for the xforms routine, but this one accepts uint args +unsigned long fl_getmcolor(int i, + unsigned int * r, unsigned int * g, unsigned int * b) +{ + int r2, g2, b2; + unsigned long ret_val = ::fl_getmcolor(i, &r2, &g2, &b2); + *r = r2; + *g = g2; + *b = b2; + return ret_val; } @@ -71,7 +97,7 @@ void setEnabled(FL_OBJECT * ob, bool enable) { if (enable) { fl_activate_object(ob); - fl_set_object_lcol(ob, FL_BLACK); + fl_set_object_lcol(ob, FL_LCOL); } else { fl_deactivate_object(ob); fl_set_object_lcol(ob, FL_INACTIVE); @@ -79,197 +105,110 @@ void setEnabled(FL_OBJECT * ob, bool enable) } -// Given an fl_choice, create a vector of its entries -vector const getVectorFromChoice(FL_OBJECT * ob) +// Given an fl_choice or an fl_browser, create a vector of its entries +vector const getVector(FL_OBJECT * ob) { - vector vec; - if (!ob || ob->objclass != FL_CHOICE) - return vec; + vector vec; - for(int i = 0; i < fl_get_choice_maxitems(ob); ++i) { - string const text = fl_get_choice_item_text(ob, i+1); - vec.push_back(strip(frontStrip(text))); + switch (ob->objclass) { + case FL_CHOICE: + for(int i = 0; i < fl_get_choice_maxitems(ob); ++i) { + string const text = fl_get_choice_item_text(ob, i+1); + vec.push_back(trim(text)); + } + break; + case FL_BROWSER: + for(int i = 0; i < fl_get_browser_maxline(ob); ++i) { + string const text = fl_get_browser_line(ob, i+1); + vec.push_back(trim(text)); + } + break; + default: + BOOST_ASSERT(false); } return vec; } -/// Given an fl_input, return its contents. -string const getStringFromInput(FL_OBJECT * ob) +/// +string const getString(FL_OBJECT * ob, int line) { - if (!ob || ob->objclass != FL_INPUT) - return string(); - - char const * tmp = fl_get_input(ob); - return (tmp) ? tmp : string(); -} + // Negative line value does not make sense. + BOOST_ASSERT(line >= 0); + char const * tmp = 0; + switch (ob->objclass) { + case FL_INPUT: + tmp = fl_get_input(ob); + break; -// Given an fl_browser, return the contents of line -string const getStringFromBrowser(FL_OBJECT * ob, int line) -{ - if (!ob || ob->objclass != FL_BROWSER || - line < 1 || line > fl_get_browser_maxline(ob)) - return string(); - - char const * tmp = fl_get_browser_line(ob, line); - return (tmp) ? tmp : string(); -} + case FL_BROWSER: + if (line == 0) + line = fl_get_browser(ob); -// Given an fl_browser, return the contents of the currently -// highlighted line. -// If nothing is selected, return an empty string -string const getSelectedStringFromBrowser(FL_OBJECT * ob) -{ - if (!ob || ob->objclass != FL_BROWSER) - return string(); - - int const line = fl_get_browser(ob); - if (line < 1 || line > fl_get_browser_maxline(ob)) - return string(); - - if (!fl_isselected_browser_line(ob, line)) - return string(); + if (line >= 1 && line <= fl_get_browser_maxline(ob)) + tmp = fl_get_browser_line(ob, line); + break; - char const * tmp = fl_get_browser_line(ob, line); - return (tmp) ? tmp : string(); -} + case FL_CHOICE: + if (line == 0) + line = fl_get_choice(ob); + if (line >= 1 && line <= fl_get_choice_maxitems(ob)) + tmp = fl_get_choice_item_text(ob, line); + break; -// Given an fl_browser, create a vector of its entries -vector const getVectorFromBrowser(FL_OBJECT * ob) -{ - vector vec; - if (!ob || ob->objclass != FL_BROWSER) - return vec; + case FL_COMBOX: + tmp = fl_get_combox_text(ob); + break; - for(int i = 0; i < fl_get_browser_maxline(ob); ++i) { - string const text = fl_get_browser_line(ob, i+1); - vec.push_back(strip(frontStrip(text))); + default: + BOOST_ASSERT(false); } - return vec; + return tmp ? trim(tmp) : string(); } - string getLengthFromWidgets(FL_OBJECT * input, FL_OBJECT * choice) { // Paranoia check - lyx::Assert(input && input->objclass == FL_INPUT && + BOOST_ASSERT(input && input->objclass == FL_INPUT && choice && choice->objclass == FL_CHOICE); - string const length = strip(frontStrip(fl_get_input(input))); + string const length = trim(fl_get_input(input)); if (length.empty()) return string(); - //don't return unit-from-choice if the input(field) contains a unit + // don't return unit-from-choice if the input(field) contains a unit if (isValidGlueLength(length)) return length; - string unit = strip(frontStrip(fl_get_choice_text(choice))); + string unit = trim(fl_get_choice_text(choice)); unit = subst(unit, "%%", "%"); return length + unit; } -#if 0 -// old code which can be deleted if the new one, now enabled, -// works satisfyingly (JSpitzm, 11/02/2002) -// this should definitely be the other way around!!! -void updateWidgetsFromLength(FL_OBJECT * input, FL_OBJECT * choice, - LyXLength const & len, - string const & default_unit) -{ - if (len.zero()) - updateWidgetsFromLengthString(input, choice, - string(), default_unit); - // use input field only for gluelengths - else if (!isValidLength(len) && !isStrDbl(len)) { - fl_set_input(input, len.c_str()); - fl_set_choice_text(choice, default_unit.c_str()); - } - else - updateWidgetsFromLengthString(input, choice, - len.asString(), default_unit); - -} - - -// Most of the code here is a poor duplication of the parser code -// which is in LyXLength. Use that instead void updateWidgetsFromLengthString(FL_OBJECT * input, FL_OBJECT * choice, string const & str, string const & default_unit) { // Paranoia check - lyx::Assert(input && input->objclass == FL_INPUT && - choice && choice->objclass == FL_CHOICE); - - if (str.empty()) { - fl_set_input(input, ""); - int unitpos = 1; // xforms has Fortran-style indexing - for(int i = 0; i < fl_get_choice_maxitems(choice); ++i) { - string const text = fl_get_choice_item_text(choice,i+1); - if (default_unit == - lowercase(strip(frontStrip(text)))) { - unitpos = i+1; - break; - } - } - fl_set_choice(choice, unitpos); - return; - } - - // The unit is presumed to begin at the first char a-z - // or with the char '%' - string const tmp = lowercase(strip(frontStrip(str))); - - string::const_iterator p = tmp.begin(); - for (; p != tmp.end(); ++p) { - if ((*p >= 'a' && *p <= 'z') || *p == '%') - break; - } - - string len = "0"; - int unitpos = 1; // xforms has Fortran-style indexing - - if (p == tmp.end()) { - if (isStrDbl(tmp)) - len = tmp; + BOOST_ASSERT(input && input->objclass == FL_INPUT && + choice && choice->objclass == FL_CHOICE); - } else { - string tmplen = string(tmp.begin(), p); - if (isStrDbl(tmplen)) - len = tmplen; - string unit = string(p, tmp.end()); - unit = subst(unit, "%", "%%"); - - for(int i = 0; i < fl_get_choice_maxitems(choice); ++i) { - string const text = fl_get_choice_item_text(choice,i+1); - if (unit == lowercase(strip(frontStrip(text)))) { - unitpos = i+1; - break; - } - } - } - - fl_set_input(input, len.c_str()); - fl_set_choice(choice, unitpos); -} -#else -void updateWidgetsFromLengthString(FL_OBJECT * input, FL_OBJECT * choice, - string const & str, - string const & default_unit) -{ // use input field only for gluelengths if (!isValidLength(str) && !isStrDbl(str)) { fl_set_input(input, str.c_str()); + // we assume that "default_unit" is in the choice as "we" + // have control over that! + // No need to check for its presence in the choice, therefore. fl_set_choice_text(choice, default_unit.c_str()); } else { updateWidgetsFromLength(input, choice, - LyXLength(str), default_unit); + LyXLength(str), default_unit); } } @@ -279,94 +218,44 @@ void updateWidgetsFromLength(FL_OBJECT * input, FL_OBJECT * choice, string const & default_unit) { // Paranoia check - lyx::Assert(input && input->objclass == FL_INPUT && - choice && choice->objclass == FL_CHOICE); + BOOST_ASSERT(input && input->objclass == FL_INPUT && + choice && choice->objclass == FL_CHOICE); - if (len.zero()) { + if (len.empty()) { fl_set_input(input, ""); fl_set_choice_text(choice, default_unit.c_str()); } else { - ostringstream buffer; - buffer << len.value(); - fl_set_input(input, buffer.str().c_str()); - fl_set_choice_text(choice, - subst(stringFromUnit(len.unit()),"%","%%").c_str()); + fl_set_input(input, tostr(len.value()).c_str()); + + // Set the choice to the desired unit, if present in the choice. + // Else set the choice to the default unit. + string const unit = subst(stringFromUnit(len.unit()),"%","%%"); + + vector const vec = getVector(choice); + vector::const_iterator it = + std::find(vec.begin(), vec.end(), unit); + if (it != vec.end()) { + fl_set_choice_text(choice, unit.c_str()); + } else { + fl_set_choice_text(choice, default_unit.c_str()); + } } } -#endif // Take a string and add breaks so that it fits into a desired label width, w string formatted(string const & sin, int w, int size, int style) { string sout; - if (sin.empty()) return sout; - -#if 0 - // FIX: Q: Why cant this be done by a one pass algo? (Lgb) - - // breaks in up into a vector of individual words - vector sentence; - string word; - for (string::const_iterator sit = sin.begin(); - sit != sin.end(); ++sit) { - if ((*sit) == ' ' || (*sit) == '\n') { - if (!word.empty()) { - sentence.push_back(word); - word.erase(); - } - if ((*sit) == '\n') word += '\n'; - - } else { - word += (*sit); - } - } - - // Flush remaining contents of word - if (!word.empty()) sentence.push_back(word); - - string line; - string line_plus_word; - for (vector::const_iterator vit = sentence.begin(); - vit != sentence.end(); ++vit) { - string word(*vit); - - char c = word[0]; - if (c == '\n') { - sout += line + '\n'; - word.erase(0,1); - line_plus_word.erase(); - line.erase(); - } - - if (!line_plus_word.empty()) line_plus_word += ' '; - line_plus_word += word; + if (sin.empty()) + return sout; - int const length = fl_get_string_width(style, size, - line_plus_word.c_str(), - int(line_plus_word.length())); - if (length >= w) { - sout += line + '\n'; - line_plus_word = word; - } - - line = line_plus_word; - } - // Flush remaining contents of line - if (!line.empty()) { - sout += line; - } - - if (sout[sout.length() - 1] == '\n') - sout.erase(sout.length() - 1); - -#else string::size_type curpos = 0; string line; for(;;) { string::size_type const nxtpos1 = sin.find(' ', curpos); string::size_type const nxtpos2 = sin.find('\n', curpos); - string::size_type const nxtpos = std::min(nxtpos1, nxtpos1); + string::size_type const nxtpos = std::min(nxtpos1, nxtpos2); string const word = nxtpos == string::npos ? sin.substr(curpos) : sin.substr(curpos, nxtpos-curpos); @@ -409,7 +298,6 @@ string formatted(string const & sin, int w, int size, int style) curpos = nxtpos+1; } -#endif return sout; } @@ -448,9 +336,13 @@ const int xformCount = sizeof(xformTags) / sizeof(keyword_item); bool XformsColor::read(string const & filename) { + FileInfo const f(filename); LyXLex lexrc(xformTags, xformCount); - if (!lexrc.setFile(filename)) + if (f.readable() && !lexrc.setFile(filename)) { + lyxerr << "XformsColor::read(" << filename << ")\n" + << _("Failed to open file.") << std::endl; return false; + } while (lexrc.isOK()) { int const le = lexrc.lex(); @@ -491,21 +383,17 @@ bool XformsColor::read(string const & filename) bool XformsColor::write(string const & filename) { ofstream os(filename.c_str()); - if (!os) + if (!os) { + lyxerr << "XformsColor::write(" << filename << ")\n" + << _("Failed to open file.") << std::endl; return false; + } - os << "### This file is part of\n" - << "### ========================================================\n" - << "### LyX, The Document Processor\n" - << "###\n" - << "### Copyright 1995 Matthias Ettrich\n" - << "### Copyright 1995-2002 The LyX Team.\n" - << "###\n" - << "### ========================================================\n" - << "\n" - << "# This file is written by LyX, if you want to make your own\n" - << "# modifications you should do them from inside LyX and save\n" - << "\n"; + os << "###" + << "### file " << filename << "\n\n" + << "### This file is written by LyX, if you want to make your own\n" + << "### modifications you should do them from inside LyX and save\n" + << '\n'; for (int i = 0; i < xformCount; ++i) { string const tag = xformTags[i].tag; @@ -514,8 +402,8 @@ bool XformsColor::write(string const & filename) fl_getmcolor(colorID, &color.r, &color.g, &color.b); - os << tag << " " - << color.r << " " << color.g << " " << color.b << "\n"; + os << tag << ' ' + << color.r << ' ' << color.g << ' ' << color.b << '\n'; } return true; @@ -529,18 +417,18 @@ bool RWInfo::WriteableDir(string const & name) error_message.erase(); if (!AbsolutePath(name)) { - error_message = N_("The absolute path is required."); + error_message = _("The absolute path is required."); return false; } FileInfo const tp(name); if (!tp.isOK() || !tp.isDir()) { - error_message = N_("Directory does not exist."); + error_message = _("Directory does not exist."); return false; } if (!tp.writable()) { - error_message = N_("Cannot write to this directory."); + error_message = _("Cannot write to this directory."); return false; } @@ -553,18 +441,18 @@ bool RWInfo::ReadableDir(string const & name) error_message.erase(); if (!AbsolutePath(name)) { - error_message = N_("The absolute path is required."); + error_message = _("The absolute path is required."); return false; } FileInfo const tp(name); if (!tp.isOK() || !tp.isDir()) { - error_message = N_("Directory does not exist."); + error_message = _("Directory does not exist."); return false; } if (!tp.readable()) { - error_message = N_("Cannot read this directory."); + error_message = _("Cannot read this directory."); return false; } @@ -582,13 +470,13 @@ bool RWInfo::WriteableFile(string const & name) error_message.erase(); if (name.empty()) { - error_message = N_("No file input."); + error_message = _("No file input."); return false; } string const dir = OnlyPath(name); if (!AbsolutePath(dir)) { - error_message = N_("The absolute path is required."); + error_message = _("The absolute path is required."); return false; } @@ -599,23 +487,23 @@ bool RWInfo::WriteableFile(string const & name) } if (!d.isOK() || !d.isDir()) { - error_message = N_("Directory does not exist."); + error_message = _("Directory does not exist."); return false; } if (!d.writable()) { - error_message = N_("Cannot write to this directory."); + error_message = _("Cannot write to this directory."); return false; } FileInfo f(name); if (dir == name || (f.isOK() && f.isDir())) { - error_message = N_("A file is required, not a directory."); + error_message = _("A file is required, not a directory."); return false; } if (f.isOK() && f.exist() && !f.writable()) { - error_message = N_("Cannot write to this file."); + error_message = _("Cannot write to this file."); return false; } @@ -628,13 +516,13 @@ bool RWInfo::ReadableFile(string const & name) error_message.erase(); if (name.empty()) { - error_message = N_("No file input."); + error_message = _("No file input."); return false; } string const dir = OnlyPath(name); if (!AbsolutePath(dir)) { - error_message = N_("The absolute path is required."); + error_message = _("The absolute path is required."); return false; } @@ -645,30 +533,33 @@ bool RWInfo::ReadableFile(string const & name) } if (!d.isOK() || !d.isDir()) { - error_message = N_("Directory does not exist."); + error_message = _("Directory does not exist."); return false; } if (!d.readable()) { - error_message = N_("Cannot read from this directory."); + error_message = _("Cannot read from this directory."); return false; } FileInfo f(name); if (dir == name || (f.isOK() && f.isDir())) { - error_message = N_("A file is required, not a directory."); + error_message = _("A file is required, not a directory."); return false; } if (!f.exist()) { - error_message = N_("File does not exist."); + error_message = _("File does not exist."); return false; } if (!f.readable()) { - error_message = N_("Cannot read from this file."); + error_message = _("Cannot read from this file."); return false; } return true; } + +} // namespace frontend +} // namespace lyx