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.

493 lines
11KB

  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.
  14. //
  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.
  19. //
  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.
  24. //
  25. // Please report all bugs and problems on the following page:
  26. //
  27. // http://www.fltk.org/str.php
  28. //
  29. // Contents:
  30. //
  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.
  38. //
  39. //
  40. // Include necessary header files...
  41. //
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include <FL/fl_utf8.h>
  45. #include "flstring.h"
  46. #include <errno.h>
  47. #include <sys/types.h>
  48. #include <sys/stat.h>
  49. #if (defined(WIN32) && ! defined(__CYGWIN__)) || defined(__EMX__)
  50. # include <io.h>
  51. # define F_OK 0
  52. #else
  53. # include <unistd.h>
  54. #endif /* WIN32 || __EMX__ */
  55. #include <FL/Fl_File_Icon.H>
  56. #include <FL/Fl_Widget.H>
  57. #include <FL/fl_draw.H>
  58. #include <FL/filename.H>
  59. //
  60. // Define missing POSIX/XPG4 macros as needed...
  61. //
  62. #ifndef S_ISDIR
  63. # define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
  64. # define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
  65. # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
  66. # define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
  67. # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
  68. #endif /* !S_ISDIR */
  69. //
  70. // Icon cache...
  71. //
  72. Fl_File_Icon *Fl_File_Icon::first_ = (Fl_File_Icon *)0;
  73. /**
  74. Creates a new Fl_File_Icon with the specified information.
  75. \param[in] p filename pattern
  76. \param[in] t file type
  77. \param[in] nd number of data values
  78. \param[in] d data values
  79. */
  80. Fl_File_Icon::Fl_File_Icon(const char *p, /* I - Filename pattern */
  81. int t, /* I - File type */
  82. int nd, /* I - Number of data values */
  83. short *d) /* I - Data values */
  84. {
  85. // Initialize the pattern and type...
  86. pattern_ = p;
  87. type_ = t;
  88. // Copy icon data as needed...
  89. if (nd)
  90. {
  91. num_data_ = nd;
  92. alloc_data_ = nd + 1;
  93. data_ = (short *)calloc(sizeof(short), nd + 1);
  94. memcpy(data_, d, nd * sizeof(short));
  95. }
  96. else
  97. {
  98. num_data_ = 0;
  99. alloc_data_ = 0;
  100. }
  101. // And add the icon to the list of icons...
  102. next_ = first_;
  103. first_ = this;
  104. }
  105. /**
  106. The destructor destroys the icon and frees all memory that has been
  107. allocated for it.
  108. */
  109. Fl_File_Icon::~Fl_File_Icon() {
  110. Fl_File_Icon *current, // Current icon in list
  111. *prev; // Previous icon in list
  112. // Find the icon in the list...
  113. for (current = first_, prev = (Fl_File_Icon *)0;
  114. current != this && current != (Fl_File_Icon *)0;
  115. prev = current, current = current->next_);
  116. // Remove the icon from the list as needed...
  117. if (current)
  118. {
  119. if (prev)
  120. prev->next_ = current->next_;
  121. else
  122. first_ = current->next_;
  123. }
  124. // Free any memory used...
  125. if (alloc_data_)
  126. free(data_);
  127. }
  128. /**
  129. Adds a keyword value to the icon array, returning a pointer to it.
  130. \param[in] d data value
  131. */
  132. short * // O - Pointer to new data value
  133. Fl_File_Icon::add(short d) // I - Data to add
  134. {
  135. short *dptr; // Pointer to new data value
  136. // Allocate/reallocate memory as needed
  137. if ((num_data_ + 1) >= alloc_data_)
  138. {
  139. alloc_data_ += 128;
  140. if (alloc_data_ == 128)
  141. dptr = (short *)malloc(sizeof(short) * alloc_data_);
  142. else
  143. dptr = (short *)realloc(data_, sizeof(short) * alloc_data_);
  144. if (dptr == NULL)
  145. return (NULL);
  146. data_ = dptr;
  147. }
  148. // Store the new data value and return
  149. data_[num_data_++] = d;
  150. data_[num_data_] = END;
  151. return (data_ + num_data_ - 1);
  152. }
  153. /**
  154. Finds an icon that matches the given filename and file type.
  155. \param[in] filename name of file
  156. \param[in] filetype enumerated file type
  157. \return matching file icon or NULL
  158. */
  159. Fl_File_Icon * // O - Matching file icon or NULL
  160. Fl_File_Icon::find(const char *filename,// I - Name of file */
  161. int filetype) // I - Enumerated file type
  162. {
  163. Fl_File_Icon *current; // Current file in list
  164. #ifndef WIN32
  165. struct stat fileinfo; // Information on file
  166. #endif // !WIN32
  167. const char *name; // Base name of filename
  168. // Get file information if needed...
  169. if (filetype == ANY)
  170. {
  171. #ifdef WIN32
  172. if (filename[strlen(filename) - 1] == '/')
  173. filetype = DIRECTORY;
  174. else if (fl_filename_isdir(filename))
  175. filetype = DIRECTORY;
  176. else
  177. filetype = PLAIN;
  178. #else
  179. if (!fl_stat(filename, &fileinfo))
  180. {
  181. if (S_ISDIR(fileinfo.st_mode))
  182. filetype = DIRECTORY;
  183. # ifdef S_IFIFO
  184. else if (S_ISFIFO(fileinfo.st_mode))
  185. filetype = FIFO;
  186. # endif // S_IFIFO
  187. # if defined(S_ICHR) && defined(S_IBLK)
  188. else if (S_ISCHR(fileinfo.st_mode) || S_ISBLK(fileinfo.st_mode))
  189. filetype = DEVICE;
  190. # endif // S_ICHR && S_IBLK
  191. # ifdef S_ILNK
  192. else if (S_ISLNK(fileinfo.st_mode))
  193. filetype = LINK;
  194. # endif // S_ILNK
  195. else
  196. filetype = PLAIN;
  197. }
  198. else
  199. filetype = PLAIN;
  200. #endif // WIN32
  201. }
  202. // Look at the base name in the filename
  203. name = fl_filename_name(filename);
  204. // Loop through the available file types and return any match that
  205. // is found...
  206. for (current = first_; current != (Fl_File_Icon *)0; current = current->next_)
  207. if ((current->type_ == filetype || current->type_ == ANY) &&
  208. (fl_filename_match(filename, current->pattern_) ||
  209. fl_filename_match(name, current->pattern_)))
  210. break;
  211. // Return the match (if any)...
  212. return (current);
  213. }
  214. /**
  215. Draws an icon in the indicated area.
  216. \param[in] x, y, w, h position and size
  217. \param[in] ic icon color
  218. \param[in] active status, default is active [non-zero]
  219. */
  220. void
  221. Fl_File_Icon::draw(int x, // I - Upper-lefthand X
  222. int y, // I - Upper-lefthand Y
  223. int w, // I - Width of bounding box
  224. int h, // I - Height of bounding box
  225. Fl_Color ic, // I - Icon color...
  226. int active) // I - Active or inactive?
  227. {
  228. Fl_Color c, // Current color
  229. oc; // Outline color
  230. short *d, // Pointer to data
  231. *dend; // End of data...
  232. short *prim; // Pointer to start of primitive...
  233. double scale; // Scale of icon
  234. // Don't try to draw a NULL array!
  235. if (num_data_ == 0)
  236. return;
  237. // Setup the transform matrix as needed...
  238. scale = w < h ? w : h;
  239. fl_push_matrix();
  240. fl_translate((float)x + 0.5 * ((float)w - scale),
  241. (float)y + 0.5 * ((float)h + scale));
  242. fl_scale(scale, -scale);
  243. // Loop through the array until we see an unmatched END...
  244. d = data_;
  245. dend = data_ + num_data_;
  246. prim = NULL;
  247. c = ic;
  248. if (active)
  249. fl_color(c);
  250. else
  251. fl_color(fl_inactive(c));
  252. while (d < dend)
  253. switch (*d)
  254. {
  255. case END :
  256. if (prim)
  257. switch (*prim)
  258. {
  259. case LINE :
  260. fl_end_line();
  261. break;
  262. case CLOSEDLINE :
  263. fl_end_loop();
  264. break;
  265. case POLYGON :
  266. fl_end_complex_polygon();
  267. break;
  268. case OUTLINEPOLYGON :
  269. fl_end_complex_polygon();
  270. oc = (Fl_Color)((((unsigned short *)prim)[1] << 16) |
  271. ((unsigned short *)prim)[2]);
  272. if (active)
  273. {
  274. if (oc == FL_ICON_COLOR)
  275. fl_color(ic);
  276. else
  277. fl_color(oc);
  278. }
  279. else
  280. {
  281. if (oc == FL_ICON_COLOR)
  282. fl_color(fl_inactive(ic));
  283. else
  284. fl_color(fl_inactive(oc));
  285. }
  286. fl_begin_loop();
  287. prim += 3;
  288. while (*prim == VERTEX)
  289. {
  290. fl_vertex(prim[1] * 0.0001, prim[2] * 0.0001);
  291. prim += 3;
  292. }
  293. fl_end_loop();
  294. fl_color(c);
  295. break;
  296. }
  297. prim = NULL;
  298. d ++;
  299. break;
  300. case COLOR :
  301. c = (Fl_Color)((((unsigned short *)d)[1] << 16) |
  302. ((unsigned short *)d)[2]);
  303. if (c == FL_ICON_COLOR)
  304. c = ic;
  305. if (!active)
  306. c = fl_inactive(c);
  307. fl_color(c);
  308. d += 3;
  309. break;
  310. case LINE :
  311. prim = d;
  312. d ++;
  313. fl_begin_line();
  314. break;
  315. case CLOSEDLINE :
  316. prim = d;
  317. d ++;
  318. fl_begin_loop();
  319. break;
  320. case POLYGON :
  321. prim = d;
  322. d ++;
  323. fl_begin_complex_polygon();
  324. break;
  325. case OUTLINEPOLYGON :
  326. prim = d;
  327. d += 3;
  328. fl_begin_complex_polygon();
  329. break;
  330. case VERTEX :
  331. if (prim)
  332. fl_vertex(d[1] * 0.0001, d[2] * 0.0001);
  333. d += 3;
  334. break;
  335. default : // Ignore invalid data...
  336. d ++;
  337. }
  338. // If we still have an open primitive, close it...
  339. if (prim)
  340. switch (*prim)
  341. {
  342. case LINE :
  343. fl_end_line();
  344. break;
  345. case CLOSEDLINE :
  346. fl_end_loop();
  347. break;
  348. case POLYGON :
  349. fl_end_polygon();
  350. break;
  351. case OUTLINEPOLYGON :
  352. fl_end_polygon();
  353. oc = (Fl_Color)((((unsigned short *)prim)[1] << 16) |
  354. ((unsigned short *)prim)[2]);
  355. if (active)
  356. {
  357. if (oc == FL_ICON_COLOR)
  358. fl_color(ic);
  359. else
  360. fl_color(oc);
  361. }
  362. else
  363. {
  364. if (oc == FL_ICON_COLOR)
  365. fl_color(fl_inactive(ic));
  366. else
  367. fl_color(fl_inactive(oc));
  368. }
  369. fl_begin_loop();
  370. prim += 3;
  371. while (*prim == VERTEX)
  372. {
  373. fl_vertex(prim[1] * 0.0001, prim[2] * 0.0001);
  374. prim += 3;
  375. }
  376. fl_end_loop();
  377. fl_color(c);
  378. break;
  379. }
  380. // Restore the transform matrix
  381. fl_pop_matrix();
  382. }
  383. /**
  384. Applies the icon to the widget, registering the Fl_File_Icon
  385. label type as needed.
  386. \param[in] w widget for which this icon will become the label
  387. */
  388. void Fl_File_Icon::label(Fl_Widget *w) // I - Widget to label
  389. {
  390. Fl::set_labeltype(_FL_ICON_LABEL, labeltype, 0);
  391. w->label(_FL_ICON_LABEL, (const char*)this);
  392. }
  393. /**
  394. Draw the icon label.
  395. \param[in] o label data
  396. \param[in] x, y, w, h position and size of label
  397. \param[in] a label alignment [not used]
  398. */
  399. void
  400. Fl_File_Icon::labeltype(const Fl_Label *o, // I - Label data
  401. int x, // I - X position of label
  402. int y, // I - Y position of label
  403. int w, // I - Width of label
  404. int h, // I - Height of label
  405. Fl_Align a) // I - Label alignment (not used)
  406. {
  407. Fl_File_Icon *icon; // Pointer to icon data
  408. (void)a;
  409. icon = (Fl_File_Icon *)(o->value);
  410. if (icon) icon->draw(x, y, w, h, (Fl_Color)(o->color));
  411. }
  412. //
  413. // End of "$Id: Fl_File_Icon.cxx 7903 2010-11-28 21:06:39Z matt $".
  414. //