| // |
| // "$Id: Fl_File_Icon.cxx 7903 2010-11-28 21:06:39Z matt $" |
| // |
| // Fl_File_Icon routines. |
| // |
| // KDE icon code donated by Maarten De Boer. |
| // |
| // Copyright 1999-2010 by Michael Sweet. |
| // |
| // This library is free software; you can redistribute it and/or |
| // modify it under the terms of the GNU Library General Public |
| // License as published by the Free Software Foundation; either |
| // version 2 of the License, or (at your option) any later version. |
| // |
| // This library is distributed in the hope that it will be useful, |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| // Library General Public License for more details. |
| // |
| // You should have received a copy of the GNU Library General Public |
| // License along with this library; if not, write to the Free Software |
| // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 |
| // USA. |
| // |
| // Please report all bugs and problems on the following page: |
| // |
| // http://www.fltk.org/str.php |
| // |
| // Contents: |
| // |
| // Fl_File_Icon::Fl_File_Icon() - Create a new file icon. |
| // Fl_File_Icon::~Fl_File_Icon() - Remove a file icon. |
| // Fl_File_Icon::add() - Add data to an icon. |
| // Fl_File_Icon::find() - Find an icon based upon a given file. |
| // Fl_File_Icon::draw() - Draw an icon. |
| // Fl_File_Icon::label() - Set the widgets label to an icon. |
| // Fl_File_Icon::labeltype() - Draw the icon label. |
| // |
| |
| // |
| // Include necessary header files... |
| // |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <FL/fl_utf8.h> |
| #include "flstring.h" |
| #include <errno.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #if (defined(WIN32) && ! defined(__CYGWIN__)) || defined(__EMX__) |
| # include <io.h> |
| # define F_OK 0 |
| #else |
| # include <unistd.h> |
| #endif /* WIN32 || __EMX__ */ |
| |
| #include <FL/Fl_File_Icon.H> |
| #include <FL/Fl_Widget.H> |
| #include <FL/fl_draw.H> |
| #include <FL/filename.H> |
| |
| |
| // |
| // Define missing POSIX/XPG4 macros as needed... |
| // |
| |
| #ifndef S_ISDIR |
| # define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) |
| # define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) |
| # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) |
| # define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) |
| # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) |
| #endif /* !S_ISDIR */ |
| |
| |
| // |
| // Icon cache... |
| // |
| |
| Fl_File_Icon *Fl_File_Icon::first_ = (Fl_File_Icon *)0; |
| |
| |
| /** |
| Creates a new Fl_File_Icon with the specified information. |
| \param[in] p filename pattern |
| \param[in] t file type |
| \param[in] nd number of data values |
| \param[in] d data values |
| */ |
| Fl_File_Icon::Fl_File_Icon(const char *p, /* I - Filename pattern */ |
| int t, /* I - File type */ |
| int nd, /* I - Number of data values */ |
| short *d) /* I - Data values */ |
| { |
| // Initialize the pattern and type... |
| pattern_ = p; |
| type_ = t; |
| |
| // Copy icon data as needed... |
| if (nd) |
| { |
| num_data_ = nd; |
| alloc_data_ = nd + 1; |
| data_ = (short *)calloc(sizeof(short), nd + 1); |
| memcpy(data_, d, nd * sizeof(short)); |
| } |
| else |
| { |
| num_data_ = 0; |
| alloc_data_ = 0; |
| } |
| |
| // And add the icon to the list of icons... |
| next_ = first_; |
| first_ = this; |
| } |
| |
| |
| /** |
| The destructor destroys the icon and frees all memory that has been |
| allocated for it. |
| */ |
| Fl_File_Icon::~Fl_File_Icon() { |
| Fl_File_Icon *current, // Current icon in list |
| *prev; // Previous icon in list |
| |
| |
| // Find the icon in the list... |
| for (current = first_, prev = (Fl_File_Icon *)0; |
| current != this && current != (Fl_File_Icon *)0; |
| prev = current, current = current->next_); |
| |
| // Remove the icon from the list as needed... |
| if (current) |
| { |
| if (prev) |
| prev->next_ = current->next_; |
| else |
| first_ = current->next_; |
| } |
| |
| // Free any memory used... |
| if (alloc_data_) |
| free(data_); |
| } |
| |
| |
| /** |
| Adds a keyword value to the icon array, returning a pointer to it. |
| \param[in] d data value |
| */ |
| short * // O - Pointer to new data value |
| Fl_File_Icon::add(short d) // I - Data to add |
| { |
| short *dptr; // Pointer to new data value |
| |
| |
| // Allocate/reallocate memory as needed |
| if ((num_data_ + 1) >= alloc_data_) |
| { |
| alloc_data_ += 128; |
| |
| if (alloc_data_ == 128) |
| dptr = (short *)malloc(sizeof(short) * alloc_data_); |
| else |
| dptr = (short *)realloc(data_, sizeof(short) * alloc_data_); |
| |
| if (dptr == NULL) |
| return (NULL); |
| |
| data_ = dptr; |
| } |
| |
| // Store the new data value and return |
| data_[num_data_++] = d; |
| data_[num_data_] = END; |
| |
| return (data_ + num_data_ - 1); |
| } |
| |
| |
| /** |
| Finds an icon that matches the given filename and file type. |
| \param[in] filename name of file |
| \param[in] filetype enumerated file type |
| \return matching file icon or NULL |
| */ |
| Fl_File_Icon * // O - Matching file icon or NULL |
| Fl_File_Icon::find(const char *filename,// I - Name of file */ |
| int filetype) // I - Enumerated file type |
| { |
| Fl_File_Icon *current; // Current file in list |
| #ifndef WIN32 |
| struct stat fileinfo; // Information on file |
| #endif // !WIN32 |
| const char *name; // Base name of filename |
| |
| |
| // Get file information if needed... |
| if (filetype == ANY) |
| { |
| #ifdef WIN32 |
| if (filename[strlen(filename) - 1] == '/') |
| filetype = DIRECTORY; |
| else if (fl_filename_isdir(filename)) |
| filetype = DIRECTORY; |
| else |
| filetype = PLAIN; |
| #else |
| if (!fl_stat(filename, &fileinfo)) |
| { |
| if (S_ISDIR(fileinfo.st_mode)) |
| filetype = DIRECTORY; |
| # ifdef S_IFIFO |
| else if (S_ISFIFO(fileinfo.st_mode)) |
| filetype = FIFO; |
| # endif // S_IFIFO |
| # if defined(S_ICHR) && defined(S_IBLK) |
| else if (S_ISCHR(fileinfo.st_mode) || S_ISBLK(fileinfo.st_mode)) |
| filetype = DEVICE; |
| # endif // S_ICHR && S_IBLK |
| # ifdef S_ILNK |
| else if (S_ISLNK(fileinfo.st_mode)) |
| filetype = LINK; |
| # endif // S_ILNK |
| else |
| filetype = PLAIN; |
| } |
| else |
| filetype = PLAIN; |
| #endif // WIN32 |
| } |
| |
| // Look at the base name in the filename |
| name = fl_filename_name(filename); |
| |
| // Loop through the available file types and return any match that |
| // is found... |
| for (current = first_; current != (Fl_File_Icon *)0; current = current->next_) |
| if ((current->type_ == filetype || current->type_ == ANY) && |
| (fl_filename_match(filename, current->pattern_) || |
| fl_filename_match(name, current->pattern_))) |
| break; |
| |
| // Return the match (if any)... |
| return (current); |
| } |
| |
| /** |
| Draws an icon in the indicated area. |
| \param[in] x, y, w, h position and size |
| \param[in] ic icon color |
| \param[in] active status, default is active [non-zero] |
| */ |
| void |
| Fl_File_Icon::draw(int x, // I - Upper-lefthand X |
| int y, // I - Upper-lefthand Y |
| int w, // I - Width of bounding box |
| int h, // I - Height of bounding box |
| Fl_Color ic, // I - Icon color... |
| int active) // I - Active or inactive? |
| { |
| Fl_Color c, // Current color |
| oc; // Outline color |
| short *d, // Pointer to data |
| *dend; // End of data... |
| short *prim; // Pointer to start of primitive... |
| double scale; // Scale of icon |
| |
| |
| // Don't try to draw a NULL array! |
| if (num_data_ == 0) |
| return; |
| |
| // Setup the transform matrix as needed... |
| scale = w < h ? w : h; |
| |
| fl_push_matrix(); |
| fl_translate((float)x + 0.5 * ((float)w - scale), |
| (float)y + 0.5 * ((float)h + scale)); |
| fl_scale(scale, -scale); |
| |
| // Loop through the array until we see an unmatched END... |
| d = data_; |
| dend = data_ + num_data_; |
| prim = NULL; |
| c = ic; |
| |
| if (active) |
| fl_color(c); |
| else |
| fl_color(fl_inactive(c)); |
| |
| while (d < dend) |
| switch (*d) |
| { |
| case END : |
| if (prim) |
| switch (*prim) |
| { |
| case LINE : |
| fl_end_line(); |
| break; |
| |
| case CLOSEDLINE : |
| fl_end_loop(); |
| break; |
| |
| case POLYGON : |
| fl_end_complex_polygon(); |
| break; |
| |
| case OUTLINEPOLYGON : |
| fl_end_complex_polygon(); |
| |
| oc = (Fl_Color)((((unsigned short *)prim)[1] << 16) | |
| ((unsigned short *)prim)[2]); |
| if (active) |
| { |
| if (oc == FL_ICON_COLOR) |
| fl_color(ic); |
| else |
| fl_color(oc); |
| } |
| else |
| { |
| if (oc == FL_ICON_COLOR) |
| fl_color(fl_inactive(ic)); |
| else |
| fl_color(fl_inactive(oc)); |
| } |
| |
| fl_begin_loop(); |
| |
| prim += 3; |
| while (*prim == VERTEX) |
| { |
| fl_vertex(prim[1] * 0.0001, prim[2] * 0.0001); |
| prim += 3; |
| } |
| |
| fl_end_loop(); |
| fl_color(c); |
| break; |
| } |
| |
| prim = NULL; |
| d ++; |
| break; |
| |
| case COLOR : |
| c = (Fl_Color)((((unsigned short *)d)[1] << 16) | |
| ((unsigned short *)d)[2]); |
| |
| if (c == FL_ICON_COLOR) |
| c = ic; |
| |
| if (!active) |
| c = fl_inactive(c); |
| |
| fl_color(c); |
| d += 3; |
| break; |
| |
| case LINE : |
| prim = d; |
| d ++; |
| fl_begin_line(); |
| break; |
| |
| case CLOSEDLINE : |
| prim = d; |
| d ++; |
| fl_begin_loop(); |
| break; |
| |
| case POLYGON : |
| prim = d; |
| d ++; |
| fl_begin_complex_polygon(); |
| break; |
| |
| case OUTLINEPOLYGON : |
| prim = d; |
| d += 3; |
| fl_begin_complex_polygon(); |
| break; |
| |
| case VERTEX : |
| if (prim) |
| fl_vertex(d[1] * 0.0001, d[2] * 0.0001); |
| d += 3; |
| break; |
| |
| default : // Ignore invalid data... |
| d ++; |
| } |
| |
| // If we still have an open primitive, close it... |
| if (prim) |
| switch (*prim) |
| { |
| case LINE : |
| fl_end_line(); |
| break; |
| |
| case CLOSEDLINE : |
| fl_end_loop(); |
| break; |
| |
| case POLYGON : |
| fl_end_polygon(); |
| break; |
| |
| case OUTLINEPOLYGON : |
| fl_end_polygon(); |
| |
| oc = (Fl_Color)((((unsigned short *)prim)[1] << 16) | |
| ((unsigned short *)prim)[2]); |
| if (active) |
| { |
| if (oc == FL_ICON_COLOR) |
| fl_color(ic); |
| else |
| fl_color(oc); |
| } |
| else |
| { |
| if (oc == FL_ICON_COLOR) |
| fl_color(fl_inactive(ic)); |
| else |
| fl_color(fl_inactive(oc)); |
| } |
| |
| fl_begin_loop(); |
| |
| prim += 3; |
| while (*prim == VERTEX) |
| { |
| fl_vertex(prim[1] * 0.0001, prim[2] * 0.0001); |
| prim += 3; |
| } |
| |
| fl_end_loop(); |
| fl_color(c); |
| break; |
| } |
| |
| // Restore the transform matrix |
| fl_pop_matrix(); |
| } |
| |
| /** |
| Applies the icon to the widget, registering the Fl_File_Icon |
| label type as needed. |
| \param[in] w widget for which this icon will become the label |
| */ |
| void Fl_File_Icon::label(Fl_Widget *w) // I - Widget to label |
| { |
| Fl::set_labeltype(_FL_ICON_LABEL, labeltype, 0); |
| w->label(_FL_ICON_LABEL, (const char*)this); |
| } |
| |
| |
| /** |
| Draw the icon label. |
| \param[in] o label data |
| \param[in] x, y, w, h position and size of label |
| \param[in] a label alignment [not used] |
| */ |
| void |
| Fl_File_Icon::labeltype(const Fl_Label *o, // I - Label data |
| int x, // I - X position of label |
| int y, // I - Y position of label |
| int w, // I - Width of label |
| int h, // I - Height of label |
| Fl_Align a) // I - Label alignment (not used) |
| { |
| Fl_File_Icon *icon; // Pointer to icon data |
| |
| |
| (void)a; |
| |
| icon = (Fl_File_Icon *)(o->value); |
| if (icon) icon->draw(x, y, w, h, (Fl_Color)(o->color)); |
| } |
| |
| |
| // |
| // End of "$Id: Fl_File_Icon.cxx 7903 2010-11-28 21:06:39Z matt $". |
| // |