mirror of https://github.com/fltk/fltk.git
FLTK - Fast Light Tool Kit - https://github.com/fltk/fltk - cross platform GUI development
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
488 lines
11 KiB
488 lines
11 KiB
// |
|
// "$Id$" |
|
// |
|
// Fl_File_Icon routines. |
|
// |
|
// KDE icon code donated by Maarten De Boer. |
|
// |
|
// Copyright 1999-2010 by Michael Sweet. |
|
// |
|
// This library is free software. Distribution and use rights are outlined in |
|
// the file "COPYING" which should have been included with this file. If this |
|
// file is missing or damaged, see the license at: |
|
// |
|
// http://www.fltk.org/COPYING.php |
|
// |
|
// 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> |
|
|
|
#if defined(WIN32) || defined(__APPLE__) // PORTME: platform file browser |
|
#elif defined(FL_PORTING) |
|
# pragma message "FL_PORTING: implement file type interpretation here" |
|
#else |
|
#endif |
|
|
|
// |
|
// 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$". |
|
//
|
|
|