ntk/src/Fl_File_Icon.cxx

493 lines
11 KiB
C++

//
// "$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 $".
//