fltk/src/Fl_File_Icon2.cxx
Matthias Melcher a63ad76603
FLUID refactor and macOS warnings removed (#623)
P renamed to g_project
class Project renamed to class Fluid_Project
fixes macOS type cast warnings
2023-01-01 20:05:42 +01:00

990 lines
30 KiB
C++

//
// Fl_File_Icon system icon routines.
//
// KDE icon code donated by Maarten De Boer.
//
// Copyright 1999-2010 by Michael Sweet.
// Copyright 2011-2019 by Bill Spitzak and others.
//
// 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:
//
// https://www.fltk.org/COPYING.php
//
// Please see the following page on how to report bugs and issues:
//
// https://www.fltk.org/bugs.php
//
// Contents:
//
// Fl_File_Icon::load() - Load an icon file...
// Fl_File_Icon::load_fti() - Load an SGI-format FTI file...
// Fl_File_Icon::load_image() - Load an image icon file...
// Fl_File_Icon::load_system_icons() - Load the standard system icons/filetypes.
// load_kde_icons() - Load KDE icon files.
// load_kde_mimelnk() - Load a KDE "mimelnk" file.
// kde_to_fltk_pattern() - Convert a KDE pattern to a FLTK pattern.
// get_kde_val() - Get a KDE value.
//
//
// Include necessary header files...
//
#include <stdio.h>
#include <stdlib.h>
#include <FL/fl_utf8.h>
#include "flstring.h"
#include <ctype.h>
#include <errno.h>
#include <FL/math.h>
#include <FL/Fl_File_Icon.H>
#include <FL/Fl_Shared_Image.H>
#include <FL/Fl_Widget.H>
#include <FL/fl_draw.H>
#include <FL/filename.H>
#ifndef F_OK
# define F_OK 0
#endif
//
// Local functions...
//
static void load_kde_icons(const char *directory, const char *icondir);
static void load_kde_mimelnk(const char *filename, const char *icondir);
static char *kde_to_fltk_pattern(const char *kdepattern);
static char *get_kde_val(char *str, const char *key);
//
// Local globals...
//
static const char *kdedir = NULL;
/**
Loads the specified icon image. The format is deduced from the filename.
\param[in] f filename
*/
void
Fl_File_Icon::load(const char *f) // I - File to read from
{
int i; // Load status...
const char *ext; // File extension
ext = fl_filename_ext(f);
if (ext && strcmp(ext, ".fti") == 0)
i = load_fti(f);
else
i = load_image(f);
if (i)
{
Fl::warning("Fl_File_Icon::load(): Unable to load icon file \"%s\".", f);
return;
}
}
/**
Loads an SGI icon file.
\param[in] fti icon filename
\return 0 on success, non-zero on error
*/
int // O - 0 on success, non-zero on error
Fl_File_Icon::load_fti(const char *fti) // I - File to read from
{
FILE *fp; // File pointer
int ch; // Current character
char command[255], // Command string ("vertex", etc.)
params[255], // Parameter string ("10.0,20.0", etc.)
*ptr; // Pointer into strings
int outline; // Outline polygon
// Try to open the file...
if ((fp = fl_fopen(fti, "rb")) == NULL)
{
Fl::error("Fl_File_Icon::load_fti(): Unable to open \"%s\" - %s",
fti, strerror(errno));
return -1;
}
// Read the entire file, adding data as needed...
outline = 0;
while ((ch = getc(fp)) != EOF)
{
// Skip whitespace
if (isspace(ch))
continue;
// Skip comments starting with "#"...
if (ch == '#')
{
while ((ch = getc(fp)) != EOF)
if (ch == '\n')
break;
if (ch == EOF)
break;
else
continue;
}
// OK, this character better be a letter...
if (!isalpha(ch))
{
Fl::error("Fl_File_Icon::load_fti(): Expected a letter at file position %ld (saw '%c')",
ftell(fp) - 1, ch);
break;
}
// Scan the command name...
ptr = command;
*ptr++ = ch;
while ((ch = getc(fp)) != EOF)
{
if (ch == '(')
break;
else if (ptr < (command + sizeof(command) - 1))
*ptr++ = ch;
}
*ptr++ = '\0';
// Make sure we stopped on a parenthesis...
if (ch != '(')
{
Fl::error("Fl_File_Icon::load_fti(): Expected a ( at file position %ld (saw '%c')",
ftell(fp) - 1, ch);
break;
}
// Scan the parameters...
ptr = params;
while ((ch = getc(fp)) != EOF)
{
if (ch == ')')
break;
else if (ptr < (params + sizeof(params) - 1))
*ptr++ = ch;
}
*ptr++ = '\0';
// Make sure we stopped on a parenthesis...
if (ch != ')')
{
Fl::error("Fl_File_Icon::load_fti(): Expected a ) at file position %ld (saw '%c')",
ftell(fp) - 1, ch);
break;
}
// Make sure the next character is a semicolon...
if ((ch = getc(fp)) != ';')
{
Fl::error("Fl_File_Icon::load_fti(): Expected a ; at file position %ld (saw '%c')",
ftell(fp) - 1, ch);
break;
}
// Now process the command...
if (strcmp(command, "color") == 0)
{
// Set the color; for negative colors blend the two primaries to
// produce a composite color. Also, the following symbolic color
// names are understood:
//
// name FLTK color
// ------------- ----------
// iconcolor FL_ICON_COLOR; mapped to the icon color in
// Fl_File_Icon::draw()
// shadowcolor FL_DARK3
// outlinecolor FL_BLACK
if (strcmp(params, "iconcolor") == 0)
add_color(FL_ICON_COLOR);
else if (strcmp(params, "shadowcolor") == 0)
add_color(FL_DARK3);
else if (strcmp(params, "outlinecolor") == 0)
add_color(FL_BLACK);
else
{
int c = atoi(params); // Color value
if (c < 0)
{
// Composite color; compute average...
c = -c;
add_color(fl_color_average((Fl_Color)(c >> 4),
(Fl_Color)(c & 15), 0.5f));
}
else
add_color((Fl_Color)c);
}
}
else if (strcmp(command, "bgnline") == 0)
add(LINE);
else if (strcmp(command, "bgnclosedline") == 0)
add(CLOSEDLINE);
else if (strcmp(command, "bgnpolygon") == 0)
add(POLYGON);
else if (strcmp(command, "bgnoutlinepolygon") == 0)
{
add(OUTLINEPOLYGON);
outline = int(add(0) - data_);
add(0);
}
else if (strcmp(command, "endoutlinepolygon") == 0 && outline)
{
unsigned cval; // Color value
// Set the outline color; see above for valid values...
if (strcmp(params, "iconcolor") == 0)
cval = FL_ICON_COLOR;
else if (strcmp(params, "shadowcolor") == 0)
cval = FL_DARK3;
else if (strcmp(params, "outlinecolor") == 0)
cval = FL_BLACK;
else
{
int c = atoi(params); // Color value
if (c < 0)
{
// Composite color; compute average...
c = -c;
cval = fl_color_average((Fl_Color)(c >> 4), (Fl_Color)(c & 15), 0.5f);
}
else
cval = c;
}
// Store outline color...
data_[outline] = cval >> 16;
data_[outline + 1] = cval;
outline = 0;
add(END);
}
else if (strncmp(command, "end", 3) == 0)
add(END);
else if (strcmp(command, "vertex") == 0)
{
float x, y; // Coordinates of vertex
if (sscanf(params, "%f,%f", &x, &y) != 2)
break;
add_vertex((short)(int)rint(x * 100.0), (short)(int)rint(y * 100.0));
}
else
{
Fl::error("Fl_File_Icon::load_fti(): Unknown command \"%s\" at file position %ld.",
command, ftell(fp) - 1);
break;
}
}
// Close the file and return...
fclose(fp);
#ifdef DEBUG
printf("Icon File \"%s\":\n", fti);
for (int i = 0; i < num_data_; i ++)
printf(" %d,\n", data_[i]);
#endif /* DEBUG */
return 0;
}
/**
Load an image icon file from an image filename.
\param[in] ifile image filename
\return 0 on success, non-zero on error
*/
int Fl_File_Icon::load_image(const char *ifile) // I - File to read from
{
Fl_Shared_Image *img; // Image file
img = Fl_Shared_Image::get(ifile);
if (!img || !img->count() || !img->w() || !img->h()) return -1;
if (img->count() == 1) {
int x, y; // X & Y in image
int startx; // Starting X coord
Fl_Color c, // Current color
temp; // Temporary color
const uchar *row; // Pointer into image
const int extra_data = img->ld() ? (img->ld()-img->w()*img->d()) : 0;
// Loop through grayscale or RGB image...
for (y = 0, row = (const uchar *)(*(img->data())); y < img->h(); y ++, row += extra_data)
{
for (x = 0, startx = 0, c = (Fl_Color)-1;
x < img->w();
x ++, row += img->d())
{
switch (img->d())
{
case 1 :
temp = fl_rgb_color(row[0], row[0], row[0]);
break;
case 2 :
if (row[1] > 127)
temp = fl_rgb_color(row[0], row[0], row[0]);
else
temp = (Fl_Color)-1;
break;
case 3 :
temp = fl_rgb_color(row[0], row[1], row[2]);
break;
default :
if (row[3] > 127)
temp = fl_rgb_color(row[0], row[1], row[2]);
else
temp = (Fl_Color)-1;
break;
}
if (temp != c)
{
if (x > startx && c != (Fl_Color)-1)
{
add_color(c);
add(POLYGON);
add_vertex(startx * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h());
add_vertex(x * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h());
add_vertex(x * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h());
add_vertex(startx * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h());
add(END);
}
c = temp;
startx = x;
}
}
if (x > startx && c != (Fl_Color)-1)
{
add_color(c);
add(POLYGON);
add_vertex(startx * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h());
add_vertex(x * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h());
add_vertex(x * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h());
add_vertex(startx * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h());
add(END);
}
}
} else {
int i, j; // Looping vars
int ch; // Current character
int newch; // New character
int bg; // Background color
char val[16]; // Color value
const char *lineptr, // Pointer into line
*const*ptr; // Pointer into data array
int ncolors, // Number of colors
chars_per_color; // Characters per color
Fl_Color *colors; // Colors
int red, green, blue; // Red, green, and blue values
int x, y; // X & Y in image
int startx; // Starting X coord
// Get the pixmap data...
ptr = img->data();
sscanf(*ptr, "%*d%*d%d%d", &ncolors, &chars_per_color);
colors = new Fl_Color[int(1 << (chars_per_color * 8))];
// Read the colormap...
memset(colors, 0, sizeof(Fl_Color) << (chars_per_color * 8));
bg = ' ';
ptr ++;
if (ncolors < 0) {
// Read compressed colormap...
const uchar *cmapptr;
ncolors = -ncolors;
for (i = 0, cmapptr = (const uchar *)*ptr; i < ncolors; i ++, cmapptr += 4)
colors[cmapptr[0]] = fl_rgb_color(cmapptr[1], cmapptr[2], cmapptr[3]);
ptr ++;
} else {
for (i = 0; i < ncolors; i ++, ptr ++) {
// Get the color's character
lineptr = *ptr;
ch = *lineptr++;
if (chars_per_color > 1) ch = (ch << 8) | *lineptr++;
// Get the color value...
if ((lineptr = strstr(lineptr, "c ")) == NULL) {
// No color; make this black...
colors[ch] = FL_BLACK;
} else if (lineptr[2] == '#') {
// Read the RGB triplet...
lineptr += 3;
for (j = 0; j < 12; j ++)
if (!isxdigit(lineptr[j]))
break;
switch (j) {
case 0 :
bg = ch;
default :
red = green = blue = 0;
break;
case 3 :
val[0] = lineptr[0];
val[1] = '\0';
red = 255 * (int)strtol(val, NULL, 16) / 15;
val[0] = lineptr[1];
val[1] = '\0';
green = 255 * (int)strtol(val, NULL, 16) / 15;
val[0] = lineptr[2];
val[1] = '\0';
blue = 255 * (int)strtol(val, NULL, 16) / 15;
break;
case 6 :
case 9 :
case 12 :
j /= 3;
val[0] = lineptr[0];
val[1] = lineptr[1];
val[2] = '\0';
red = (int)strtol(val, NULL, 16);
val[0] = lineptr[j + 0];
val[1] = lineptr[j + 1];
val[2] = '\0';
green = (int)strtol(val, NULL, 16);
val[0] = lineptr[2 * j + 0];
val[1] = lineptr[2 * j + 1];
val[2] = '\0';
blue = (int)strtol(val, NULL, 16);
break;
}
colors[ch] = fl_rgb_color((uchar)red, (uchar)green, (uchar)blue);
} else {
// Read a color name...
if (strncasecmp(lineptr + 2, "white", 5) == 0) colors[ch] = FL_WHITE;
else if (strncasecmp(lineptr + 2, "black", 5) == 0) colors[ch] = FL_BLACK;
else if (strncasecmp(lineptr + 2, "none", 4) == 0) {
colors[ch] = FL_BLACK;
bg = ch;
} else colors[ch] = FL_GRAY;
}
}
}
// Read the image data...
for (y = 0; y < img->h(); y ++, ptr ++) {
lineptr = *ptr;
startx = 0;
ch = bg;
for (x = 0; x < img->w(); x ++) {
newch = *lineptr++;
if (chars_per_color > 1) newch = (newch << 8) | *lineptr++;
if (newch != ch) {
if (ch != bg) {
add_color(colors[ch]);
add(POLYGON);
add_vertex(startx * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h());
add_vertex(x * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h());
add_vertex(x * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h());
add_vertex(startx * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h());
add(END);
}
ch = newch;
startx = x;
}
}
if (ch != bg) {
add_color(colors[ch]);
add(POLYGON);
add_vertex(startx * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h());
add_vertex(x * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h());
add_vertex(x * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h());
add_vertex(startx * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h());
add(END);
}
}
// Free the colormap...
delete[] colors;
}
img->release();
#ifdef DEBUG
{
int i;
printf("Icon File \"%s\":\n", ifile);
for (i = 0; i < num_data_; i ++)
{
printf(" %d,\n", data_[i]);
}
}
#endif // DEBUG
return 0;
}
/**
Loads all system-defined icons. This call is useful when using the
FileChooser widget and should be used when the application starts:
\code
Fl_File_Icon::load_system_icons();
\endcode
*/
void
Fl_File_Icon::load_system_icons(void) {
int i; // Looping var
Fl_File_Icon *icon; // New icons
char filename[FL_PATH_MAX + 60]; // Filename
char icondir[FL_PATH_MAX]; // Icon directory
static int init = 0; // Have the icons been initialized?
const char * const icondirs[] = {
"Bluecurve", // Icon directories to look for, in order
"crystalsvg",
"default.kde",
"hicolor",
NULL
};
static short plain[] = { // Plain file icon
COLOR, -1, -1, OUTLINEPOLYGON, 0, FL_GRAY,
VERTEX, 2000, 1000, VERTEX, 2000, 9000,
VERTEX, 6000, 9000, VERTEX, 8000, 7000,
VERTEX, 8000, 1000, END, OUTLINEPOLYGON, 0, FL_GRAY,
VERTEX, 6000, 9000, VERTEX, 6000, 7000,
VERTEX, 8000, 7000, END,
COLOR, 0, FL_BLACK, LINE, VERTEX, 6000, 7000,
VERTEX, 8000, 7000, VERTEX, 8000, 1000,
VERTEX, 2000, 1000, END, LINE, VERTEX, 3000, 7000,
VERTEX, 5000, 7000, END, LINE, VERTEX, 3000, 6000,
VERTEX, 5000, 6000, END, LINE, VERTEX, 3000, 5000,
VERTEX, 7000, 5000, END, LINE, VERTEX, 3000, 4000,
VERTEX, 7000, 4000, END, LINE, VERTEX, 3000, 3000,
VERTEX, 7000, 3000, END, LINE, VERTEX, 3000, 2000,
VERTEX, 7000, 2000, END,
END
};
static short image[] = { // Image file icon
COLOR, -1, -1, OUTLINEPOLYGON, 0, FL_GRAY,
VERTEX, 2000, 1000, VERTEX, 2000, 9000,
VERTEX, 6000, 9000, VERTEX, 8000, 7000,
VERTEX, 8000, 1000, END, OUTLINEPOLYGON, 0, FL_GRAY,
VERTEX, 6000, 9000, VERTEX, 6000, 7000,
VERTEX, 8000, 7000, END,
COLOR, 0, FL_BLACK, LINE, VERTEX, 6000, 7000,
VERTEX, 8000, 7000, VERTEX, 8000, 1000,
VERTEX, 2000, 1000, END,
COLOR, 0, FL_RED, POLYGON, VERTEX, 3500, 2500,
VERTEX, 3000, 3000, VERTEX, 3000, 4000,
VERTEX, 3500, 4500, VERTEX, 4500, 4500,
VERTEX, 5000, 4000, VERTEX, 5000, 3000,
VERTEX, 4500, 2500, END,
COLOR, 0, FL_GREEN, POLYGON, VERTEX, 5500, 2500,
VERTEX, 5000, 3000, VERTEX, 5000, 4000,
VERTEX, 5500, 4500, VERTEX, 6500, 4500,
VERTEX, 7000, 4000, VERTEX, 7000, 3000,
VERTEX, 6500, 2500, END,
COLOR, 0, FL_BLUE, POLYGON, VERTEX, 4500, 3500,
VERTEX, 4000, 4000, VERTEX, 4000, 5000,
VERTEX, 4500, 5500, VERTEX, 5500, 5500,
VERTEX, 6000, 5000, VERTEX, 6000, 4000,
VERTEX, 5500, 3500, END,
END
};
static short dir[] = { // Directory icon
COLOR, -1, -1, POLYGON, VERTEX, 1000, 1000,
VERTEX, 1000, 7500, VERTEX, 9000, 7500,
VERTEX, 9000, 1000, END,
POLYGON, VERTEX, 1000, 7500, VERTEX, 2500, 9000,
VERTEX, 5000, 9000, VERTEX, 6500, 7500, END,
COLOR, 0, FL_WHITE, LINE, VERTEX, 1500, 1500,
VERTEX, 1500, 7000, VERTEX, 9000, 7000, END,
COLOR, 0, FL_BLACK, LINE, VERTEX, 9000, 7500,
VERTEX, 9000, 1000, VERTEX, 1000, 1000, END,
COLOR, 0, FL_GRAY, LINE, VERTEX, 1000, 1000,
VERTEX, 1000, 7500, VERTEX, 2500, 9000,
VERTEX, 5000, 9000, VERTEX, 6500, 7500,
VERTEX, 9000, 7500, END,
END
};
// Add symbols if they haven't been added already...
if (!init) {
// This method requires the images library...
fl_register_images();
if (!kdedir) {
// Figure out where KDE is installed...
if ((kdedir = fl_getenv("KDEDIR")) == NULL) {
if (!fl_access("/opt/kde", F_OK)) kdedir = "/opt/kde";
else if (!fl_access("/usr/local/share/mimelnk", F_OK)) kdedir = "/usr/local";
else kdedir = "/usr";
}
}
snprintf(filename, sizeof(filename), "%s/share/mimelnk", kdedir);
if (!fl_access(filename, F_OK)) {
// Load KDE icons...
icon = new Fl_File_Icon("*", Fl_File_Icon::PLAIN);
for (i = 0; icondirs[i]; i ++) {
snprintf(icondir, sizeof(icondir), "%s/share/icons/%s", kdedir,
icondirs[i]);
if (!fl_access(icondir, F_OK)) break;
}
if (icondirs[i]) {
snprintf(filename, sizeof(filename), "%s/16x16/mimetypes/unknown.png",
icondir);
} else {
snprintf(filename, sizeof(filename), "%s/share/icons/unknown.xpm",
kdedir);
}
if (!fl_access(filename, F_OK)) icon->load_image(filename);
icon = new Fl_File_Icon("*", Fl_File_Icon::LINK);
snprintf(filename, sizeof(filename), "%s/16x16/filesystems/link.png",
icondir);
if (!fl_access(filename, F_OK)) icon->load_image(filename);
snprintf(filename, sizeof(filename), "%s/share/mimelnk", kdedir);
load_kde_icons(filename, icondir);
} else if (!fl_access("/usr/share/icons/folder.xpm", F_OK)) {
// Load GNOME icons...
icon = new Fl_File_Icon("*", Fl_File_Icon::PLAIN);
icon->load_image("/usr/share/icons/page.xpm");
icon = new Fl_File_Icon("*", Fl_File_Icon::DIRECTORY);
icon->load_image("/usr/share/icons/folder.xpm");
} else if (!fl_access("/usr/dt/appconfig/icons", F_OK)) {
// Load CDE icons...
icon = new Fl_File_Icon("*", Fl_File_Icon::PLAIN);
icon->load_image("/usr/dt/appconfig/icons/C/Dtdata.m.pm");
icon = new Fl_File_Icon("*", Fl_File_Icon::DIRECTORY);
icon->load_image("/usr/dt/appconfig/icons/C/DtdirB.m.pm");
icon = new Fl_File_Icon("core", Fl_File_Icon::PLAIN);
icon->load_image("/usr/dt/appconfig/icons/C/Dtcore.m.pm");
icon = new Fl_File_Icon("*.{bmp|bw|gif|jpg|pbm|pcd|pgm|ppm|png|ras|rgb|tif|xbm|xpm}", Fl_File_Icon::PLAIN);
icon->load_image("/usr/dt/appconfig/icons/C/Dtimage.m.pm");
icon = new Fl_File_Icon("*.{eps|pdf|ps}", Fl_File_Icon::PLAIN);
icon->load_image("/usr/dt/appconfig/icons/C/Dtps.m.pm");
icon = new Fl_File_Icon("*.ppd", Fl_File_Icon::PLAIN);
icon->load_image("/usr/dt/appconfig/icons/C/DtPrtpr.m.pm");
} else if (!fl_access("/usr/lib/filetype", F_OK)) {
// Load SGI icons...
icon = new Fl_File_Icon("*", Fl_File_Icon::PLAIN);
icon->load_fti("/usr/lib/filetype/iconlib/generic.doc.fti");
icon = new Fl_File_Icon("*", Fl_File_Icon::DIRECTORY);
icon->load_fti("/usr/lib/filetype/iconlib/generic.folder.closed.fti");
icon = new Fl_File_Icon("core", Fl_File_Icon::PLAIN);
icon->load_fti("/usr/lib/filetype/default/iconlib/CoreFile.fti");
icon = new Fl_File_Icon("*.{bmp|bw|gif|jpg|pbm|pcd|pgm|ppm|png|ras|rgb|tif|xbm|xpm}", Fl_File_Icon::PLAIN);
icon->load_fti("/usr/lib/filetype/system/iconlib/ImageFile.fti");
if (!fl_access("/usr/lib/filetype/install/iconlib/acroread.doc.fti", F_OK)) {
icon = new Fl_File_Icon("*.{eps|ps}", Fl_File_Icon::PLAIN);
icon->load_fti("/usr/lib/filetype/system/iconlib/PostScriptFile.closed.fti");
icon = new Fl_File_Icon("*.pdf", Fl_File_Icon::PLAIN);
icon->load_fti("/usr/lib/filetype/install/iconlib/acroread.doc.fti");
} else {
icon = new Fl_File_Icon("*.{eps|pdf|ps}", Fl_File_Icon::PLAIN);
icon->load_fti("/usr/lib/filetype/system/iconlib/PostScriptFile.closed.fti");
}
if (!fl_access("/usr/lib/filetype/install/iconlib/html.fti", F_OK)) {
icon = new Fl_File_Icon("*.{htm|html|shtml}", Fl_File_Icon::PLAIN);
icon->load_fti("/usr/lib/filetype/iconlib/generic.doc.fti");
icon->load_fti("/usr/lib/filetype/install/iconlib/html.fti");
}
if (!fl_access("/usr/lib/filetype/install/iconlib/color.ps.idle.fti", F_OK)) {
icon = new Fl_File_Icon("*.ppd", Fl_File_Icon::PLAIN);
icon->load_fti("/usr/lib/filetype/install/iconlib/color.ps.idle.fti");
}
} else {
// Create the default icons...
new Fl_File_Icon("*", Fl_File_Icon::PLAIN, sizeof(plain) / sizeof(plain[0]), plain);
new Fl_File_Icon("*.{bm|bmp|bw|gif|jpg|pbm|pcd|pgm|ppm|png|ras|rgb|tif|xbm|xpm}", Fl_File_Icon::PLAIN,
sizeof(image) / sizeof(image[0]), image);
new Fl_File_Icon("*", Fl_File_Icon::DIRECTORY, sizeof(dir) / sizeof(dir[0]), dir);
}
// Mark things as initialized...
init = 1;
#ifdef DEBUG
int count;
Fl_File_Icon *temp;
for (count = 0, temp = first_; temp; temp = temp->next_, count ++);
printf("count of Fl_File_Icon's is %d...\n", count);
#endif // DEBUG
}
}
//
// 'load_kde_icons()' - Load KDE icon files.
//
static void
load_kde_icons(const char *directory, // I - Directory to load
const char *icondir) { // I - Location of icons
int i; // Looping var
int n; // Number of entries in directory
dirent **entries; // Entries in directory
char full[FL_PATH_MAX]; // Full name of file
entries = (dirent **)0;
n = fl_filename_list(directory, &entries);
for (i = 0; i < n; i ++) {
if (entries[i]->d_name[0] != '.') {
snprintf(full, sizeof(full), "%s/%s", directory, entries[i]->d_name);
if (fl_filename_isdir(full)) load_kde_icons(full, icondir);
else load_kde_mimelnk(full, icondir);
}
free((void *)entries[i]);
}
free((void*)entries);
}
//
// 'load_kde_mimelnk()' - Load a KDE "mimelnk" file.
//
static void
load_kde_mimelnk(const char *filename, // I - mimelnk filename
const char *icondir) { // I - Location of icons
FILE *fp;
char tmp[1024];
char iconfilename[FL_PATH_MAX];
char pattern[1024];
char mimetype[1024];
char *val;
char full_iconfilename[2 * FL_PATH_MAX];
Fl_File_Icon *icon;
mimetype[0] = '\0';
pattern[0] = '\0';
iconfilename[0] = '\0';
if ((fp = fl_fopen(filename, "rb")) != NULL) {
while (fgets(tmp, sizeof(tmp), fp)) {
if ((val = get_kde_val(tmp, "Icon")) != NULL)
strlcpy(iconfilename, val, sizeof(iconfilename));
else if ((val = get_kde_val(tmp, "MimeType")) != NULL)
strlcpy(mimetype, val, sizeof(mimetype));
else if ((val = get_kde_val(tmp, "Patterns")) != NULL)
strlcpy(pattern, val, sizeof(pattern));
}
fclose(fp);
#ifdef DEBUG
printf("%s: Icon=\"%s\", MimeType=\"%s\", Patterns=\"%s\"\n", filename,
iconfilename, mimetype, pattern);
#endif // DEBUG
if (!pattern[0] && strncmp(mimetype, "inode/", 6)) return;
if (iconfilename[0]) {
if (iconfilename[0] == '/') {
strlcpy(full_iconfilename, iconfilename, sizeof(full_iconfilename));
} else if (!fl_access(icondir, F_OK)) {
// KDE 3.x and 2.x icons
int i; // Looping var
static const char *paths[] = { // Subdirs to look in...
"16x16/actions",
"16x16/apps",
"16x16/devices",
"16x16/filesystems",
"16x16/mimetypes",
/*
"20x20/actions",
"20x20/apps",
"20x20/devices",
"20x20/filesystems",
"20x20/mimetypes",
"22x22/actions",
"22x22/apps",
"22x22/devices",
"22x22/filesystems",
"22x22/mimetypes",
"24x24/actions",
"24x24/apps",
"24x24/devices",
"24x24/filesystems",
"24x24/mimetypes",
*/
"32x32/actions",
"32x32/apps",
"32x32/devices",
"32x32/filesystems",
"32x32/mimetypes",
/*
"36x36/actions",
"36x36/apps",
"36x36/devices",
"36x36/filesystems",
"36x36/mimetypes",
"48x48/actions",
"48x48/apps",
"48x48/devices",
"48x48/filesystems",
"48x48/mimetypes",
"64x64/actions",
"64x64/apps",
"64x64/devices",
"64x64/filesystems",
"64x64/mimetypes",
"96x96/actions",
"96x96/apps",
"96x96/devices",
"96x96/filesystems",
"96x96/mimetypes"
*/ };
for (i = 0; i < (int)(sizeof(paths) / sizeof(paths[0])); i ++) {
snprintf(full_iconfilename, sizeof(full_iconfilename),
"%s/%s/%s.png", icondir, paths[i], iconfilename);
if (!fl_access(full_iconfilename, F_OK)) break;
}
if (i >= (int)(sizeof(paths) / sizeof(paths[0]))) return;
} else {
// KDE 1.x icons
snprintf(full_iconfilename, sizeof(full_iconfilename),
"%s/%s", tmp, iconfilename);
if (fl_access(full_iconfilename, F_OK)) return;
}
if (strncmp(mimetype, "inode/", 6) == 0) {
if (!strcmp(mimetype + 6, "directory"))
icon = new Fl_File_Icon("*", Fl_File_Icon::DIRECTORY);
else if (!strcmp(mimetype + 6, "blockdevice"))
icon = new Fl_File_Icon("*", Fl_File_Icon::DEVICE);
else if (!strcmp(mimetype + 6, "fifo"))
icon = new Fl_File_Icon("*", Fl_File_Icon::FIFO);
else return;
} else {
icon = new Fl_File_Icon(kde_to_fltk_pattern(pattern),
Fl_File_Icon::PLAIN);
}
icon->load(full_iconfilename);
}
}
}
//
// 'kde_to_fltk_pattern()' - Convert a KDE pattern to a FLTK pattern.
//
static char *
kde_to_fltk_pattern(const char *kdepattern) {
char *pattern,
*patptr;
pattern = (char *)malloc(strlen(kdepattern) + 3);
strcpy(pattern, "{");
strcpy(pattern + 1, kdepattern);
if (pattern[strlen(pattern) - 1] == ';') pattern[strlen(pattern) - 1] = '\0';
strcat(pattern, "}");
for (patptr = pattern; *patptr; patptr ++) {
if (*patptr == ';') *patptr = '|';
}
return (pattern);
}
//
// 'get_kde_val()' - Get a KDE value.
//
static char *
get_kde_val(char *str,
const char *key) {
while (*str == *key) {
str ++;
key ++;
}
if (*key == '\0' && *str == '=') {
if (str[strlen(str) - 1] == '\n') str[strlen(str) - 1] = '\0';
return (str + 1);
}
return ((char *)0);
}