chiark / gitweb /
Import upstream version 5.3.
[mup] / mup / mupmate / Preferences.C
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 }