66 static bool __isroot; /* not very thread save, but will do in this case */ |
64 static bool __isroot; /* not very thread save, but will do in this case */ |
67 #define ISROOT(__p) (__isroot = (__p[strlen(__p)-1] == ':')) |
65 #define ISROOT(__p) (__isroot = (__p[strlen(__p)-1] == ':')) |
68 #define PATHTEMPLATE (__isroot ? "%s:%s" : "%s/%s") |
66 #define PATHTEMPLATE (__isroot ? "%s:%s" : "%s/%s") |
69 #endif |
67 #endif |
70 |
68 |
71 // Get a list of savegames |
69 bool FiosIsRoot(const char *path) |
72 FiosItem *FiosGetSavegameList(int *num, int mode) |
70 { |
73 { |
71 #if !defined(__MORPHOS__) && !defined(__AMIGAOS__) |
74 FiosItem *fios; |
72 return path[1] == '\0'; |
75 DIR *dir; |
73 #else |
76 struct dirent *dirent; |
74 /* On MorphOS or AmigaOS paths look like: "Volume:directory/subdirectory" */ |
77 struct stat sb; |
75 const char *s = strchr(path, ':'); |
78 int sort_start; |
76 return s[1] == '\0'; |
|
77 #endif |
|
78 } |
|
79 |
|
80 void FiosGetDrives(void) |
|
81 { |
|
82 return; |
|
83 } |
|
84 |
|
85 bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb) |
|
86 { |
79 char filename[MAX_PATH]; |
87 char filename[MAX_PATH]; |
80 |
88 |
81 if (_fios_save_path == NULL) { |
89 #if defined(__MORPHOS__) || defined(__AMIGAOS__) |
82 _fios_save_path = malloc(MAX_PATH); |
90 /* On MorphOS or AmigaOS paths look like: "Volume:directory/subdirectory" */ |
83 strcpy(_fios_save_path, _path.save_dir); |
91 if (FiosIsRoot(path)) { |
84 } |
92 snprintf(filename, lengthof(filename), "%s:%s", path, ent->d_name); |
85 |
93 } else // XXX - only next line! |
86 _fios_path = _fios_save_path; |
94 #endif |
87 |
95 snprintf(filename, lengthof(filename), "%s" PATHSEP "%s", path, ent->d_name); |
88 // Parent directory, only if not in root already. |
96 |
89 if (!ISROOT(_fios_path)) { |
97 if (stat(filename, sb) != 0) return false; |
90 fios = FiosAlloc(); |
98 |
91 fios->type = FIOS_TYPE_PARENT; |
99 return (ent->d_name[0] != '.'); // hidden file |
92 fios->mtime = 0; |
|
93 strcpy(fios->name, ".."); |
|
94 strcpy(fios->title, ".. (Parent directory)"); |
|
95 } |
|
96 |
|
97 // Show subdirectories first |
|
98 dir = opendir(_fios_path); |
|
99 if (dir != NULL) { |
|
100 while ((dirent = readdir(dir)) != NULL) { |
|
101 snprintf(filename, lengthof(filename), PATHTEMPLATE, |
|
102 _fios_path, dirent->d_name); |
|
103 if (!stat(filename, &sb) && S_ISDIR(sb.st_mode) && |
|
104 dirent->d_name[0] != '.') { |
|
105 fios = FiosAlloc(); |
|
106 fios->type = FIOS_TYPE_DIR; |
|
107 fios->mtime = 0; |
|
108 ttd_strlcpy(fios->name, dirent->d_name, lengthof(fios->name)); |
|
109 snprintf(fios->title, lengthof(fios->title), "%s/ (Directory)", FS2OTTD(dirent->d_name)); |
|
110 str_validate(fios->title); |
|
111 } |
|
112 } |
|
113 closedir(dir); |
|
114 } |
|
115 |
|
116 { |
|
117 /* XXX ugly global variables ... */ |
|
118 byte order = _savegame_sort_order; |
|
119 _savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING; |
|
120 qsort(_fios_items, _fios_count, sizeof(FiosItem), compare_FiosItems); |
|
121 _savegame_sort_order = order; |
|
122 } |
|
123 |
|
124 // this is where to start sorting |
|
125 sort_start = _fios_count; |
|
126 |
|
127 /* Show savegame files |
|
128 * .SAV OpenTTD saved game |
|
129 * .SS1 Transport Tycoon Deluxe preset game |
|
130 * .SV1 Transport Tycoon Deluxe (Patch) saved game |
|
131 * .SV2 Transport Tycoon Deluxe (Patch) saved 2-player game |
|
132 */ |
|
133 dir = opendir(_fios_path); |
|
134 if (dir != NULL) { |
|
135 while ((dirent = readdir(dir)) != NULL) { |
|
136 char *t; |
|
137 |
|
138 snprintf(filename, lengthof(filename), PATHTEMPLATE, |
|
139 _fios_path, dirent->d_name); |
|
140 if (stat(filename, &sb) || S_ISDIR(sb.st_mode)) continue; |
|
141 |
|
142 t = strrchr(dirent->d_name, '.'); |
|
143 if (t == NULL) continue; |
|
144 |
|
145 if (strcasecmp(t, ".sav") == 0) { // OpenTTD |
|
146 fios = FiosAlloc(); |
|
147 fios->type = FIOS_TYPE_FILE; |
|
148 fios->mtime = sb.st_mtime; |
|
149 ttd_strlcpy(fios->name, dirent->d_name, lengthof(fios->name)); |
|
150 |
|
151 *t = '\0'; // strip extension |
|
152 ttd_strlcpy(fios->title, FS2OTTD(dirent->d_name), lengthof(fios->title)); |
|
153 str_validate(fios->title); |
|
154 } else if (mode == SLD_LOAD_GAME || mode == SLD_LOAD_SCENARIO) { |
|
155 if (strcasecmp(t, ".ss1") == 0 || |
|
156 strcasecmp(t, ".sv1") == 0 || |
|
157 strcasecmp(t, ".sv2") == 0) { // TTDLX(Patch) |
|
158 fios = FiosAlloc(); |
|
159 fios->type = FIOS_TYPE_OLDFILE; |
|
160 fios->mtime = sb.st_mtime; |
|
161 ttd_strlcpy(fios->name, dirent->d_name, lengthof(fios->name)); |
|
162 GetOldSaveGameName(fios->title, filename); |
|
163 } |
|
164 } |
|
165 } |
|
166 closedir(dir); |
|
167 } |
|
168 |
|
169 qsort(_fios_items + sort_start, _fios_count - sort_start, sizeof(FiosItem), compare_FiosItems); |
|
170 *num = _fios_count; |
|
171 return _fios_items; |
|
172 } |
|
173 |
|
174 // Get a list of scenarios |
|
175 // FIXME: Gross code duplication with FiosGetSavegameList() |
|
176 FiosItem *FiosGetScenarioList(int *num, int mode) |
|
177 { |
|
178 FiosItem *fios; |
|
179 DIR *dir; |
|
180 struct dirent *dirent; |
|
181 struct stat sb; |
|
182 int sort_start; |
|
183 char filename[MAX_PATH]; |
|
184 |
|
185 if (_fios_scn_path == NULL) { |
|
186 _fios_scn_path = malloc(MAX_PATH); |
|
187 strcpy(_fios_scn_path, _path.scenario_dir); |
|
188 } |
|
189 |
|
190 _fios_path = _fios_scn_path; |
|
191 |
|
192 // Parent directory, only if not of the type C:\. |
|
193 if ((!ISROOT(_fios_path)) && mode != SLD_NEW_GAME) { |
|
194 fios = FiosAlloc(); |
|
195 fios->type = FIOS_TYPE_PARENT; |
|
196 fios->mtime = 0; |
|
197 strcpy(fios->title, ".. (Parent directory)"); |
|
198 } |
|
199 |
|
200 // Show subdirectories first |
|
201 dir = opendir(_fios_path); |
|
202 if (dir != NULL) { |
|
203 while ((dirent = readdir(dir)) != NULL) { |
|
204 snprintf(filename, lengthof(filename), PATHTEMPLATE, |
|
205 _fios_path, dirent->d_name); |
|
206 if (!stat(filename, &sb) && S_ISDIR(sb.st_mode) && |
|
207 dirent->d_name[0] != '.') { |
|
208 fios = FiosAlloc(); |
|
209 fios->type = FIOS_TYPE_DIR; |
|
210 fios->mtime = 0; |
|
211 ttd_strlcpy(fios->name, dirent->d_name, lengthof(fios->name)); |
|
212 snprintf(fios->title, lengthof(fios->title), "%s/ (Directory)", FS2OTTD(dirent->d_name)); |
|
213 str_validate(fios->title); |
|
214 } |
|
215 } |
|
216 closedir(dir); |
|
217 } |
|
218 |
|
219 { |
|
220 /* XXX ugly global variables ... */ |
|
221 byte order = _savegame_sort_order; |
|
222 _savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING; |
|
223 qsort(_fios_items, _fios_count, sizeof(FiosItem), compare_FiosItems); |
|
224 _savegame_sort_order = order; |
|
225 } |
|
226 |
|
227 // this is where to start sorting |
|
228 sort_start = _fios_count; |
|
229 |
|
230 /* Show scenario files |
|
231 * .SCN OpenTTD style scenario file |
|
232 * .SV0 Transport Tycoon Deluxe (Patch) scenario |
|
233 * .SS0 Transport Tycoon Deluxe preset scenario |
|
234 */ |
|
235 dir = opendir(_fios_path); |
|
236 if (dir != NULL) { |
|
237 while ((dirent = readdir(dir)) != NULL) { |
|
238 char *t; |
|
239 |
|
240 snprintf(filename, lengthof(filename), PATHTEMPLATE, _fios_path, dirent->d_name); |
|
241 if (stat(filename, &sb) || S_ISDIR(sb.st_mode)) continue; |
|
242 |
|
243 t = strrchr(dirent->d_name, '.'); |
|
244 if (t == NULL) continue; |
|
245 |
|
246 if (strcasecmp(t, ".scn") == 0) { // OpenTTD |
|
247 fios = FiosAlloc(); |
|
248 fios->type = FIOS_TYPE_SCENARIO; |
|
249 fios->mtime = sb.st_mtime; |
|
250 ttd_strlcpy(fios->name, dirent->d_name, lengthof(fios->name)); |
|
251 |
|
252 *t = '\0'; // strip extension |
|
253 ttd_strlcpy(fios->title, FS2OTTD(dirent->d_name), lengthof(fios->title)); |
|
254 str_validate(fios->title); |
|
255 } else if (mode == SLD_LOAD_GAME || mode == SLD_LOAD_SCENARIO || |
|
256 mode == SLD_NEW_GAME) { |
|
257 if (strcasecmp(t, ".sv0") == 0 || |
|
258 strcasecmp(t, ".ss0") == 0) { // TTDLX(Patch) |
|
259 fios = FiosAlloc(); |
|
260 fios->type = FIOS_TYPE_OLD_SCENARIO; |
|
261 fios->mtime = sb.st_mtime; |
|
262 GetOldScenarioGameName(fios->title, filename); |
|
263 ttd_strlcpy(fios->name, dirent->d_name, lengthof(fios->name)); |
|
264 } |
|
265 } |
|
266 } |
|
267 closedir(dir); |
|
268 } |
|
269 |
|
270 qsort(_fios_items + sort_start, _fios_count - sort_start, sizeof(FiosItem), compare_FiosItems); |
|
271 *num = _fios_count; |
|
272 return _fios_items; |
|
273 } |
100 } |
274 |
101 |
275 // Browse to |
102 // Browse to |
276 char *FiosBrowseTo(const FiosItem *item) |
103 char *FiosBrowseTo(const FiosItem *item) |
277 { |
104 { |