themes: Workaround for bug where a background color of RGB 0,0,0 in Black color schem...
[ntk.git] / src / Fl_File_Icon.cxx
blob98069dda9311743e86643034a4aaf7e178421133
1 //
2 // "$Id: Fl_File_Icon.cxx 7903 2010-11-28 21:06:39Z matt $"
3 //
4 // Fl_File_Icon routines.
5 //
6 // KDE icon code donated by Maarten De Boer.
7 //
8 // Copyright 1999-2010 by Michael Sweet.
9 //
10 // This library is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Library General Public
12 // License as published by the Free Software Foundation; either
13 // version 2 of the License, or (at your option) any later version.
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Library General Public License for more details.
20 // You should have received a copy of the GNU Library General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 // USA.
25 // Please report all bugs and problems on the following page:
27 // http://www.fltk.org/str.php
29 // Contents:
31 // Fl_File_Icon::Fl_File_Icon() - Create a new file icon.
32 // Fl_File_Icon::~Fl_File_Icon() - Remove a file icon.
33 // Fl_File_Icon::add() - Add data to an icon.
34 // Fl_File_Icon::find() - Find an icon based upon a given file.
35 // Fl_File_Icon::draw() - Draw an icon.
36 // Fl_File_Icon::label() - Set the widgets label to an icon.
37 // Fl_File_Icon::labeltype() - Draw the icon label.
41 // Include necessary header files...
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <FL/fl_utf8.h>
47 #include "flstring.h"
48 #include <errno.h>
49 #include <sys/types.h>
50 #include <sys/stat.h>
51 #if (defined(WIN32) && ! defined(__CYGWIN__)) || defined(__EMX__)
52 # include <io.h>
53 # define F_OK 0
54 #else
55 # include <unistd.h>
56 #endif /* WIN32 || __EMX__ */
58 #include <FL/Fl_File_Icon.H>
59 #include <FL/Fl_Widget.H>
60 #include <FL/fl_draw.H>
61 #include <FL/filename.H>
65 // Define missing POSIX/XPG4 macros as needed...
68 #ifndef S_ISDIR
69 # define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
70 # define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
71 # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
72 # define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
73 # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
74 #endif /* !S_ISDIR */
78 // Icon cache...
81 Fl_File_Icon *Fl_File_Icon::first_ = (Fl_File_Icon *)0;
84 /**
85 Creates a new Fl_File_Icon with the specified information.
86 \param[in] p filename pattern
87 \param[in] t file type
88 \param[in] nd number of data values
89 \param[in] d data values
91 Fl_File_Icon::Fl_File_Icon(const char *p, /* I - Filename pattern */
92 int t, /* I - File type */
93 int nd, /* I - Number of data values */
94 short *d) /* I - Data values */
96 // Initialize the pattern and type...
97 pattern_ = p;
98 type_ = t;
100 // Copy icon data as needed...
101 if (nd)
103 num_data_ = nd;
104 alloc_data_ = nd + 1;
105 data_ = (short *)calloc(sizeof(short), nd + 1);
106 memcpy(data_, d, nd * sizeof(short));
108 else
110 num_data_ = 0;
111 alloc_data_ = 0;
114 // And add the icon to the list of icons...
115 next_ = first_;
116 first_ = this;
121 The destructor destroys the icon and frees all memory that has been
122 allocated for it.
124 Fl_File_Icon::~Fl_File_Icon() {
125 Fl_File_Icon *current, // Current icon in list
126 *prev; // Previous icon in list
129 // Find the icon in the list...
130 for (current = first_, prev = (Fl_File_Icon *)0;
131 current != this && current != (Fl_File_Icon *)0;
132 prev = current, current = current->next_);
134 // Remove the icon from the list as needed...
135 if (current)
137 if (prev)
138 prev->next_ = current->next_;
139 else
140 first_ = current->next_;
143 // Free any memory used...
144 if (alloc_data_)
145 free(data_);
150 Adds a keyword value to the icon array, returning a pointer to it.
151 \param[in] d data value
153 short * // O - Pointer to new data value
154 Fl_File_Icon::add(short d) // I - Data to add
156 short *dptr; // Pointer to new data value
159 // Allocate/reallocate memory as needed
160 if ((num_data_ + 1) >= alloc_data_)
162 alloc_data_ += 128;
164 if (alloc_data_ == 128)
165 dptr = (short *)malloc(sizeof(short) * alloc_data_);
166 else
167 dptr = (short *)realloc(data_, sizeof(short) * alloc_data_);
169 if (dptr == NULL)
170 return (NULL);
172 data_ = dptr;
175 // Store the new data value and return
176 data_[num_data_++] = d;
177 data_[num_data_] = END;
179 return (data_ + num_data_ - 1);
184 Finds an icon that matches the given filename and file type.
185 \param[in] filename name of file
186 \param[in] filetype enumerated file type
187 \return matching file icon or NULL
189 Fl_File_Icon * // O - Matching file icon or NULL
190 Fl_File_Icon::find(const char *filename,// I - Name of file */
191 int filetype) // I - Enumerated file type
193 Fl_File_Icon *current; // Current file in list
194 #ifndef WIN32
195 struct stat fileinfo; // Information on file
196 #endif // !WIN32
197 const char *name; // Base name of filename
200 // Get file information if needed...
201 if (filetype == ANY)
203 #ifdef WIN32
204 if (filename[strlen(filename) - 1] == '/')
205 filetype = DIRECTORY;
206 else if (fl_filename_isdir(filename))
207 filetype = DIRECTORY;
208 else
209 filetype = PLAIN;
210 #else
211 if (!fl_stat(filename, &fileinfo))
213 if (S_ISDIR(fileinfo.st_mode))
214 filetype = DIRECTORY;
215 # ifdef S_IFIFO
216 else if (S_ISFIFO(fileinfo.st_mode))
217 filetype = FIFO;
218 # endif // S_IFIFO
219 # if defined(S_ICHR) && defined(S_IBLK)
220 else if (S_ISCHR(fileinfo.st_mode) || S_ISBLK(fileinfo.st_mode))
221 filetype = DEVICE;
222 # endif // S_ICHR && S_IBLK
223 # ifdef S_ILNK
224 else if (S_ISLNK(fileinfo.st_mode))
225 filetype = LINK;
226 # endif // S_ILNK
227 else
228 filetype = PLAIN;
230 else
231 filetype = PLAIN;
232 #endif // WIN32
235 // Look at the base name in the filename
236 name = fl_filename_name(filename);
238 // Loop through the available file types and return any match that
239 // is found...
240 for (current = first_; current != (Fl_File_Icon *)0; current = current->next_)
241 if ((current->type_ == filetype || current->type_ == ANY) &&
242 (fl_filename_match(filename, current->pattern_) ||
243 fl_filename_match(name, current->pattern_)))
244 break;
246 // Return the match (if any)...
247 return (current);
251 Draws an icon in the indicated area.
252 \param[in] x, y, w, h position and size
253 \param[in] ic icon color
254 \param[in] active status, default is active [non-zero]
256 void
257 Fl_File_Icon::draw(int x, // I - Upper-lefthand X
258 int y, // I - Upper-lefthand Y
259 int w, // I - Width of bounding box
260 int h, // I - Height of bounding box
261 Fl_Color ic, // I - Icon color...
262 int active) // I - Active or inactive?
264 Fl_Color c, // Current color
265 oc; // Outline color
266 short *d, // Pointer to data
267 *dend; // End of data...
268 short *prim; // Pointer to start of primitive...
269 double scale; // Scale of icon
272 // Don't try to draw a NULL array!
273 if (num_data_ == 0)
274 return;
276 // Setup the transform matrix as needed...
277 scale = w < h ? w : h;
279 fl_push_matrix();
280 fl_translate((float)x + 0.5 * ((float)w - scale),
281 (float)y + 0.5 * ((float)h + scale));
282 fl_scale(scale, -scale);
284 // Loop through the array until we see an unmatched END...
285 d = data_;
286 dend = data_ + num_data_;
287 prim = NULL;
288 c = ic;
290 if (active)
291 fl_color(c);
292 else
293 fl_color(fl_inactive(c));
295 while (d < dend)
296 switch (*d)
298 case END :
299 if (prim)
300 switch (*prim)
302 case LINE :
303 fl_end_line();
304 break;
306 case CLOSEDLINE :
307 fl_end_loop();
308 break;
310 case POLYGON :
311 fl_end_complex_polygon();
312 break;
314 case OUTLINEPOLYGON :
315 fl_end_complex_polygon();
317 oc = (Fl_Color)((((unsigned short *)prim)[1] << 16) |
318 ((unsigned short *)prim)[2]);
319 if (active)
321 if (oc == FL_ICON_COLOR)
322 fl_color(ic);
323 else
324 fl_color(oc);
326 else
328 if (oc == FL_ICON_COLOR)
329 fl_color(fl_inactive(ic));
330 else
331 fl_color(fl_inactive(oc));
334 fl_begin_loop();
336 prim += 3;
337 while (*prim == VERTEX)
339 fl_vertex(prim[1] * 0.0001, prim[2] * 0.0001);
340 prim += 3;
343 fl_end_loop();
344 fl_color(c);
345 break;
348 prim = NULL;
349 d ++;
350 break;
352 case COLOR :
353 c = (Fl_Color)((((unsigned short *)d)[1] << 16) |
354 ((unsigned short *)d)[2]);
356 if (c == FL_ICON_COLOR)
357 c = ic;
359 if (!active)
360 c = fl_inactive(c);
362 fl_color(c);
363 d += 3;
364 break;
366 case LINE :
367 prim = d;
368 d ++;
369 fl_begin_line();
370 break;
372 case CLOSEDLINE :
373 prim = d;
374 d ++;
375 fl_begin_loop();
376 break;
378 case POLYGON :
379 prim = d;
380 d ++;
381 fl_begin_complex_polygon();
382 break;
384 case OUTLINEPOLYGON :
385 prim = d;
386 d += 3;
387 fl_begin_complex_polygon();
388 break;
390 case VERTEX :
391 if (prim)
392 fl_vertex(d[1] * 0.0001, d[2] * 0.0001);
393 d += 3;
394 break;
396 default : // Ignore invalid data...
397 d ++;
400 // If we still have an open primitive, close it...
401 if (prim)
402 switch (*prim)
404 case LINE :
405 fl_end_line();
406 break;
408 case CLOSEDLINE :
409 fl_end_loop();
410 break;
412 case POLYGON :
413 fl_end_polygon();
414 break;
416 case OUTLINEPOLYGON :
417 fl_end_polygon();
419 oc = (Fl_Color)((((unsigned short *)prim)[1] << 16) |
420 ((unsigned short *)prim)[2]);
421 if (active)
423 if (oc == FL_ICON_COLOR)
424 fl_color(ic);
425 else
426 fl_color(oc);
428 else
430 if (oc == FL_ICON_COLOR)
431 fl_color(fl_inactive(ic));
432 else
433 fl_color(fl_inactive(oc));
436 fl_begin_loop();
438 prim += 3;
439 while (*prim == VERTEX)
441 fl_vertex(prim[1] * 0.0001, prim[2] * 0.0001);
442 prim += 3;
445 fl_end_loop();
446 fl_color(c);
447 break;
450 // Restore the transform matrix
451 fl_pop_matrix();
455 Applies the icon to the widget, registering the Fl_File_Icon
456 label type as needed.
457 \param[in] w widget for which this icon will become the label
459 void Fl_File_Icon::label(Fl_Widget *w) // I - Widget to label
461 Fl::set_labeltype(_FL_ICON_LABEL, labeltype, 0);
462 w->label(_FL_ICON_LABEL, (const char*)this);
467 Draw the icon label.
468 \param[in] o label data
469 \param[in] x, y, w, h position and size of label
470 \param[in] a label alignment [not used]
472 void
473 Fl_File_Icon::labeltype(const Fl_Label *o, // I - Label data
474 int x, // I - X position of label
475 int y, // I - Y position of label
476 int w, // I - Width of label
477 int h, // I - Height of label
478 Fl_Align a) // I - Label alignment (not used)
480 Fl_File_Icon *icon; // Pointer to icon data
483 (void)a;
485 icon = (Fl_File_Icon *)(o->value);
486 if (icon) icon->draw(x, y, w, h, (Fl_Color)(o->color));
491 // End of "$Id: Fl_File_Icon.cxx 7903 2010-11-28 21:06:39Z matt $".