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