]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/xforms_helpers.C
77b9b3ee7b27bd6133c29397b4df2b42080902e7
[lyx.git] / src / frontends / xforms / xforms_helpers.C
1 /** Collection of some useful xform helper functions
2  */
3
4 #include <config.h>
5
6 #include FORMS_H_LOCATION
7
8 #include <fstream> // ofstream
9 #include <vector>
10
11 #ifdef __GNUG_
12 #pragma implementation
13 #endif
14  
15 #include "xforms_helpers.h"
16 #include "lyxlex.h"
17 #include "frontends/FileDialog.h"
18 #include "support/FileInfo.h"
19 #include "support/filetools.h"
20 #include "lyx_gui_misc.h" // WriteAlert
21 #include "gettext.h"
22
23 using std::ofstream;
24 using std::pair;
25 using std::vector;
26
27 // Set an FL_OBJECT to activated or deactivated
28 void setEnabled(FL_OBJECT * ob, bool enable)
29 {
30         if (enable) {
31                 fl_activate_object(ob);
32                 fl_set_object_lcol(ob, FL_BLACK);
33         } else {
34                 fl_deactivate_object(ob);
35                 fl_set_object_lcol(ob, FL_INACTIVE);
36         }
37 }
38
39         
40 // Take a string and add breaks so that it fits into a desired label width, w
41 string formatted(string const & sin, int w, int size, int style)
42 {
43         string sout;
44         if (sin.empty()) return sout;
45
46         // break sin up into a vector of individual words
47         vector<string> sentence;
48         string word;
49         for (string::const_iterator sit = sin.begin();
50              sit != sin.end(); ++sit) {
51                 if ((*sit) == ' ' || (*sit) == '\n') {
52                         sentence.push_back(word);
53                         word.erase();
54                 } else {
55                         word += (*sit);
56                 }
57         }
58         // Flush remaining contents of word
59         if (!word.empty() ) sentence.push_back(word);
60
61         string line, l1;
62         for (vector<string>::const_iterator vit = sentence.begin();
63              vit != sentence.end(); ++vit) {
64                 if (!l1.empty() ) l1 += ' ';
65                 l1 += (*vit);
66                 int length = fl_get_string_width(style, size, l1.c_str(),
67                                                  int(l1.length()));
68                 if (length >= w) {
69                         if (!sout.empty() ) sout += '\n';
70                         sout += line;
71                         l1 = (*vit);
72                 }
73
74                 line = l1;
75         }
76         // Flush remaining contents of line
77         if (!line.empty()) {
78                 if (!sout.empty() ) sout += '\n';
79                 sout += line;
80         }
81         
82         return sout;
83 }
84
85
86 string const browseFile(LyXView * lv, string const & filename,
87                         string const & title,
88                         string const & pattern, 
89                         pair<string,string> const & dir1,
90                         pair<string,string> const & dir2)
91 {
92         string lastPath = ".";
93         if (!filename.empty()) lastPath = OnlyPath(filename);
94
95         FileDialog fileDlg(lv, title, LFUN_SELECT_FILE_SYNC, dir1, dir2);
96
97         FileDialog::Result result;
98  
99         while (1) {
100                 result = fileDlg.Select(lastPath, pattern, OnlyFilename(filename));
101
102                 if (result.second.empty()) 
103                         return result.second;
104
105                 lastPath = OnlyPath(result.second);
106
107                 if (result.second.find_first_of("#~$% ") == string::npos)
108                         break; 
109  
110                 WriteAlert(_("Filename can't contain any "
111                         "of these characters:"),
112                         _("space, '#', '~', '$' or '%'."));
113         }
114
115         return result.second;
116 }
117
118
119 namespace {
120
121 // sorted by hand to prevent LyXLex from complaining on read().
122 keyword_item xformTags[] = {
123         { "\\gui_background", FL_COL1 },
124         { "\\gui_buttonbottom", FL_BOTTOM_BCOL },
125         { "\\gui_buttonleft", FL_LEFT_BCOL },
126         { "\\gui_buttonright", FL_RIGHT_BCOL },
127         { "\\gui_buttontop", FL_TOP_BCOL },
128         { "\\gui_inactive", FL_INACTIVE },
129         { "\\gui_push_button", FL_YELLOW },
130         { "\\gui_selected", FL_MCOL },  
131         { "\\gui_text", FL_BLACK }
132 };
133
134
135 const int xformCount = sizeof(xformTags) / sizeof(keyword_item);
136
137 } // namespace anon
138
139
140 bool XformsColor::read(string const & filename)
141 {
142         LyXLex lexrc(xformTags, xformCount);
143         if (!lexrc.setFile(filename))
144                 return false;
145
146         while (lexrc.IsOK()) {
147                 int const le = lexrc.lex();
148
149                 switch (le) {
150                 case LyXLex::LEX_UNDEF:
151                         lexrc.printError("Unknown tag `$$Token'");
152                         continue; 
153                 case LyXLex::LEX_FEOF:
154                         continue;
155                 default: break;
156                 }
157
158                 RGBColor col;
159
160                 if (!lexrc.next()) break;
161                 col.r = lexrc.GetInteger();
162
163                 if (!lexrc.next()) break;
164                 col.g = lexrc.GetInteger();
165
166                 if (!lexrc.next()) break;
167                 col.b = lexrc.GetInteger();
168
169                 fl_mapcolor(le, col.r, col.g, col.b);
170         }
171                 
172         return true;
173 }
174
175
176 bool XformsColor::write(string const & filename)
177 {
178         ofstream os(filename.c_str());
179         if (!os)
180                 return false;
181
182         os << "### This file is part of\n"
183            << "### ========================================================\n"
184            << "###          LyX, The Document Processor\n"
185            << "###\n"
186            << "###          Copyright 1995 Matthias Ettrich\n"
187            << "###          Copyright 1995-2000 The LyX Team.\n"
188            << "###\n"
189            << "### ========================================================\n"
190            << "\n"
191            << "# This file is written by LyX, if you want to make your own\n"
192            << "# modifications you should do them from inside LyX and save\n"
193            << "\n";
194
195         for (int i = 0; i < xformCount; ++i) {
196                 string const tag  = xformTags[i].tag;
197                 int const colorID = xformTags[i].code;
198                 RGBColor color;
199
200                 fl_getmcolor(colorID, &color.r, &color.g, &color.b);
201
202                 os << tag << " "
203                    << color.r << " " << color.g << " " << color.b << "\n";
204         }
205
206         return true;
207 }
208
209
210 string  RWInfo::error_message;
211
212 bool RWInfo::WriteableDir(string const & name)
213 {
214         error_message.erase();
215
216         if (!AbsolutePath(name)) {
217                 error_message = N_("The absolute path is required.");
218                 return false;
219         }
220
221         FileInfo const tp(name);
222         if (!tp.isDir()) {
223                 error_message = N_("Directory does not exist.");
224                 return false;
225         }
226
227         if (!tp.writable()) {
228                 error_message = N_("Cannot write to this directory.");
229                 return false;
230         }
231
232         return true;
233 }
234
235
236 bool RWInfo::ReadableDir(string const & name)
237 {
238         error_message.erase();
239
240         if (!AbsolutePath(name)) {
241                 error_message = N_("The absolute path is required.");
242                 return false;
243         }
244
245         FileInfo const tp(name);
246         if (!tp.isDir()) {
247                 error_message = N_("Directory does not exist.");
248                 return false;
249         }
250
251         if (!tp.readable()) {
252                 error_message = N_("Cannot read this directory.");
253                 return false;
254         }
255
256         return true;
257 }
258
259
260 bool RWInfo::WriteableFile(string const & name)
261 {
262         // A writeable file is either:
263         // * An existing file to which we have write access, or
264         // * A file that doesn't yet exist but that would exist in a writeable
265         //   directory.
266
267         error_message.erase();
268
269         if (name.empty()) {
270                 error_message = N_("No file input.");
271                 return false;
272         }
273
274         string const dir = OnlyPath(name);
275         if (!AbsolutePath(dir)) {
276                 error_message = N_("The absolute path is required.");
277                 return false;
278         }
279
280         FileInfo d(name);
281         if (!d.isDir()) {
282                 d.newFile(dir);
283         }
284
285         if (!d.isDir()) {
286                 error_message = N_("Directory does not exist.");
287                 return false;
288         }
289         
290         if (!d.writable()) {
291                 error_message = N_("Cannot write to this directory.");
292                 return false;
293         }
294
295         FileInfo f(name);
296         if (dir == name || f.isDir()) {
297                 error_message = N_("A file is required, not a directory.");
298                 return false;
299         }
300
301         if (f.exist() && !f.writable()) {
302                 error_message = N_("Cannot write to this file.");
303                 return false;
304         }
305         
306         return true;
307 }
308
309
310 bool RWInfo::ReadableFile(string const & name)
311 {
312         error_message.erase();
313
314         if (name.empty()) {
315                 error_message = N_("No file input.");
316                 return false;
317         }
318
319         string const dir = OnlyPath(name);
320         if (!AbsolutePath(dir)) {
321                 error_message = N_("The absolute path is required.");
322                 return false;
323         }
324
325         FileInfo d(name);
326         if (!d.isDir()) {
327                 d.newFile(dir);
328         }
329
330         if (!d.isDir()) {
331                 error_message = N_("Directory does not exist.");
332                 return false;
333         }
334         
335         if (!d.readable()) {
336                 error_message = N_("Cannot read from this directory.");
337                 return false;
338         }
339
340         FileInfo f(name);
341         if (dir == name || f.isDir()) {
342                 error_message = N_("A file is required, not a directory.");
343                 return false;
344         }
345
346         if (!f.exist()) {
347                 error_message = N_("File does not exist.");
348                 return false;
349         }
350         
351         if (!f.readable()) {
352                 error_message = N_("Cannot read from this file.");
353                 return false;
354         }
355
356         return true;
357 }