1 /** Collection of some useful xform helper functions
6 #include FORMS_H_LOCATION
8 #include <fstream> // ofstream
12 #pragma implementation
15 #include "xforms_helpers.h"
17 #include "support/FileInfo.h"
18 #include "support/filetools.h"
19 #include "support/lstrings.h" // frontStrip, strip
21 #include "support/LAssert.h"
27 // Set an FL_OBJECT to activated or deactivated
28 void setEnabled(FL_OBJECT * ob, bool enable)
31 fl_activate_object(ob);
32 fl_set_object_lcol(ob, FL_BLACK);
34 fl_deactivate_object(ob);
35 fl_set_object_lcol(ob, FL_INACTIVE);
40 // Given an fl_choice, create a vector of its entries
41 vector<string> const getVectorFromChoice(FL_OBJECT * ob)
44 if (!ob || ob->objclass != FL_CHOICE)
47 for(int i = 0; i < fl_get_choice_maxitems(ob); ++i) {
48 string const text = fl_get_choice_item_text(ob, i+1);
49 vec.push_back(strip(frontStrip(text)));
56 // Given an fl_browser, create a vector of its entries
57 vector<string> const getVectorFromBrowser(FL_OBJECT * ob)
60 if (!ob || ob->objclass != FL_BROWSER)
63 for(int i = 0; i < fl_get_browser_maxline(ob); ++i) {
64 string const text = fl_get_browser_line(ob, i+1);
65 vec.push_back(strip(frontStrip(text)));
72 string getLengthFromWidgets(FL_OBJECT * input, FL_OBJECT * choice)
75 lyx::Assert(input && input->objclass == FL_INPUT &&
76 choice && choice->objclass == FL_CHOICE);
78 string const length = strip(frontStrip(fl_get_input(input)));
82 string unit = strip(frontStrip(fl_get_choice_text(choice)));
83 unit = subst(unit, "%%", "%");
89 void updateWidgetsFromLengthString(FL_OBJECT * input, FL_OBJECT * choice,
91 string const & default_unit)
94 lyx::Assert(input && input->objclass == FL_INPUT &&
95 choice && choice->objclass == FL_CHOICE);
98 fl_set_input(input, "");
99 int unitpos = 1; // xforms has Fortran-style indexing
100 for(int i = 0; i < fl_get_choice_maxitems(choice); ++i) {
101 string const text = fl_get_choice_item_text(choice,i+1);
103 lowercase(strip(frontStrip(text)))) {
108 fl_set_choice(choice, unitpos);
112 // The unit is presumed to begin at the first char a-z
113 string const tmp = lowercase(strip(frontStrip(str)));
115 string::const_iterator p = tmp.begin();
116 for (; p != tmp.end(); ++p) {
117 if (*p >= 'a' && *p <= 'z')
122 int unitpos = 1; // xforms has Fortran-style indexing
124 if (p == tmp.end()) {
129 string tmplen = string(tmp.begin(), p);
130 if (isStrDbl(tmplen))
132 string unit = string(p, tmp.end());
133 unit = subst(unit, "%", "%%");
135 for(int i = 0; i < fl_get_choice_maxitems(choice); ++i) {
136 string const text = fl_get_choice_item_text(choice,i+1);
137 if (unit == lowercase(strip(frontStrip(text)))) {
144 fl_set_input(input, len.c_str());
145 fl_set_choice(choice, unitpos);
148 // Take a string and add breaks so that it fits into a desired label width, w
149 string formatted(string const & sin, int w, int size, int style)
151 // FIX: Q: Why cant this be done by a one pass algo? (Lgb)
154 if (sin.empty()) return sout;
156 // breaks in up into a vector of individual words
157 vector<string> sentence;
159 for (string::const_iterator sit = sin.begin();
160 sit != sin.end(); ++sit) {
161 if ((*sit) == ' ' || (*sit) == '\n') {
163 sentence.push_back(word);
166 if ((*sit) == '\n') word += '\n';
173 // Flush remaining contents of word
174 if (!word.empty() ) sentence.push_back(word);
177 string line_plus_word;
178 for (vector<string>::const_iterator vit = sentence.begin();
179 vit != sentence.end(); ++vit) {
186 line_plus_word.erase();
190 if (!line_plus_word.empty() ) line_plus_word += ' ';
191 line_plus_word += word;
193 int const length = fl_get_string_width(style, size,
194 line_plus_word.c_str(),
195 int(line_plus_word.length()));
198 line_plus_word = word;
201 line = line_plus_word;
203 // Flush remaining contents of line
208 if (sout[sout.length() - 1] == '\n')
209 sout.erase(sout.length() - 1);
217 // sorted by hand to prevent LyXLex from complaining on read().
218 keyword_item xformTags[] = {
219 { "\\gui_background", FL_COL1 },
220 { "\\gui_buttonbottom", FL_BOTTOM_BCOL },
221 { "\\gui_buttonleft", FL_LEFT_BCOL },
222 { "\\gui_buttonright", FL_RIGHT_BCOL },
223 { "\\gui_buttontop", FL_TOP_BCOL },
224 { "\\gui_inactive", FL_INACTIVE },
225 { "\\gui_push_button", FL_YELLOW },
226 { "\\gui_selected", FL_MCOL },
227 { "\\gui_text", FL_BLACK }
231 const int xformCount = sizeof(xformTags) / sizeof(keyword_item);
236 bool XformsColor::read(string const & filename)
238 LyXLex lexrc(xformTags, xformCount);
239 if (!lexrc.setFile(filename))
242 while (lexrc.isOK()) {
243 int const le = lexrc.lex();
246 case LyXLex::LEX_UNDEF:
247 lexrc.printError("Unknown tag `$$Token'");
249 case LyXLex::LEX_FEOF:
256 if (!lexrc.next()) break;
257 col.r = lexrc.getInteger();
259 if (!lexrc.next()) break;
260 col.g = lexrc.getInteger();
262 if (!lexrc.next()) break;
263 col.b = lexrc.getInteger();
265 fl_mapcolor(le, col.r, col.g, col.b);
272 bool XformsColor::write(string const & filename)
274 ofstream os(filename.c_str());
278 os << "### This file is part of\n"
279 << "### ========================================================\n"
280 << "### LyX, The Document Processor\n"
282 << "### Copyright 1995 Matthias Ettrich\n"
283 << "### Copyright 1995-2001 The LyX Team.\n"
285 << "### ========================================================\n"
287 << "# This file is written by LyX, if you want to make your own\n"
288 << "# modifications you should do them from inside LyX and save\n"
291 for (int i = 0; i < xformCount; ++i) {
292 string const tag = xformTags[i].tag;
293 int const colorID = xformTags[i].code;
296 fl_getmcolor(colorID, &color.r, &color.g, &color.b);
299 << color.r << " " << color.g << " " << color.b << "\n";
306 string RWInfo::error_message;
308 bool RWInfo::WriteableDir(string const & name)
310 error_message.erase();
312 if (!AbsolutePath(name)) {
313 error_message = N_("The absolute path is required.");
317 FileInfo const tp(name);
319 error_message = N_("Directory does not exist.");
323 if (!tp.writable()) {
324 error_message = N_("Cannot write to this directory.");
332 bool RWInfo::ReadableDir(string const & name)
334 error_message.erase();
336 if (!AbsolutePath(name)) {
337 error_message = N_("The absolute path is required.");
341 FileInfo const tp(name);
343 error_message = N_("Directory does not exist.");
347 if (!tp.readable()) {
348 error_message = N_("Cannot read this directory.");
356 bool RWInfo::WriteableFile(string const & name)
358 // A writeable file is either:
359 // * An existing file to which we have write access, or
360 // * A file that doesn't yet exist but that would exist in a writeable
363 error_message.erase();
366 error_message = N_("No file input.");
370 string const dir = OnlyPath(name);
371 if (!AbsolutePath(dir)) {
372 error_message = N_("The absolute path is required.");
382 error_message = N_("Directory does not exist.");
387 error_message = N_("Cannot write to this directory.");
392 if (dir == name || f.isDir()) {
393 error_message = N_("A file is required, not a directory.");
397 if (f.exist() && !f.writable()) {
398 error_message = N_("Cannot write to this file.");
406 bool RWInfo::ReadableFile(string const & name)
408 error_message.erase();
411 error_message = N_("No file input.");
415 string const dir = OnlyPath(name);
416 if (!AbsolutePath(dir)) {
417 error_message = N_("The absolute path is required.");
427 error_message = N_("Directory does not exist.");
432 error_message = N_("Cannot read from this directory.");
437 if (dir == name || f.isDir()) {
438 error_message = N_("A file is required, not a directory.");
443 error_message = N_("File does not exist.");
448 error_message = N_("Cannot read from this file.");