00001
00002
00003
00004
00005
00006
00007 #include "property.h"
00008 #include "fileUtils.h"
00009 #include <libxml/tree.h>
00010
00011
00012 Property::Property(void)
00013 : loaded_file(""), selected_index(0), pre_tag(BAD_CAST ""), user(NULL) {
00014
00015 sys.fullscreen = false;
00016 sys.user_index = 0;
00017 LIBXML_TEST_VERSION;
00018 }
00019
00020
00021 Property::~Property(void) {
00022 if (!loaded_file.empty()) {
00023 save();
00024 }
00025 }
00026
00027
00028 bool Property::readXMLLine(xml_t& xml, xmlTextReaderPtr reader) {
00029 xml.depth = -1;
00030 if (xmlTextReaderRead(reader) != 1) {
00031 return false;
00032 }
00033
00034 xml.type = xmlTextReaderNodeType(reader);
00035 if (xml.type == XML_READER_TYPE_END_ELEMENT) {
00036 pre_tag = BAD_CAST "";
00037 }
00038 xml.depth = xmlTextReaderDepth(reader);
00039
00040 const xmlChar* tag_name = xmlTextReaderConstName(reader);
00041 if (tag_name && (xml.type == XML_READER_TYPE_ELEMENT)) {
00042 xml.tag = tag_name;
00043 pre_tag = tag_name;
00044 } else {
00045 xml.tag = pre_tag;
00046 }
00047 const xmlChar* value_name = xmlTextReaderConstValue(reader);
00048 xml.value = (value_name) ? value_name : BAD_CAST "";
00049
00050 return true;
00051 }
00052
00053
00054 void Property::readSysInfo(xmlTextReaderPtr reader) {
00055 bool ret;
00056 xml_t xml;
00057 do {
00058 ret = readXMLLine(xml, reader);
00059
00060 if (xml.depth < 2) {
00061 continue;
00062 }
00063
00064 if (!xmlStrcmp(BAD_CAST "fullscreen", xml.tag)) {
00065
00066 sys.fullscreen = !xmlStrcmp(BAD_CAST "true", xml.value) ? true : false;
00067
00068 } else if (!xmlStrcmp(BAD_CAST "user_index", xml.tag)) {
00069
00070 selected_index = atoi((char*)(BAD_CAST xml.value));
00071 }
00072 } while (ret &&
00073 !((xml.depth < 2) && (xml.type == XML_READER_TYPE_END_ELEMENT)));
00074 }
00075
00076
00077 void Property::setUserIndex(unsigned int index) {
00078 sys.user_index = index;
00079 if (sys.user_index >= users.size()) {
00080 sys.user_index = 0;
00081 }
00082 user = &users[sys.user_index];
00083 }
00084
00085
00086 int Property::addUser(const char* name) {
00087 if (users.size() >= UserMax) {
00088 return UsersNumOver;
00089 }
00090
00091 if (strlen(name) <= 0) {
00092 return InvalidName;
00093 }
00094
00095 for (std::vector<userInfo_t>::iterator it = users.begin();
00096 it != users.end(); ++it) {
00097 if (!it->name.compare(name)) {
00098 return AlreadyExist;
00099 }
00100 }
00101
00102
00103 userInfo_t add;
00104 add.name = name;
00105
00106 bool empty = users.empty();
00107 users.push_back(add);
00108 if (empty) {
00109 setUserIndex(0);
00110 }
00111 return 0;
00112 }
00113
00114
00115 void Property::delUser(unsigned int index) {
00116 if (index >= users.size()) {
00117 return;
00118 }
00119 if (sys.user_index > index) {
00120 --sys.user_index;
00121 } else if (sys.user_index == index) {
00122 sys.user_index = 0;
00123 }
00124 users.erase(users.begin() + index);
00125 setUserIndex(sys.user_index);
00126 }
00127
00128
00129 void Property::readAllUserInfo(xmlTextReaderPtr reader) {
00130 bool ret;
00131 xml_t xml;
00132 do {
00133 userInfo_t add;
00134 bool added = false;
00135 do {
00136 ret = readXMLLine(xml, reader);
00137
00138
00139 if (!xmlStrcmp(BAD_CAST "name", xml.tag)) {
00140
00141 add.name = (char*)(xml.value);
00142 added = true;
00143
00144 } else if (!xmlStrcmp(BAD_CAST "practice_num", xml.tag)) {
00145
00146 add.practice_num = atoi((char*)(BAD_CAST xml.value));
00147
00148 } else if (!xmlStrcmp(BAD_CAST "roman_convert", xml.tag)) {
00149
00150 add.roman_convert = !xmlStrcmp(BAD_CAST "true", xml.value)? true:false;
00151
00152 } else if (!xmlStrcmp(BAD_CAST "auto_next", xml.tag)) {
00153
00154 add.auto_next = !xmlStrcmp(BAD_CAST "true", xml.value)? true : false;
00155
00156 } else if (!xmlStrcmp(BAD_CAST "learn_mode", xml.tag)) {
00157
00158 add.learn_mode = !xmlStrcmp(BAD_CAST "true", xml.value)? true : false;
00159
00160 } else if (!xmlStrcmp(BAD_CAST "send_ranking", xml.tag)) {
00161
00162 add.send_ranking = !xmlStrcmp(BAD_CAST "true", xml.value)? true :false;
00163
00164 } else if (!xmlStrcmp(BAD_CAST "rank_page", xml.tag)) {
00165
00166 add.rank_page = (char*)(xml.value);
00167 }
00168 } while (ret && (xml.depth >= 3));
00169 if (added) {
00170 users.push_back(add);
00171 }
00172 } while (ret &&
00173 !((xml.depth < 2) && (xml.type == XML_READER_TYPE_END_ELEMENT)));
00174 }
00175
00176
00177 bool Property::load(const char* file, const char* path[]) {
00178
00179
00180 std::string full_path = VXV::searchFile(file, path);
00181
00182
00183 if (full_path.size() <= 0) {
00184 int last_index = 0;
00185 while (path[last_index]) {
00186 ++last_index;
00187 }
00188 for (int i = last_index -1; i >= 0; --i) {
00189 if (VXV::createDirs(path[i]) < 0) {
00190 continue;
00191 }
00192 full_path = std::string(path[i]) + '/' + file;
00193 if (save(full_path.c_str())) {
00194 break;
00195 }
00196 }
00197 }
00198
00199 xmlTextReaderPtr reader = xmlReaderForFile(full_path.c_str(), NULL, 0);
00200 if (!reader) {
00201 xmlCleanupParser();
00202 return false;
00203 }
00204
00205 bool ret;
00206 do {
00207 xml_t xml;
00208 ret = readXMLLine(xml, reader);
00209 if ((xml.depth != 1) || ((xml.type != XML_READER_TYPE_ELEMENT) &&
00210 (xml.type != XML_READER_TYPE_TEXT))) {
00211 continue;
00212 }
00213 if (!xmlStrcmp(BAD_CAST "sys", xml.tag)) {
00214
00215 readSysInfo(reader);
00216
00217 } else if (!xmlStrcmp(BAD_CAST "users", xml.tag)) {
00218
00219 readAllUserInfo(reader);
00220 }
00221 } while (ret);
00222 setUserIndex(selected_index);
00223 xmlFreeTextReader(reader);
00224 xmlCleanupParser();
00225
00226 loaded_file = full_path;
00227 if (users.empty()) {
00228 addUser();
00229 }
00230 return true;
00231 }
00232
00233
00234 bool Property::save(const char* file) {
00235 std::string save_file = (file) ? file : loaded_file;
00236 if (!save_file[0]) {
00237 return false;
00238 }
00239
00240
00241 xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
00242 xmlNodePtr root_node = xmlNewNode(NULL, BAD_CAST "nettypingrc");
00243 xmlDocSetRootElement(doc, root_node);
00244
00245
00246 xmlNodePtr node = xmlNewChild(root_node, NULL, BAD_CAST "sys", NULL);
00247 xmlNewChild(node, NULL, BAD_CAST "fullscreen",
00248 sys.fullscreen ? BAD_CAST "true" : BAD_CAST "false");
00249 char num_str[] = "0";
00250 num_str[0] += sys.user_index;
00251 xmlNewChild(node, NULL, BAD_CAST "user_index", BAD_CAST num_str);
00252
00253
00254 xmlNodePtr user_node = xmlNewChild(root_node, NULL, BAD_CAST "users", NULL);
00255 for (std::vector<userInfo_t>::iterator it = users.begin();
00256 it != users.end(); ++it) {
00257
00258 node = xmlNewChild(user_node, NULL, BAD_CAST "user", NULL);
00259 xmlNewChild(node, NULL, BAD_CAST "name", BAD_CAST it->name.c_str());
00260
00261
00262 char nth[13];
00263 sprintf(nth, "%d", it->practice_num);
00264 xmlNewChild(node, NULL, BAD_CAST "practice_num", BAD_CAST nth);
00265
00266
00267 xmlNewChild(node, NULL, BAD_CAST "roman_convert",
00268 it->roman_convert ? BAD_CAST "true" : BAD_CAST "false");
00269
00270
00271 xmlNewChild(node, NULL, BAD_CAST "auto_next",
00272 it->auto_next ? BAD_CAST "true" : BAD_CAST "false");
00273
00274
00275 xmlNewChild(node, NULL, BAD_CAST "learn_mode",
00276 it->learn_mode ? BAD_CAST "true" : BAD_CAST "false");
00277
00278
00279 xmlNewChild(node, NULL, BAD_CAST "send_ranking",
00280 it->send_ranking ? BAD_CAST "true" : BAD_CAST "false");
00281
00282
00283 xmlNewChild(node, NULL, BAD_CAST "rank_page",
00284 BAD_CAST it->rank_page.c_str());
00285 }
00286 int ret = xmlSaveFormatFileEnc(save_file.c_str(), doc, "UTF-8", 1);
00287 xmlFreeDoc(doc);
00288 xmlCleanupParser();
00289
00290 return (ret < 0 ? false : true);
00291 }
00292