X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ffrontends%2Fxforms%2Fxforms_helpers.C;h=67055a5c1a5425e78446ff0ce11ee70d4a986a95;hb=e8c9544a2d74248d6b64d4833f01874893aca2ee;hp=9e1373e08ca72fdf0cd68da3258d7158fa1a22d1;hpb=33a28bdc9cdf978601d5d40b693f13924801ad9e;p=lyx.git diff --git a/src/frontends/xforms/xforms_helpers.C b/src/frontends/xforms/xforms_helpers.C index 9e1373e08c..67055a5c1a 100644 --- a/src/frontends/xforms/xforms_helpers.C +++ b/src/frontends/xforms/xforms_helpers.C @@ -1,62 +1,66 @@ -/** Collection of some useful xform helper functions +/** + * \file xforms_helpers.C + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \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 "gettext.h" +#include "lyxlength.h" +#include "lyxgluelength.h" + +#include "support/LAssert.h" #include "support/FileInfo.h" #include "support/filetools.h" #include "support/lstrings.h" // frontStrip, strip -#include "gettext.h" -#include "support/LAssert.h" + +#include + +#include FORMS_H_LOCATION using std::ofstream; using std::pair; using std::vector; +using std::make_pair; -// Extract shortcut from | string -char const * flyx_shortcut_extract(char const * sc) +bool isActive(FL_OBJECT * ob) { - // Find '|' in the sc and return the string after that. - register char const * sd = sc; - while (sd[0]!= 0 && sd[0] != '|') ++sd; - - if (sd[0] == '|') { - ++sd; - //lyxerr << sd << endl; - return sd; - } - return ""; + return ob && ob->active > 0; +} + +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); } -// Extract identifier from | string -char const * flyx_ident_extract(char const * sc) +// 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) { - register char const * se = sc; - while (se[0]!= 0 && se[0] != '|') ++se; - - 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; + int r2, g2, b2; + unsigned long ret_val = ::fl_getmcolor(i, &r2, &g2, &b2); + *r = r2; + *g = g2; + *b = b2; + return ret_val; } @@ -65,202 +69,228 @@ 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); } } - -// 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: + lyx::Assert(0); } return vec; } -// Given an fl_browser, create a vector of its entries -vector const getVectorFromBrowser(FL_OBJECT * ob) +/// +string const getString(FL_OBJECT * ob, int line) { - vector vec; - if (!ob || ob->objclass != FL_BROWSER) - return vec; + // Negative line value does not make sense. + lyx::Assert(line >= 0); + + char const * tmp = 0; + switch (ob->objclass) { + case FL_INPUT: + tmp = fl_get_input(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))); + case FL_BROWSER: + if (line == 0) + line = fl_get_browser(ob); + + if (line >= 1 && line <= fl_get_browser_maxline(ob)) + tmp = fl_get_browser_line(ob, line); + break; + + 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; + + default: + lyx::Assert(0); } - return vec; + return tmp ? trim(tmp) : string(); } - string getLengthFromWidgets(FL_OBJECT * input, FL_OBJECT * choice) { // Paranoia check lyx::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(); - string unit = strip(frontStrip(fl_get_choice_text(choice))); + // don't return unit-from-choice if the input(field) contains a unit + if (isValidGlueLength(length)) + return length; + + string unit = trim(fl_get_choice_text(choice)); unit = subst(unit, "%%", "%"); return length + unit; } - + 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); + } +} + + +void updateWidgetsFromLength(FL_OBJECT * input, FL_OBJECT * choice, + LyXLength const & len, + string const & default_unit) { // Paranoia check lyx::Assert(input && input->objclass == FL_INPUT && choice && choice->objclass == FL_CHOICE); - if (str.empty()) { + if (len.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 - string const tmp = lowercase(strip(frontStrip(str))); - - string::const_iterator p = tmp.begin(); - for (; p != tmp.end(); ++p) { - if (*p >= 'a' && *p <= 'z') - break; - } - - string len = "0"; - int unitpos = 1; // xforms has Fortran-style indexing - - if (p == tmp.end()) { - if (isStrDbl(tmp)) - len = tmp; - + fl_set_choice_text(choice, default_unit.c_str()); } 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; - } + ostringstream buffer; + buffer << len.value(); + fl_set_input(input, buffer.str().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()); } } - - fl_set_input(input, len.c_str()); - fl_set_choice(choice, unitpos); } - + + // 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) { - // FIX: Q: Why cant this be done by a one pass algo? (Lgb) - string sout; if (sin.empty()) return sout; - // 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); - } - } + 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, nxtpos2); - // Flush remaining contents of word - if (!word.empty() ) sentence.push_back(word); + string const word = nxtpos == string::npos ? + sin.substr(curpos) : sin.substr(curpos, nxtpos-curpos); - string line; - string line_plus_word; - for (vector::const_iterator vit = sentence.begin(); - vit != sentence.end(); ++vit) { - string word(*vit); + bool const newline = (nxtpos2 != string::npos && + nxtpos2 < nxtpos1); - char c = word[0]; - if (c == '\n') { - sout += line + '\n'; - word.erase(0,1); - line_plus_word.erase(); - line.erase(); - } + string const line_plus_word = + line.empty() ? word : line + ' ' + word; - if (!line_plus_word.empty() ) line_plus_word += ' '; - line_plus_word += word; + int const length = + fl_get_string_width(style, size, + line_plus_word.c_str(), + int(line_plus_word.length())); - 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; + if (newline) { + sout += word + '\n'; + line.erase(); + } else { + line = word; + } + + } else if (newline) { + sout += line_plus_word + '\n'; + line.erase(); + + } else { + if (!line.empty()) + line += ' '; + line += word; } - line = line_plus_word; - } - // Flush remaining contents of line - if (!line.empty()) { - sout += line; - } + if (nxtpos == string::npos) { + if (!line.empty()) + sout += line; + break; + } - if (sout[sout.length() - 1] == '\n') - sout.erase(sout.length() - 1); + curpos = nxtpos+1; + } return sout; } +void setCursorColor(int color) +{ + fl_set_cursor_color(FL_DEFAULT_CURSOR, color, FL_WHITE); + fl_set_cursor_color(XC_xterm, color, FL_WHITE); + fl_set_cursor_color(XC_watch, color, FL_WHITE); + fl_set_cursor_color(XC_sb_right_arrow, color, FL_WHITE); +} + + namespace { // sorted by hand to prevent LyXLex from complaining on read(). keyword_item xformTags[] = { - { "\\gui_background", FL_COL1 }, + { "\\gui_background", FL_COL1 }, { "\\gui_buttonbottom", FL_BOTTOM_BCOL }, - { "\\gui_buttonleft", FL_LEFT_BCOL }, - { "\\gui_buttonright", FL_RIGHT_BCOL }, - { "\\gui_buttontop", FL_TOP_BCOL }, - { "\\gui_inactive", FL_INACTIVE }, - { "\\gui_push_button", FL_YELLOW }, - { "\\gui_selected", FL_MCOL }, - { "\\gui_text", FL_BLACK } + { "\\gui_buttonleft", FL_LEFT_BCOL }, + { "\\gui_buttonright", FL_RIGHT_BCOL }, + { "\\gui_buttontop", FL_TOP_BCOL }, + { "\\gui_inactive", FL_INACTIVE }, + { "\\gui_pointer", FL_FREE_COL16 }, + { "\\gui_push_button", FL_YELLOW }, + { "\\gui_selected", FL_MCOL }, + { "\\gui_text", FL_BLACK } }; @@ -281,12 +311,14 @@ bool XformsColor::read(string const & filename) switch (le) { case LyXLex::LEX_UNDEF: lexrc.printError("Unknown tag `$$Token'"); - continue; + continue; case LyXLex::LEX_FEOF: continue; default: break; } + string const tag = lexrc.getString(); + RGBColor col; if (!lexrc.next()) break; @@ -299,8 +331,12 @@ bool XformsColor::read(string const & filename) col.b = lexrc.getInteger(); fl_mapcolor(le, col.r, col.g, col.b); + + if (tag == "\\gui_pointer") { + setCursorColor(FL_FREE_COL16); + } } - + return true; } @@ -311,18 +347,11 @@ bool XformsColor::write(string const & filename) if (!os) return false; - os << "### This file is part of\n" - << "### ========================================================\n" - << "### LyX, The Document Processor\n" - << "###\n" - << "### Copyright 1995 Matthias Ettrich\n" - << "### Copyright 1995-2001 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; @@ -331,8 +360,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; @@ -346,18 +375,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.isDir()) { - error_message = N_("Directory does not exist."); + if (!tp.isOK() || !tp.isDir()) { + 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; } @@ -370,18 +399,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.isDir()) { - error_message = N_("Directory does not exist."); + if (!tp.isOK() || !tp.isDir()) { + 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; } @@ -399,42 +428,43 @@ 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; } FileInfo d(name); - if (!d.isDir()) { + + if (!d.isOK() || !d.isDir()) { d.newFile(dir); } - if (!d.isDir()) { - error_message = N_("Directory does not exist."); + if (!d.isOK() || !d.isDir()) { + 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.isDir()) { - error_message = N_("A file is required, not a directory."); + if (dir == name || (f.isOK() && f.isDir())) { + error_message = _("A file is required, not a directory."); return false; } - if (f.exist() && !f.writable()) { - error_message = N_("Cannot write to this file."); + if (f.isOK() && f.exist() && !f.writable()) { + error_message = _("Cannot write to this file."); return false; } - + return true; } @@ -444,44 +474,45 @@ 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; } FileInfo d(name); - if (!d.isDir()) { + + if (!d.isOK() && !d.isDir()) { d.newFile(dir); } - if (!d.isDir()) { - error_message = N_("Directory does not exist."); + if (!d.isOK() || !d.isDir()) { + 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.isDir()) { - error_message = N_("A file is required, not a directory."); + if (dir == name || (f.isOK() && f.isDir())) { + 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; }