Commit | Line | Data |
---|---|---|
fac14bbe MW |
1 | /* Copyright (c) 2006 by Arkkra Enterprises */ |
2 | /* All rights reserved */ | |
3 | ||
4 | // This file contains code for defining and using things | |
5 | // related to user configuration settings and preferences. | |
6 | ||
7 | #include <stdio.h> | |
8 | #include <string.h> | |
9 | #include <unistd.h> | |
10 | #include "globals.H" | |
11 | #include "utils.H" | |
12 | #include "Preferences.H" | |
13 | #include <FL/filename.H> | |
14 | ||
15 | // Access to the user preferences file | |
16 | Fl_Preferences * Preferences_p; | |
17 | ||
18 | // Preference names and default values | |
19 | const char * const Editor_font_preference = "editor_font"; | |
20 | const char * const Default_editor_font = "Courier"; | |
21 | ||
22 | const char * const Editor_size_preference = "editor_size"; | |
23 | const char * const Default_editor_size = "12"; | |
24 | ||
25 | const char * const Auto_display_preference = "auto_display"; | |
26 | const int Default_auto_display = 0; | |
27 | ||
28 | const char * const Auto_save_preference = "auto_save"; | |
29 | const int Default_auto_save = 1; | |
30 | ||
31 | const char * const Tooltips_delay_preference = "tooltips_delay"; | |
32 | const double Default_tooltips_delay = 1.0; | |
33 | ||
34 | const char * const Mup_program_location = "Mup_program"; | |
35 | const char * const Default_Mup_program_location = "mup"; | |
36 | ||
37 | const char * const Mup_documentation_location = "Mup_documentation"; | |
38 | #if defined(__WIN32) | |
39 | const char * const Default_Mup_documentation_location = "c:\\Program Files\\mupmate"; | |
40 | #else | |
41 | const char * const Default_Mup_documentation_location = "/usr/share/doc/packages/mup"; | |
42 | #endif | |
43 | ||
44 | const char * const Music_files_location = "Music_folder"; | |
45 | const char * const Default_music_files_location = "."; | |
46 | ||
47 | const char * const MUPPATH_location = "MUPPATH"; | |
48 | const char * const Default_MUPPATH_location = "."; | |
49 | ||
50 | const char * const Viewer_location = "Viewer"; | |
51 | #if defined(__WIN32) | |
52 | const char * const Default_viewer_location = "c:\\Program Files\\Ghostgum\\gsview\\gsview32.exe"; | |
53 | #else | |
54 | const char * const Default_viewer_location = "gv"; | |
55 | #endif | |
56 | ||
57 | const char * const MIDI_player_location = "MIDI_player"; | |
58 | #if defined(__WIN32) | |
59 | const char * const Default_MIDI_player_location = "c:\\Program Files\\Windows Media Player\\wmplayer.exe"; | |
60 | #else | |
61 | const char * const Default_MIDI_player_location = "xplaymidi"; | |
62 | #endif | |
63 | ||
64 | const char * const Showed_startup_hints = "showed_startup_hints"; | |
65 | const int Default_startup_hints_flag = 0; | |
66 | ||
67 | // Name of User's Guide directory and index file | |
68 | // relative to Mup documentation directory. | |
69 | const char * uguide_directory = "uguide"; | |
70 | #ifdef OS_LIKE_WIN32 | |
71 | const char * uguide_filename = "index.htm"; | |
72 | #else | |
73 | const char * uguide_filename = "index.html"; | |
74 | #endif | |
75 | ||
76 | // Don't use un-readable tiny font, but especially avoid size of zero, | |
77 | // which could happen if preferences file contains a bad number, so that | |
78 | // atoi() returns zero. Keep max small enough to fit reasonable number | |
79 | // of characters in a window. | |
80 | const unsigned char Min_size = 5; | |
81 | const unsigned char Max_size = 30; | |
82 | ||
83 | // Minimum and default sizes for Main and Help browser windows. | |
84 | const int Min_width = 600; | |
85 | const int Default_width = 720; | |
86 | const int Min_height = 400; | |
87 | const int Default_height = 480; | |
88 | ||
89 | ||
90 | // If user hasn't specified any program yet to use for PostScript viewer | |
91 | // and/or MIDI file player, we try to deduce what they have available | |
92 | // that could be used, and set one of those as the default. | |
93 | ||
94 | // List of likely programs to use as PostScript viewers | |
95 | static const char * const viewer_candidates[] = { | |
96 | #if defined(__WIN32) | |
97 | "GSview32", | |
98 | "GSview", | |
99 | #else | |
100 | #ifdef OS_LIKE_UNIX | |
101 | "gv", | |
102 | "ghostview", | |
103 | #endif | |
104 | #endif | |
105 | 0 | |
106 | }; | |
107 | ||
108 | // List of likely programs to use as MIDI file players | |
109 | static const char * const player_candidates[] = { | |
110 | #if defined(__WIN32) | |
111 | "wmplayer", | |
112 | "mplayer", | |
113 | #else | |
114 | #ifdef OS_LIKE_UNIX | |
115 | "xplaymidi", | |
116 | "timidity", | |
117 | "pmidi", | |
118 | "playmidi", | |
119 | #endif | |
120 | #endif | |
121 | 0 | |
122 | }; | |
123 | ||
124 | ||
125 | // If the default preference value for a program location is no good, | |
126 | // try to find where it is. | |
127 | // pgm_location = the preference name of the program of interest | |
128 | // default_location = the default path to the program | |
129 | // file_suffix = .ps or .mod or .mup | |
130 | // Returns true if the preference value was updated. | |
131 | ||
132 | static bool | |
133 | deduce_location(const char * pgm_location, const char * default_location, | |
134 | const char * file_suffix, const char * const * candidates) | |
135 | { | |
136 | char * place; // a path to try for finding the pgm | |
137 | char location[FL_PATH_MAX]; // full path to pgm when it is found | |
138 | ||
139 | if (Preferences_p->get(pgm_location, place, default_location) != 0) { | |
140 | // There was a value already set. Make sure it is good. | |
141 | if (find_executable(place, location)) { | |
142 | if (strcmp(place, location) != 0) { | |
143 | // Must have started as relative path | |
144 | // and now we know the full path. | |
145 | (void) Preferences_p->set(pgm_location, location); | |
146 | return(true); | |
147 | } | |
148 | else { | |
149 | // Existing setting was okay as is. | |
150 | return(false); | |
151 | } | |
152 | } | |
153 | } | |
154 | ||
155 | #ifdef OS_LIKE_WIN32 | |
156 | // Try looking in the registry for what to use for | |
157 | // files of this type. | |
158 | if ((place = lookup_pgm_for_file_suffix(file_suffix)) != 0) { | |
159 | (void) Preferences_p->set(place, default_location); | |
160 | return(true); | |
161 | } | |
162 | #endif | |
163 | ||
164 | // If there had been nothing set, see if the default location is good. | |
165 | if (find_executable(default_location, location)) { | |
166 | (void) Preferences_p->set(pgm_location, location); | |
167 | return(true); | |
168 | } | |
169 | ||
170 | // Try looking in the various educated guess locations. | |
171 | if (candidates != 0) { | |
172 | int i; | |
173 | for (i = 0; candidates[i] != 0; i++) { | |
174 | if (find_executable(candidates[i], location)) { | |
175 | (void) Preferences_p->set(pgm_location, location); | |
176 | return(true); | |
177 | } | |
178 | } | |
179 | } | |
180 | ||
181 | return(false); | |
182 | } | |
183 | ||
184 | ||
185 | // Returns true is the Mup User's Guide can be found at the given location. | |
186 | ||
187 | static bool | |
188 | doc_found(const char * location) | |
189 | { | |
190 | return(access(users_guide_index_file(location), F_OK) == 0); | |
191 | } | |
192 | ||
193 | ||
194 | // Try to deduce where the Mup documentation is. | |
195 | // Returns true if updated the Preferences to point to new location. | |
196 | ||
197 | static bool | |
198 | deduce_documentation_location(const char * doc_location, const char * default_doc_location) | |
199 | { | |
200 | char * place; | |
201 | // First try the stored location, if any | |
202 | if (Preferences_p->get(doc_location, place, default_doc_location) != 0) { | |
203 | if (doc_found(place)) { | |
204 | // Existing preference is good. No update needed. | |
205 | return(false); | |
206 | } | |
207 | } | |
208 | ||
209 | // Try default location | |
210 | if (doc_found(default_doc_location)) { | |
211 | Preferences_p->set(doc_location, default_doc_location); | |
212 | return(true); | |
213 | } | |
214 | ||
215 | // Try relative to where Mup executable is. | |
216 | char *muploc; | |
217 | (void) Preferences_p->get(Mup_program_location, muploc, | |
218 | Default_Mup_program_location); | |
219 | char * basename_p; | |
220 | if ((basename_p = strrchr(muploc, dir_separator())) != 0) { | |
221 | int len = basename_p - muploc; | |
222 | char mupdir[len + 1]; | |
223 | (void) strncpy(mupdir, muploc, len); | |
224 | mupdir[len] = '\0'; | |
225 | if (doc_found(mupdir)) { | |
226 | Preferences_p->set(doc_location, mupdir); | |
227 | return(true); | |
228 | } | |
229 | ||
230 | // Try at ../docs from where mup executable was, | |
231 | // since it could be there from unpacking tar file. | |
232 | char * parentdir_p; | |
233 | if ((parentdir_p = strrchr(mupdir, dir_separator())) != 0) { | |
234 | len = parentdir_p - mupdir + 1; | |
235 | // Add room for doc and terminator | |
236 | char mupdocdir[len + 5]; | |
237 | (void) strncpy(mupdocdir, muploc, len); | |
238 | (void) strcpy(mupdocdir + len, "docs"); | |
239 | if (doc_found(mupdocdir)) { | |
240 | Preferences_p->set(doc_location, mupdocdir); | |
241 | return(true); | |
242 | } | |
243 | } | |
244 | } | |
245 | return(false); | |
246 | } | |
247 | ||
248 | ||
249 | // This function attempts to find the locations of what we need, | |
250 | // like a PostScript viewer and MIDI player. | |
251 | ||
252 | void | |
253 | deduce_helper_locations(void) | |
254 | { | |
255 | bool updated = false; | |
256 | ||
257 | // First try to find a PostScript viewer | |
258 | if (deduce_location(Viewer_location, Default_viewer_location, ".ps", | |
259 | viewer_candidates)) { | |
260 | updated = true; | |
261 | } | |
262 | ||
263 | // Next do MIDI player | |
264 | if (deduce_location(MIDI_player_location, Default_MIDI_player_location, | |
265 | ".mid", player_candidates)) { | |
266 | updated = true; | |
267 | } | |
268 | ||
269 | // Find the Mup command itself | |
270 | if (deduce_location(Mup_program_location, Default_Mup_program_location, ".mup", 0)) { | |
271 | updated = true; | |
272 | } | |
273 | ||
274 | if (deduce_documentation_location(Mup_documentation_location, | |
275 | Default_Mup_documentation_location)) { | |
276 | updated = true; | |
277 | } | |
278 | ||
279 | #ifdef OS_LIKE_WIN32 | |
280 | // Try to guess a good default place for Mup input files. | |
281 | char * place; | |
282 | if (Preferences_p->get(Music_files_location, place, | |
283 | Default_music_files_location) == 0) { | |
284 | if ((place = find_music_folder()) != 0) { | |
285 | Preferences_p->set(Music_files_location, place); | |
286 | updated = true; | |
287 | } | |
288 | } | |
289 | // The same place is probably a good guess for Mup include files. | |
290 | if (Preferences_p->get(MUPPATH_location, place, | |
291 | Default_MUPPATH_location) == 0) { | |
292 | if ((place = find_music_folder()) != 0) { | |
293 | Preferences_p->set(MUPPATH_location, place); | |
294 | updated = true; | |
295 | } | |
296 | } | |
297 | #endif | |
298 | ||
299 | // If at least one better choice was found, update the persistent data. | |
300 | if (updated) { | |
301 | Preferences_p->flush(); | |
302 | } | |
303 | } | |
304 | ||
305 | ||
306 | // Given a path to Mup's documentation directory, | |
307 | // add on the name of the User's Guide index file. | |
308 | // Return that in a static area. | |
309 | ||
310 | const char * | |
311 | users_guide_index_file(const char * const doc_dir) | |
312 | { | |
313 | static char file_path[FL_PATH_MAX]; | |
314 | (void) sprintf(file_path, "%s%c%s%c%s", doc_dir, dir_separator(), | |
315 | uguide_directory, dir_separator(), uguide_filename); | |
316 | return((const char *) file_path); | |
317 | } |