CConfigHandler.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. //#define BOOST_SPIRIT_DEBUG
  2. #include "CConfigHandler.h"
  3. #include <boost/bind.hpp>
  4. #include <boost/function.hpp>
  5. #if BOOST_VERSION >= 103800
  6. #include <boost/spirit/include/classic.hpp>
  7. #else
  8. #include <boost/spirit.hpp>
  9. #endif
  10. #include <fstream>
  11. using namespace config;
  12. using namespace boost::spirit;
  13. using namespace phoenix;
  14. /*
  15. * CConfigHandler.cpp, part of VCMI engine
  16. *
  17. * Authors: listed in file AUTHORS in main folder
  18. *
  19. * License: GNU General Public License v2.0 or later
  20. * Full text of license available in license.txt file, in main folder
  21. *
  22. */
  23. CConfigHandler conf;
  24. GUIOptions *current = NULL;
  25. std::pair<int,int> curRes;
  26. ButtonInfo *currentButton;
  27. int gnb=-1;
  28. struct lerror
  29. {
  30. std::string txt;
  31. lerror(const std::string & TXT):txt(TXT){};
  32. void operator()() const
  33. {
  34. tlog1 << txt << std::endl;
  35. }
  36. template<typename IteratorT>
  37. void operator()(IteratorT t1, IteratorT t2) const
  38. {
  39. tlog1 << txt << std::endl;
  40. }
  41. };
  42. struct SetCurButton
  43. {
  44. template<typename IteratorT>
  45. void operator()(IteratorT t1, IteratorT t2) const
  46. {
  47. std::string str(t1,t2);
  48. if(str=="KingdomOv")
  49. currentButton = &current->ac.kingOverview;
  50. else if(str=="Underground")
  51. currentButton = &current->ac.underground;
  52. else if(str=="QuestLog")
  53. currentButton = &current->ac.questlog;
  54. else if(str=="SleepWake")
  55. currentButton = &current->ac.sleepWake;
  56. else if(str=="MoveHero")
  57. currentButton = &current->ac.moveHero;
  58. else if(str=="Spellbook")
  59. currentButton = &current->ac.spellbook;
  60. else if(str=="AdvOptions")
  61. currentButton = &current->ac.advOptions;
  62. else if(str=="SysOptions")
  63. currentButton = &current->ac.sysOptions;
  64. else if(str=="NextHero")
  65. currentButton = &current->ac.nextHero;
  66. else if(str=="EndTurn")
  67. currentButton = &current->ac.endTurn;
  68. }
  69. };
  70. struct lerror2
  71. {
  72. std::string txt;
  73. lerror2(const std::string & TXT):txt(TXT){};
  74. template<typename IteratorT>
  75. void operator()(IteratorT t1, IteratorT t2) const
  76. {
  77. std::string txt2(t1,t2);
  78. tlog1 << txt << txt2 << std::endl;
  79. }
  80. };
  81. struct dummy
  82. {
  83. boost::function<void()> func;
  84. dummy(const boost::function<void()> & F)
  85. :func(F){}
  86. template<typename IteratorT>
  87. void operator()(IteratorT t1, IteratorT t2) const
  88. {
  89. func();
  90. }
  91. };
  92. template<typename T>struct SetButtonProp
  93. {
  94. T point;
  95. SetButtonProp(T p)
  96. :point(p){}
  97. template <typename Z>
  98. void operator()(const Z & val) const
  99. {
  100. currentButton->*point = val;
  101. }
  102. };
  103. template<typename T> SetButtonProp<T> SetButtonProp_a(T p)
  104. {
  105. return SetButtonProp<T>(p);
  106. }
  107. struct SetButtonStr
  108. {
  109. std::string ButtonInfo::*point;
  110. SetButtonStr(std::string ButtonInfo::* p)
  111. :point(p){}
  112. template <typename Z>
  113. void operator()(const Z first, const Z last) const
  114. {
  115. std::string str(first,last);
  116. currentButton->*point = str;
  117. }
  118. };
  119. template<typename T>struct SetAdventureProp
  120. {
  121. T point;
  122. SetAdventureProp(T p)
  123. :point(p){}
  124. template <typename Z>
  125. void operator()(const Z & val) const
  126. {
  127. current->ac.*point = val;
  128. }
  129. };
  130. template<typename T> SetAdventureProp<T> SetAdventureProp_a(T p)
  131. {
  132. return SetAdventureProp<T>(p);
  133. }
  134. struct SetAdventureStr
  135. {
  136. std::string AdventureMapConfig::*point;
  137. SetAdventureStr(std::string AdventureMapConfig::* p)
  138. :point(p){}
  139. template <typename Z>
  140. void operator()(const Z first, const Z last) const
  141. {
  142. std::string str(first,last);
  143. current->ac.*point = str;
  144. }
  145. };
  146. struct AddDefForButton
  147. {
  148. template <typename Z>
  149. void operator()(const Z first, const Z last) const
  150. {
  151. std::string str(first,last);
  152. currentButton->additionalDefs.push_back(str);
  153. }
  154. };
  155. struct ClearAdditionalDefs
  156. {
  157. template <typename Z>
  158. void operator()(const Z first, const Z last) const
  159. {
  160. currentButton->additionalDefs.clear();
  161. }
  162. };
  163. static void addGRes()
  164. {
  165. if(current)
  166. conf.guiOptions[curRes] = *current; //we'll use by default settings from previous resolution
  167. current = &conf.guiOptions[curRes];
  168. }
  169. static void setGem(int x, int val)
  170. {
  171. if(x)
  172. current->ac.gemX[gnb] = val;
  173. else
  174. current->ac.gemY[gnb] = val;
  175. }
  176. struct AddGemName
  177. {
  178. template <typename Z>
  179. void operator()(const Z first, const Z last) const
  180. {
  181. current->ac.gemG.push_back(std::string(first,last));
  182. }
  183. };
  184. struct SettingsGrammar : public grammar<SettingsGrammar>
  185. {
  186. template <typename ScannerT>
  187. struct definition
  188. {
  189. rule<ScannerT> r, clientOption, clientOptionsSequence, ClientSettings;
  190. rule<ScannerT> GUISettings, GUIOption, GUIOptionsSequence, AdvMapOptionsSequence, AdvMapOption;
  191. rule<ScannerT> GUIResolution, fname;
  192. definition(SettingsGrammar const& self)
  193. {
  194. fname = lexeme_d[+(alnum_p | '.')];
  195. clientOption
  196. = str_p("resolution=") >> (uint_p[assign_a(conf.cc.resx)] >> 'x' >> uint_p[assign_a(conf.cc.resy)] | eps_p[lerror("Wrong resolution!")])
  197. | str_p("pregameRes=") >> (uint_p[assign_a(conf.cc.pregameResx)] >> 'x' >> uint_p[assign_a(conf.cc.pregameResy)] | eps_p[lerror("Wrong pregame size!")])
  198. | str_p("screenSize=") >> (uint_p[assign_a(conf.cc.screenx)] >> 'x' >> uint_p[assign_a(conf.cc.screeny)] | eps_p[lerror("Wrong screen size!")])
  199. | str_p("port=") >> (uint_p[assign_a(conf.cc.port)] | eps_p[lerror("Wrong port!")])
  200. | str_p("bpp=") >> (uint_p[assign_a(conf.cc.bpp)] | eps_p[lerror("Wrong bpp!")])
  201. | str_p("localInformation=") >> (uint_p[assign_a(conf.cc.localInformation)] | eps_p[lerror("Wrong localInformation!")])
  202. | str_p("fullscreen=") >> (uint_p[assign_a(conf.cc.fullscreen)] | eps_p[lerror("Wrong fullscreen!")])
  203. | str_p("server=") >> ( ( +digit_p >> *('.' >> +digit_p) )[assign_a(conf.cc.server)] | eps_p[lerror("Wrong server!")])
  204. | str_p("defaultAI=") >> ((+(anychar_p - ';'))[assign_a(conf.cc.defaultAI)] | eps_p[lerror("Wrong defaultAI!")])
  205. | (+(anychar_p - '}'))[lerror2("Unrecognized client option: ")]
  206. ;
  207. clientOptionsSequence = *(clientOption >> (';' | eps_p[lerror("Semicolon lacking after client option!")]));
  208. ClientSettings = '{' >> clientOptionsSequence >> '}';
  209. AdvMapOption
  210. = str_p("Buttons") >> ((ch_p('{') >> '}') | eps_p[lerror("Wrong Buttons!")])
  211. | str_p("Minimap: ") >>
  212. *(
  213. "width=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::minimapW)]//[assign_a(current->ac.minimapW)]
  214. | "height=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::minimapH)]
  215. | "x=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::minimapX)]
  216. | "y=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::minimapY)]
  217. )
  218. | str_p("Statusbar:") >>
  219. *(
  220. ( "x=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::statusbarX)]
  221. | "y=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::statusbarY)]
  222. | "graphic=" >> fname[SetAdventureStr(&AdventureMapConfig::statusbarG)]
  223. )
  224. )
  225. | str_p("ResDataBar:") >>
  226. *(
  227. ( "x=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::resdatabarX)]
  228. | "y=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::resdatabarY)]
  229. | "offsetX=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::resOffsetX)]
  230. | "offsetY=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::resOffsetY)]
  231. | "resSpace=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::resDist)]
  232. | "resDateSpace=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::resDateDist)]
  233. | "graphic=" >> fname[SetAdventureStr(&AdventureMapConfig::resdatabarG)]
  234. )
  235. )
  236. | str_p("InfoBox:") >>
  237. *(
  238. ( "x=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::infoboxX)]
  239. | "y=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::infoboxY)]
  240. )
  241. )
  242. | str_p("AdvMap:") >>
  243. *(
  244. ( "x=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::advmapX)]
  245. | "y=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::advmapY)]
  246. | "width=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::advmapW)]
  247. | "height=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::advmapH)]
  248. | "smoothMove=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::smoothMove)]
  249. | "puzzleSepia=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::puzzleSepia)]
  250. )
  251. )
  252. | str_p("background=") >> fname[SetAdventureStr(&AdventureMapConfig::mainGraphic)]
  253. | str_p("Button") >> (+(anychar_p-':'))[SetCurButton()] >> ':' >>
  254. *(
  255. ( "x=" >> uint_p[SetButtonProp_a(&ButtonInfo::x)]
  256. | "y=" >> uint_p[SetButtonProp_a(&ButtonInfo::y)]
  257. | "playerColoured=" >> uint_p[SetButtonProp_a(&ButtonInfo::playerColoured)]
  258. | "graphic=" >> fname[SetButtonStr(&ButtonInfo::defName)]
  259. | str_p("additionalDefs=")[ClearAdditionalDefs()]
  260. >> ch_p('(') >> fname[AddDefForButton()]
  261. >> *(',' >> fname[AddDefForButton()]) >> ')'
  262. )
  263. )
  264. | str_p("HeroList:") >>
  265. *(
  266. ( "x=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::hlistX)]
  267. | "y=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::hlistY)]
  268. | "size=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::hlistSize)]
  269. | "movePoints=" >> fname[SetAdventureStr(&AdventureMapConfig::hlistMB)]
  270. | "manaPoints=" >> fname[SetAdventureStr(&AdventureMapConfig::hlistMN)]
  271. | "arrowUp=" >> fname[SetAdventureStr(&AdventureMapConfig::hlistAU)]
  272. | "arrowDown=" >> fname[SetAdventureStr(&AdventureMapConfig::hlistAD)]
  273. )
  274. )
  275. | str_p("TownList:") >>
  276. *(
  277. ( "x=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::tlistX)]
  278. | "y=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::tlistY)]
  279. | "size=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::tlistSize)]
  280. | "arrowUp=" >> fname[SetAdventureStr(&AdventureMapConfig::tlistAU)]
  281. | "arrowDown=" >> fname[SetAdventureStr(&AdventureMapConfig::tlistAD)]
  282. )
  283. )
  284. | str_p("gem") >> uint_p[var(gnb) = arg1] >> ':' >>
  285. *(
  286. ( "x=" >> uint_p[bind(&setGem,1,_1)]
  287. | "y=" >> uint_p[bind(&setGem,0,_1)]
  288. | "graphic=" >> fname[AddGemName()]
  289. )
  290. )
  291. | str_p("InGameConsole:") >>
  292. *(
  293. ( "maxInputPerLine=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::inputLineLength)]
  294. | "maxOutputPerLine=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::outputLineLength)]
  295. )
  296. )
  297. | str_p("Overview:") >>
  298. *(
  299. ( "pics=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::overviewPics)]
  300. | "size=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::overviewSize)]
  301. | "graphic=" >> fname[SetAdventureStr(&AdventureMapConfig::overviewBg)]
  302. )
  303. )
  304. ;
  305. AdvMapOptionsSequence = *(AdvMapOption >> (';' | eps_p[lerror("Semicolon lacking in advmapopt!")]));
  306. GUIResolution = (uint_p[assign_a(curRes.first)] >> 'x' >> uint_p[assign_a(curRes.second)])
  307. [dummy(&addGRes)];
  308. GUIOption = str_p("AdventureMap") >> ('{' >> AdvMapOptionsSequence >> '}' | eps_p[lerror("Wrong AdventureMap!")]);
  309. GUIOptionsSequence = *(GUIOption >> (';' | eps_p[lerror("Semicolon after GUIOption lacking!")]));
  310. GUISettings = +(GUIResolution >> '{' >> GUIOptionsSequence >> '}');
  311. r
  312. = str_p("clientSettings") >> (ClientSettings | eps_p[lerror("Wrong clientSettings!")])
  313. >> str_p("GUISettings") >> ('{' >> GUISettings >> '}' | eps_p[lerror("Wrong GUISettings!")]);
  314. #ifdef BOOST_SPIRIT_DEBUG
  315. BOOST_SPIRIT_DEBUG_RULE(clientOption);
  316. BOOST_SPIRIT_DEBUG_RULE(clientOptionsSequence);
  317. BOOST_SPIRIT_DEBUG_RULE(ClientSettings);
  318. BOOST_SPIRIT_DEBUG_RULE(AdvMapOption);
  319. BOOST_SPIRIT_DEBUG_RULE(AdvMapOptionsSequence);
  320. BOOST_SPIRIT_DEBUG_RULE(GUIOption);
  321. BOOST_SPIRIT_DEBUG_RULE(GUIOptionsSequence);
  322. BOOST_SPIRIT_DEBUG_RULE(GUISettings);
  323. BOOST_SPIRIT_DEBUG_RULE(GUIResolution);
  324. BOOST_SPIRIT_DEBUG_RULE(r);
  325. #endif
  326. }
  327. rule<ScannerT> const& start() const { return r; }
  328. };
  329. };
  330. struct CommentsGrammar : public grammar<CommentsGrammar>
  331. {
  332. template <typename ScannerT>
  333. struct definition
  334. {
  335. rule<ScannerT> comment;
  336. definition(CommentsGrammar const& self)
  337. {
  338. comment = comment_p("//") | comment_p("/*","*/") | space_p;
  339. BOOST_SPIRIT_DEBUG_RULE(comment);
  340. }
  341. rule<ScannerT> const& start() const { return comment; }
  342. };
  343. };
  344. CConfigHandler::CConfigHandler(void)
  345. {
  346. }
  347. CConfigHandler::~CConfigHandler(void)
  348. {
  349. }
  350. void config::CConfigHandler::init()
  351. {
  352. std::vector<char> settings;
  353. std::ifstream ifs(DATA_DIR "/config/settings.txt");
  354. if(!ifs)
  355. {
  356. tlog1 << "Cannot open " DATA_DIR "/config/settings.txt !" << std::endl;
  357. return;
  358. }
  359. ifs.unsetf(std::ios::skipws); // Turn of white space skipping on the stream
  360. std::copy(std::istream_iterator<char>(ifs),std::istream_iterator<char>(),std::back_inserter(settings));
  361. std::vector<char>::const_iterator first = settings.begin(), last = settings.end();
  362. SettingsGrammar sg;
  363. BOOST_SPIRIT_DEBUG_NODE(sg);
  364. CommentsGrammar cg;
  365. BOOST_SPIRIT_DEBUG_NODE(cg);
  366. parse_info<std::vector<char>::const_iterator> info = parse(first,last,sg,cg);
  367. if(!info.hit)
  368. tlog1 << "Cannot parse config/settings.txt file!\n";
  369. else if(!info.full)
  370. tlog2 << "Not entire config/settings.txt parsed!\n";
  371. //fixing screenx / screeny if set to 0x0
  372. if (cc.screenx == 0 && cc.screeny == 0)
  373. {
  374. cc.screenx = cc.resx;
  375. cc.screeny = cc.resy;
  376. }
  377. }
  378. GUIOptions * config::CConfigHandler::go()
  379. {
  380. return &guiOptions[std::pair<int,int>(cc.resx,cc.resy)];
  381. }