1 /********************************************************************************
2 *                                                                               *
3 *                        F i l e   A s s o c i a t i o n s                      *
4 *                                                                               *
5 *********************************************************************************
6 * Copyright (C) 1998,2020 by Jeroen van der Zijp.   All Rights Reserved.        *
7 *********************************************************************************
8 * This library is free software; you can redistribute it and/or modify          *
9 * it under the terms of the GNU Lesser General Public License as published by   *
10 * the Free Software Foundation; either version 3 of the License, or             *
11 * (at your option) any later version.                                           *
12 *                                                                               *
13 * This library is distributed in the hope that it will be useful,               *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of                *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                 *
16 * GNU Lesser General Public License for more details.                           *
17 *                                                                               *
18 * You should have received a copy of the GNU Lesser General Public License      *
19 * along with this program.  If not, see <http://www.gnu.org/licenses/>          *
20 ********************************************************************************/
21 #ifndef FXFILEASSOCIATIONS_H
22 #define FXFILEASSOCIATIONS_H
23 
24 #ifndef FXOBJECT_H
25 #include "FXObject.h"
26 #endif
27 
28 namespace FX {
29 
30 
31 class FXIcon;
32 class FXIconSource;
33 
34 
35 /// Registers stuff to know about the extension
36 struct FXFileAssoc {
37   FXString   command;           /// Command to execute
38   FXString   extension;         /// Full extension name
39   FXString   mimetype;          /// Mime type name
40   FXIcon    *bigicon;           /// Big normal icon
41   FXIcon    *bigiconopen;       /// Big open icon
42   FXIcon    *miniicon;          /// Mini normal icon
43   FXIcon    *miniiconopen;      /// Mini open icon
44   FXDragType dragtype;          /// Registered drag type
45   FXuint     flags;             /// Flags; 1=cd, 2=term
46   };
47 
48 
49 // Dictionary of file associations
50 typedef FXDictionaryOf<FXFileAssoc> FXFileAssocDictionary;
51 
52 
53 /**
54 * The FileAssociations object manages file associations between a file extension
55 * and a FileAssoc record which contains command name, mime-type, icons, and other
56 * information about a type of file.
57 * Icons referenced by the FileAssoc record are managed by an icon cache, which
58 * guarantees that each icon is loaded into memory only once, when it is encountered
59 * for the first time.
60 * Associations for a file or directory are determined by the information in the
61 * FOX Registry setting under the "FILETYPES" section.
62 * Each entry maps a (partial) pathname to an association record comprising command
63 * name, description, large and small icons, mime-types, and flags:
64 *
65 *   command ';' description ';' bigicon [ ':' bigiconopen ] ';' icon [ ':' iconopen ] ';' mime [ ';' flags ]
66 *
67 * For example, the binding for "bmp" would be:
68 *
69 *   [FILETYPES]
70 *   bmp="eog %s &;Bitmap Image;bigimage.bmp;miniimage.bmp;image/x-ms-bmp;"
71 *
72 * And bindings for directories would be like:
73 *
74 *   [FILETYPES]
75 *   /=";Root Folder;bigroot.bmp:bigroot_open.bmp;miniroot.bmp:miniroot_open.bmp;application/x-folder;"
76 *   /home/jane=";Home Folder;mansion.bmp:mansion_open.bmp;hut.bmp:hut_open.bmp;application/x-folder;"
77 *
78 * Three types of pathnames are distinguished: regular files, directories, and
79 * executable files.
80 * The association for a regular file name is determined by first looking at the entire
81 * file name, then at the whole extension, and then at sub-extensions.
82 * For example, "package.tar.gz", "tar.gz", and "gz" can each be given a different
83 * file associations.
84 * If no extension is found, then a special fallback extension "defaultfilebinding"
85 * is consulted.  Thus, you can assign fallback properties for all reguler files
86 * by setting the "defaultfilebinding" entry under the "FILETYPES" section.
87 * The association for a directory name is found by first checking the full pathname,
88 * then dropping leading directory components in turn.
89 * For example: "/usr/local/include", "/local/include", and "/include" are checked in
90 * turn.  This scheme allows convenient assignment of an association for projects with
91 * common directory-structures but different project roots.
92 * If a directory association is not found, a fallback association "defaultdirbinding"
93 * is used to determine the association.
94 * The association for an executable file is found by looking up the binding for the
95 * "defaultexecbinding" under the "FILETYPES" section.
96 * The flags field is used for a number of bit-flags; two flags are currently
97 * defined: 'cd' and 'term'.  The first one is intended to cause a launcher
98 * to execute the application in the shown directory; the second one is meant
99 * to indicate that the application is to be ran inside a new terminal.
100 */
101 class FXAPI FXFileAssociations : public FXObject {
102   FXDECLARE(FXFileAssociations)
103 protected:
104   FXFileAssocDictionary  bindings;      // File bindings dictionary
105   FXIconCache            cache;         // Cache icons for rapid access
106   FXSettings            *settings;      // Settings database for looking up extensions
107 protected:
108   FXFileAssociations();
109 private:
110   FXFileAssociations(const FXFileAssociations&);
111   FXFileAssociations &operator=(const FXFileAssociations&);
112 public:
113 
114   /// Registry key used to find fallback executable icons
115   static const FXchar defaultExecBinding[];
116 
117   /// Registry key used to find fallback directory icons
118   static const FXchar defaultDirBinding[];
119 
120   /// Registry key used to find fallback document icons
121   static const FXchar defaultFileBinding[];
122 
123 public:
124 
125   /**
126   * Construct a dictionary mapping file-extension to file associations,
127   * using the application registry settings as a source for the bindings.
128   * The pointer to the application class is passed down to the icon source
129   * which is inside the icon dictionary.
130   */
131   FXFileAssociations(FXApp* app);
132 
133   /**
134   * Construct a dictionary mapping file-extension to file associations,
135   * using the specified settings database as a source for the bindings.
136   * The pointer to the application class is passed down to the icon source
137   * which is inside the icon dictionary.
138   */
139   FXFileAssociations(FXApp* app,FXSettings* sdb);
140 
141   /**
142   * Change settings database being used to determine extension mappings.
143   */
setSettings(FXSettings * sdb)144   void setSettings(FXSettings* sdb){ settings=sdb; }
145 
146   /**
147   * Return settings database.
148   */
getSettings()149   FXSettings* getSettings() const { return settings; }
150 
151   /**
152   * Change the IconSource object used by the icon cache to load icons.
153   */
setIconSource(FXIconSource * src)154   void setIconSource(FXIconSource* src){ cache.setIconSource(src); }
155 
156   /**
157   * Return the current IconSource object.
158   */
getIconSource()159   FXIconSource* getIconSource() const { return cache.getIconSource(); }
160 
161   /**
162   * Set the icon search paths for the icon cache.
163   */
setIconPath(const FXString & path)164   void setIconPath(const FXString& path){ cache.setIconPath(path); }
165 
166   /**
167   * Return the current icon search paths from the icon cache.
168   */
getIconPath()169   const FXString& getIconPath() const { return cache.getIconPath(); }
170 
171   /**
172   * Parse string containing description of the association.
173   */
174   virtual FXFileAssoc* parse(const FXString& assoc);
175 
176   /**
177   * Return mapping of input string to file-association; if no mapping
178   * exists, try to add a new association mapping by consulting the
179   * FILETYPES section of the settings database.
180   * You can overload this function if you need to supply custom
181   * mappings for selected extensions.
182   */
183   virtual FXFileAssoc* fetch(const FXString& ext);
184 
185   /**
186   * Determine binding for the given file.
187   * The default implementation tries the whole filename first,
188   * then tries the extensions.
189   * For example, for a file "source.tar.gz":
190   *
191   *  "source.tar.gz",
192   *  "tar.gz",
193   *  "gz"
194   *
195   * are tried in succession.  If no association is found the
196   * key "defaultfilebinding" is tried as a fallback association.
197   * A NULL is returned if no association of any kind is found.
198   */
199   virtual FXFileAssoc* findFileBinding(const FXString& pathname);
200 
201   /**
202   * Find directory binding from registry.
203   * The default implementation tries the whole pathname first,
204   * then tries successively smaller parts of the path.
205   * For example, a pathname "/usr/people/jeroen":
206   *
207   *   "/usr/people/jeroen"
208   *   "/people/jeroen"
209   *   "/jeroen"
210   *
211   * are tried in succession.  If no bindings are found, the
212   * key "defaultdirbinding" is tried as a fallback association.
213   * A NULL is returned if no association of any kind is found.
214   */
215   virtual FXFileAssoc* findDirBinding(const FXString& pathname);
216 
217   /**
218   * Determine binding for the given executable.
219   * The default implementation returns the fallback binding associated with
220   * the key "defaultexecbinding".
221   * A NULL is returned if no association of any kind is found.
222   */
223   virtual FXFileAssoc* findExecBinding(const FXString& pathname);
224 
225   /**
226   * Delete all file-associations, and clear all icons from the cache.
227   */
228   void clear();
229 
230   /**
231   * Save object to stream.
232   */
233   virtual void save(FXStream& store) const;
234 
235   /**
236   * Load object from stream.
237   */
238   virtual void load(FXStream& store);
239 
240   /**
241   * Delete all FileAssoc's, and the IconCache.
242   */
243   virtual ~FXFileAssociations();
244   };
245 
246 }
247 
248 #endif
249