34d0565b447abe07bfc4605d409ca1f97a2d2f4b
[supertux.git] / src / level_subset.cpp
1 //  $Id$
2 // 
3 //  SuperTux
4 //  Copyright (C) 2004 SuperTux Development Team, see AUTHORS for details
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 // 
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 //  02111-1307, USA.
20
21 #include <assert.h>
22 #include <unistd.h>
23 #include "app/setup.h"
24 #include "level.h"
25 #include "app/globals.h"
26 #include "video/surface.h"
27 #include "level_subset.h"
28
29 using namespace SuperTux;
30
31 static bool has_suffix(const std::string& data, const std::string& suffix)
32 {
33   if (data.length() >= suffix.length())
34     return data.compare(data.length() - suffix.length(), suffix.length(), suffix) == 0;
35   else
36     return false;
37 }
38
39 LevelSubset::LevelSubset()
40   : levels(0)
41 {
42 }
43
44 LevelSubset::~LevelSubset()
45 {
46 }
47
48 void LevelSubset::create(const std::string& subset_name)
49 {
50   Level new_lev;
51   LevelSubset new_subset;
52   new_subset.name = subset_name;
53   new_subset.title = "Unknown Title";
54   new_subset.description = "No description so far.";
55   new_subset.hide_from_contribs = false;
56   new_subset.save();
57 }
58
59 void LevelSubset::read_info_file(const std::string& info_file)
60 {
61   lisp_object_t* root_obj = lisp_read_from_file(info_file);
62   if (root_obj == NULL)
63     return;
64   lisp_object_t* cur = lisp_car(root_obj);
65
66   if (lisp_symbol_p(cur) && strcmp(lisp_symbol(cur), "supertux-level-subset") == 0)
67     {
68       LispReader reader(lisp_cdr(root_obj));
69
70       reader.read_string("title", title, true);
71       reader.read_string("description", description, true);
72       reader.read_string_vector("levels", levels);
73       hide_from_contribs = false;
74       reader.read_bool("hide-from-contribs", hide_from_contribs);
75     }
76   else
77     {
78       std::cout << "LevelSubset: parse error in info file: " << info_file << std::endl;
79     }
80
81   lisp_free(root_obj);
82 }
83
84 void LevelSubset::load(const std::string& subset)
85 {
86   name = subset;
87   
88   // Check in which directory our subset is located (ie. ~/.supertux/
89   // or SUPERTUX_DATADIR)
90   std::string filename;
91   filename = st_dir + "/levels/" + subset + "/";
92   if (access(filename.c_str(), R_OK) == 0)
93     {
94       directory = filename;
95     }
96   else
97     {
98       filename = datadir + "/levels/" + subset + "/";
99       if (access(filename.c_str(), R_OK) == 0)
100         directory = filename;
101       else
102         std::cout << "Error: LevelSubset: couldn't find subset: " << subset << std::endl;
103     }
104   
105   read_info_file(directory + "info");
106
107   if (levels.empty())
108     { // Level info file doesn't define any levels, so read the
109       // directory to see what we can find
110       std::set<std::string> files;
111   
112       filename = st_dir + "/levels/" + subset + "/";
113       if(access(filename.c_str(), R_OK) == 0)
114         {
115           files = FileSystem::read_directory(filename);
116         }
117       else
118         {
119           filename = datadir + "/levels/" + subset + "/";
120           files = FileSystem::read_directory(filename);
121         }
122   
123       for(std::set<std::string>::iterator i = files.begin(); i != files.end(); ++i)
124         {
125           if (has_suffix(*i, ".stl"))
126             levels.push_back(*i);
127         }
128     }
129 }
130
131 void
132 LevelSubset::save()
133 {
134   FILE* fi;
135   std::string filename;
136
137   /* Save data file: */
138   filename = "/levels/" + name + "/";
139
140   FileSystem::fcreatedir(filename.c_str());
141   filename = std::string(st_dir) + "/levels/" + name + "/info";
142   if(!FileSystem::fwriteable(filename.c_str()))
143     filename = datadir + "/levels/" + name + "/info";
144   if(FileSystem::fwriteable(filename.c_str()))
145     {
146       fi = fopen(filename.c_str(), "w");
147       if (fi == NULL)
148         {
149           perror(filename.c_str());
150         }
151
152       /* Write header: */
153       fprintf(fi,";; SuperTux-Level-Subset\n");
154       fprintf(fi,"(supertux-level-subset\n");
155
156       /* Save title info: */
157       fprintf(fi,"  (title \"%s\")\n", title.c_str());
158
159       /* Save the description: */
160       fprintf(fi,"  (description \"%s\")\n", description.c_str());
161
162       /* Save the hide from Contrbis menu boolean: */
163       fprintf(fi,"  (hide-from-contribs \"%s\")\n", hide_from_contribs ? "#t" : "#f");
164
165       fprintf( fi,")");
166       fclose(fi);
167     }
168 }
169
170 void
171 LevelSubset::add_level(const std::string& name)
172 {
173   levels.push_back(name);
174 }
175
176 std::string
177 LevelSubset::get_level_filename(unsigned int num)
178 {
179   assert(num < levels.size());
180   return directory + levels[num];
181 }
182
183 int
184 LevelSubset::get_num_levels() const
185 {
186   return levels.size();
187 }
188
189 /* EOF */