2 * \file xforms_helpers.C
3 * Copyright 2000-2002 The LyX Team.
4 * See the file COPYING.
6 * \author Angus Leeming, a.leeming@ic.ac.uk
12 #pragma implementation
15 #include "xforms_helpers.h"
19 #include "lyxlength.h"
20 #include "lyxgluelength.h"
22 #include "support/LAssert.h"
23 #include "support/FileInfo.h"
24 #include "support/filetools.h"
25 #include "support/lstrings.h" // frontStrip, strip
30 #include FORMS_H_LOCATION
36 // Set an FL_OBJECT to activated or deactivated
37 void setEnabled(FL_OBJECT * ob, bool enable)
40 fl_activate_object(ob);
41 fl_set_object_lcol(ob, FL_BLACK);
43 fl_deactivate_object(ob);
44 fl_set_object_lcol(ob, FL_INACTIVE);
49 // Given an fl_choice, create a vector of its entries
50 vector<string> const getVectorFromChoice(FL_OBJECT * ob)
53 if (!ob || ob->objclass != FL_CHOICE)
56 for(int i = 0; i < fl_get_choice_maxitems(ob); ++i) {
57 string const text = fl_get_choice_item_text(ob, i+1);
58 vec.push_back(strip(frontStrip(text)));
65 /// Given an fl_input, return its contents.
66 string const getStringFromInput(FL_OBJECT * ob)
68 if (!ob || ob->objclass != FL_INPUT)
71 char const * tmp = fl_get_input(ob);
72 return (tmp) ? tmp : string();
76 // Given an fl_browser, return the contents of line
77 string const getStringFromBrowser(FL_OBJECT * ob, int line)
79 if (!ob || ob->objclass != FL_BROWSER ||
80 line < 1 || line > fl_get_browser_maxline(ob))
83 char const * tmp = fl_get_browser_line(ob, line);
84 return (tmp) ? tmp : string();
87 // Given an fl_browser, return the contents of the currently
89 // If nothing is selected, return an empty string
90 string const getSelectedStringFromBrowser(FL_OBJECT * ob)
92 if (!ob || ob->objclass != FL_BROWSER)
95 int const line = fl_get_browser(ob);
96 if (line < 1 || line > fl_get_browser_maxline(ob))
99 if (!fl_isselected_browser_line(ob, line))
102 char const * tmp = fl_get_browser_line(ob, line);
103 return (tmp) ? tmp : string();
107 // Given an fl_browser, create a vector of its entries
108 vector<string> const getVectorFromBrowser(FL_OBJECT * ob)
111 if (!ob || ob->objclass != FL_BROWSER)
114 for(int i = 0; i < fl_get_browser_maxline(ob); ++i) {
115 string const text = fl_get_browser_line(ob, i+1);
116 vec.push_back(strip(frontStrip(text)));
123 string getLengthFromWidgets(FL_OBJECT * input, FL_OBJECT * choice)
126 lyx::Assert(input && input->objclass == FL_INPUT &&
127 choice && choice->objclass == FL_CHOICE);
129 string const length = strip(frontStrip(fl_get_input(input)));
133 //don't return unit-from-choice if the input(field) contains a unit
134 if (isValidGlueLength(length))
137 string unit = strip(frontStrip(fl_get_choice_text(choice)));
138 unit = subst(unit, "%%", "%");
140 return length + unit;
144 void updateWidgetsFromLengthString(FL_OBJECT * input, FL_OBJECT * choice,
146 string const & default_unit)
148 // use input field only for gluelengths
149 if (!isValidLength(str) && !isStrDbl(str)) {
150 fl_set_input(input, str.c_str());
151 // we assume that "default_unit" is in the choice as "we"
152 // have control over that!
153 // No need to check for it's precence in the choice, therefore.
154 fl_set_choice_text(choice, default_unit.c_str());
156 updateWidgetsFromLength(input, choice,
157 LyXLength(str), default_unit);
162 void updateWidgetsFromLength(FL_OBJECT * input, FL_OBJECT * choice,
163 LyXLength const & len,
164 string const & default_unit)
167 lyx::Assert(input && input->objclass == FL_INPUT &&
168 choice && choice->objclass == FL_CHOICE);
171 fl_set_input(input, "");
172 fl_set_choice_text(choice, default_unit.c_str());
174 ostringstream buffer;
175 buffer << len.value();
176 fl_set_input(input, buffer.str().c_str());
178 // Set the choice to the desired unit, if present in the choice.
179 // Else set the choice to the default unit.
180 string const unit = subst(stringFromUnit(len.unit()),"%","%%");
182 vector<string> const vec = getVectorFromChoice(choice);
183 vector<string>::const_iterator it =
184 std::find(vec.begin(), vec.end(), unit);
185 if (it != vec.end()) {
186 fl_set_choice_text(choice, unit.c_str());
188 fl_set_choice_text(choice, default_unit.c_str());
194 // Take a string and add breaks so that it fits into a desired label width, w
195 string formatted(string const & sin, int w, int size, int style)
198 if (sin.empty()) return sout;
200 string::size_type curpos = 0;
203 string::size_type const nxtpos1 = sin.find(' ', curpos);
204 string::size_type const nxtpos2 = sin.find('\n', curpos);
205 string::size_type const nxtpos = std::min(nxtpos1, nxtpos1);
207 string const word = nxtpos == string::npos ?
208 sin.substr(curpos) : sin.substr(curpos, nxtpos-curpos);
210 bool const newline = (nxtpos2 != string::npos &&
213 string const line_plus_word =
214 line.empty() ? word : line + ' ' + word;
217 fl_get_string_width(style, size,
218 line_plus_word.c_str(),
219 int(line_plus_word.length()));
230 } else if (newline) {
231 sout += line_plus_word + '\n';
240 if (nxtpos == string::npos) {
253 void setCursorColor(int color)
255 fl_set_cursor_color(FL_DEFAULT_CURSOR, color, FL_WHITE);
256 fl_set_cursor_color(XC_xterm, color, FL_WHITE);
257 fl_set_cursor_color(XC_watch, color, FL_WHITE);
258 fl_set_cursor_color(XC_sb_right_arrow, color, FL_WHITE);
264 // sorted by hand to prevent LyXLex from complaining on read().
265 keyword_item xformTags[] = {
266 { "\\gui_background", FL_COL1 },
267 { "\\gui_buttonbottom", FL_BOTTOM_BCOL },
268 { "\\gui_buttonleft", FL_LEFT_BCOL },
269 { "\\gui_buttonright", FL_RIGHT_BCOL },
270 { "\\gui_buttontop", FL_TOP_BCOL },
271 { "\\gui_inactive", FL_INACTIVE },
272 { "\\gui_pointer", FL_FREE_COL16 },
273 { "\\gui_push_button", FL_YELLOW },
274 { "\\gui_selected", FL_MCOL },
275 { "\\gui_text", FL_BLACK }
279 const int xformCount = sizeof(xformTags) / sizeof(keyword_item);
284 bool XformsColor::read(string const & filename)
286 LyXLex lexrc(xformTags, xformCount);
287 if (!lexrc.setFile(filename))
290 while (lexrc.isOK()) {
291 int const le = lexrc.lex();
294 case LyXLex::LEX_UNDEF:
295 lexrc.printError("Unknown tag `$$Token'");
297 case LyXLex::LEX_FEOF:
302 string const tag = lexrc.getString();
306 if (!lexrc.next()) break;
307 col.r = lexrc.getInteger();
309 if (!lexrc.next()) break;
310 col.g = lexrc.getInteger();
312 if (!lexrc.next()) break;
313 col.b = lexrc.getInteger();
315 fl_mapcolor(le, col.r, col.g, col.b);
317 if (tag == "\\gui_pointer") {
318 setCursorColor(FL_FREE_COL16);
326 bool XformsColor::write(string const & filename)
328 ofstream os(filename.c_str());
332 os << "### This file is part of\n"
333 << "### ========================================================\n"
334 << "### LyX, The Document Processor\n"
336 << "### Copyright 1995 Matthias Ettrich\n"
337 << "### Copyright 1995-2002 The LyX Team.\n"
339 << "### ========================================================\n"
341 << "# This file is written by LyX, if you want to make your own\n"
342 << "# modifications you should do them from inside LyX and save\n"
345 for (int i = 0; i < xformCount; ++i) {
346 string const tag = xformTags[i].tag;
347 int const colorID = xformTags[i].code;
350 fl_getmcolor(colorID, &color.r, &color.g, &color.b);
353 << color.r << " " << color.g << " " << color.b << "\n";
360 string RWInfo::error_message;
362 bool RWInfo::WriteableDir(string const & name)
364 error_message.erase();
366 if (!AbsolutePath(name)) {
367 error_message = _("The absolute path is required.");
371 FileInfo const tp(name);
372 if (!tp.isOK() || !tp.isDir()) {
373 error_message = _("Directory does not exist.");
377 if (!tp.writable()) {
378 error_message = _("Cannot write to this directory.");
386 bool RWInfo::ReadableDir(string const & name)
388 error_message.erase();
390 if (!AbsolutePath(name)) {
391 error_message = _("The absolute path is required.");
395 FileInfo const tp(name);
396 if (!tp.isOK() || !tp.isDir()) {
397 error_message = _("Directory does not exist.");
401 if (!tp.readable()) {
402 error_message = _("Cannot read this directory.");
410 bool RWInfo::WriteableFile(string const & name)
412 // A writeable file is either:
413 // * An existing file to which we have write access, or
414 // * A file that doesn't yet exist but that would exist in a writeable
417 error_message.erase();
420 error_message = _("No file input.");
424 string const dir = OnlyPath(name);
425 if (!AbsolutePath(dir)) {
426 error_message = _("The absolute path is required.");
432 if (!d.isOK() || !d.isDir()) {
436 if (!d.isOK() || !d.isDir()) {
437 error_message = _("Directory does not exist.");
442 error_message = _("Cannot write to this directory.");
447 if (dir == name || (f.isOK() && f.isDir())) {
448 error_message = _("A file is required, not a directory.");
452 if (f.isOK() && f.exist() && !f.writable()) {
453 error_message = _("Cannot write to this file.");
461 bool RWInfo::ReadableFile(string const & name)
463 error_message.erase();
466 error_message = _("No file input.");
470 string const dir = OnlyPath(name);
471 if (!AbsolutePath(dir)) {
472 error_message = _("The absolute path is required.");
478 if (!d.isOK() && !d.isDir()) {
482 if (!d.isOK() || !d.isDir()) {
483 error_message = _("Directory does not exist.");
488 error_message = _("Cannot read from this directory.");
493 if (dir == name || (f.isOK() && f.isDir())) {
494 error_message = _("A file is required, not a directory.");
499 error_message = _("File does not exist.");
504 error_message = _("Cannot read from this file.");