X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ffrontends%2Fxforms%2Fxforms_helpers.C;h=67055a5c1a5425e78446ff0ce11ee70d4a986a95;hb=e8c9544a2d74248d6b64d4833f01874893aca2ee;hp=f8601b75179bfb0089d6099935dc20bf4cc0a1e7;hpb=8a4455d459e52510b5c86dd872bcd8c65cc41903;p=lyx.git diff --git a/src/frontends/xforms/xforms_helpers.C b/src/frontends/xforms/xforms_helpers.C index f8601b7517..67055a5c1a 100644 --- a/src/frontends/xforms/xforms_helpers.C +++ b/src/frontends/xforms/xforms_helpers.C @@ -1,134 +1,279 @@ -/** 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 "frontends/FileDialog.h" +#include "gettext.h" +#include "lyxlength.h" +#include "lyxgluelength.h" + +#include "support/LAssert.h" #include "support/FileInfo.h" #include "support/filetools.h" -#include "lyx_gui_misc.h" // WriteAlert -#include "gettext.h" +#include "support/lstrings.h" // frontStrip, strip + +#include + +#include FORMS_H_LOCATION using std::ofstream; using std::pair; using std::vector; +using std::make_pair; + +bool isActive(FL_OBJECT * ob) +{ + 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); +} + + +// 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; +} + // Set an FL_OBJECT to activated or deactivated 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); } } - -// 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) + +// Given an fl_choice or an fl_browser, create a vector of its entries +vector const getVector(FL_OBJECT * ob) { - string sout; - if (sin.empty()) return sout; + vector vec; - // break sin 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') { - sentence.push_back(word); - word.erase(); - if ((*sit) == '\n') word += '\n'; - - } else { - word += (*sit); + 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); } - // Flush remaining contents of word - if (!word.empty() ) sentence.push_back(word); + return vec; +} - string line, 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 = word.substr(1); - line_plus_word.erase(); - line.erase(); - } +/// +string const getString(FL_OBJECT * ob, int line) +{ + // Negative line value does not make sense. + lyx::Assert(line >= 0); - if (!line_plus_word.empty() ) line_plus_word += ' '; - line_plus_word += word; + char const * tmp = 0; + switch (ob->objclass) { + case FL_INPUT: + tmp = fl_get_input(ob); + break; - int 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; - } + 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; - line = line_plus_word; + 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); } - // Flush remaining contents of line - if (!line.empty()) { - sout += line; + + 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 = trim(fl_get_input(input)); + if (length.empty()) + return string(); + + // 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); } +} - if (sout[sout.length()-1] == '\n') - sout.erase(sout.length()-1); - return sout; +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 (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()); + + // 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()); + } + } } -string const browseFile(LyXView * lv, string const & filename, - string const & title, - string const & pattern, - pair const & dir1, - pair const & dir2) +// 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 lastPath = "."; - if (!filename.empty()) lastPath = OnlyPath(filename); + string sout; + if (sin.empty()) return sout; + + 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); - FileDialog fileDlg(lv, title, LFUN_SELECT_FILE_SYNC, dir1, dir2); + string const word = nxtpos == string::npos ? + sin.substr(curpos) : sin.substr(curpos, nxtpos-curpos); - FileDialog::Result result; - - while (1) { - result = fileDlg.Select(lastPath, pattern, OnlyFilename(filename)); + bool const newline = (nxtpos2 != string::npos && + nxtpos2 < nxtpos1); - if (result.second.empty()) - return result.second; + string const line_plus_word = + line.empty() ? word : line + ' ' + word; - lastPath = OnlyPath(result.second); + int const length = + fl_get_string_width(style, size, + line_plus_word.c_str(), + int(line_plus_word.length())); - if (result.second.find_first_of("#~$% ") == string::npos) - break; - - WriteAlert(_("Filename can't contain any " - "of these characters:"), - _("space, '#', '~', '$' or '%'.")); + if (length >= w) { + sout += line + '\n'; + 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; + } + + if (nxtpos == string::npos) { + if (!line.empty()) + sout += line; + break; + } + + curpos = nxtpos+1; } - return result.second; + 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); } @@ -136,15 +281,16 @@ 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 } }; @@ -159,32 +305,38 @@ bool XformsColor::read(string const & filename) if (!lexrc.setFile(filename)) return false; - while (lexrc.IsOK()) { + while (lexrc.isOK()) { int const le = lexrc.lex(); 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; - col.r = lexrc.GetInteger(); + col.r = lexrc.getInteger(); if (!lexrc.next()) break; - col.g = lexrc.GetInteger(); + col.g = lexrc.getInteger(); if (!lexrc.next()) break; - col.b = lexrc.GetInteger(); + col.b = lexrc.getInteger(); fl_mapcolor(le, col.r, col.g, col.b); + + if (tag == "\\gui_pointer") { + setCursorColor(FL_FREE_COL16); + } } - + return true; } @@ -195,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-2000 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; @@ -215,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; @@ -230,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; } @@ -254,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; } @@ -283,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; } @@ -328,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; }