prefs.cpp 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. // prefs.cpp
  19. // Project: Soon-to-be-RSPiX
  20. //
  21. // This module deals with setting up the system for the game.
  22. //
  23. // History:
  24. // 11/19/96 MJR Started.
  25. // 12/11/96 JPW Implemented reading and writing of ini files,
  26. // functionallity to get/set variables, and delete/create
  27. // sections and variables.
  28. // 12/16/96 JPW Fixed so it will work with the STL stuff that comes with
  29. // MSVC 4.1 or newer. Also fixed a few psz parameters that
  30. // should have been const's.
  31. // 01/03/97 JPW Added Read() to functions that access ini file in memory
  32. // to insure the file is always read once before getting
  33. // and setting of ini file vars/sections
  34. //
  35. // 03/28/97 JMI Fixed so this'll work with MSVC 4.2.
  36. //
  37. // 03/31/97 JMI Changed sprintf %ud format specifiers (or something) to
  38. // %u.
  39. //
  40. // 04/21/97 MJR Changed inclusion of ez_stl from <ez_stl> to "ez_stl",
  41. // which goes together with adding ez_stl to sourcesafe
  42. // so there's a local copy in this directory.
  43. //
  44. // 05/08/97 JMI Added conditions for compiler versions' STL
  45. // differences (namely "list" vs. "list.h").
  46. // Also, changed #include <rspix.h> to #include "RSPiX.h".
  47. //
  48. // 06/11/97 JMI Commented TRACE in GetIteratorToVariable() when variable
  49. // cannot be found and in GetIteratorToSection() when section
  50. // cannot be found.
  51. //
  52. // 06/29/97 MJR Replaced STL vector with an RSP list. STL is an evil
  53. // entity that should be banished from the face of the earth.
  54. // Whoever suggested we use it should be shot. (Good thing
  55. // I'm the president -- it's against the rules to shoot me.)
  56. //
  57. // 07/05/97 MJR Fixed bug in printf() specifications. Apparently, "%lf"
  58. // is not a valid spec. "%f" works fine by itself.
  59. //
  60. // 07/09/97 MJR Changed so Close() no longer calls Write().
  61. // Added full support for CR or CR/LF files.
  62. //
  63. // 07/09/97 MJR Performed an overall cleanup regarding how the error flag
  64. // gets cleared and set. Also cleaned up how files are
  65. // written by close(). Also removed usage of "t" for fopen()
  66. // modes because it isn't ANSI standard. Finally, fixed
  67. // the CR/LF stuff so it actually works.
  68. //
  69. // 08/08/97 MJR Changed from using ANSI library tmpnam() to our own
  70. // version that can work in a specific directory.
  71. //
  72. ////////////////////////////////////////////////////////////////////////////////
  73. #include <stdio.h>
  74. #include <stdlib.h>
  75. #include <string.h>
  76. #include <ctype.h>
  77. #include <float.h>
  78. #include <assert.h>
  79. #include <errno.h>
  80. #include "Blue.h"
  81. #include "CYAN/cyan.h"
  82. #ifdef PATHS_IN_INCLUDES
  83. #include "ORANGE/str/str.h"
  84. #else
  85. #include "str.h"
  86. #endif
  87. #include "prefline.h"
  88. #include "prefs.h"
  89. ////////////////////////////////////////////////////////////////////////////////
  90. // Macros
  91. ////////////////////////////////////////////////////////////////////////////////
  92. ////////////////////////////////////////////////////////////////////////////////
  93. // Types
  94. ////////////////////////////////////////////////////////////////////////////////
  95. ////////////////////////////////////////////////////////////////////////////////
  96. // Variables/data
  97. ////////////////////////////////////////////////////////////////////////////////
  98. ////////////////////////////////////////////////////////////////////////////////
  99. // Function prototypes
  100. ////////////////////////////////////////////////////////////////////////////////
  101. ////////////////////////////////////////////////////////////////////////////////
  102. //
  103. // Default (and only) constructor
  104. //
  105. ////////////////////////////////////////////////////////////////////////////////
  106. RPrefs::RPrefs(void)
  107. {
  108. m_pFile = NULL;
  109. m_sReadOnly = 0;
  110. m_sModified = 0;
  111. m_sDidRead = 0;
  112. m_sUseCRLF = 0;
  113. m_pszFileName = 0;
  114. m_pszFileMode = 0;
  115. m_sErrorStatus = 0;
  116. }
  117. ////////////////////////////////////////////////////////////////////////////////
  118. //
  119. // Destructor
  120. //
  121. ////////////////////////////////////////////////////////////////////////////////
  122. RPrefs::~RPrefs()
  123. {
  124. // Close (in case file was left open)
  125. Close();
  126. // Free the name and mode
  127. delete []m_pszFileName;
  128. m_pszFileName = NULL;
  129. delete []m_pszFileMode;
  130. m_pszFileMode = NULL;
  131. // Delete all lines and get rid of list nodes
  132. while (m_pllLines.GetHead())
  133. {
  134. delete m_pllLines.GetHeadData();
  135. m_pllLines.RemoveHead();
  136. }
  137. }
  138. ////////////////////////////////////////////////////////////////////////////////
  139. //
  140. // Open preference file.
  141. //
  142. // Two overloaded versions of this function exist. The first allows the mode
  143. // to be specified using the same values as used by fopen(). The second
  144. // attempts to open the file in read/write mode. If this fails, it attempts
  145. // to open the file in read-only mode. If this fails, too, it attempts to
  146. // create an empty file.
  147. //
  148. ////////////////////////////////////////////////////////////////////////////////
  149. short RPrefs::Open( // Returns 0 if successfull, non-zero otherwise
  150. const char* pszFile) // In: Name of preference file
  151. {
  152. // Attempt to open in read/write mode
  153. if (Open(pszFile, "r+") != 0)
  154. {
  155. // Attempt to open in read-only mode (file may be read-only)
  156. if (Open(pszFile, "r") != 0)
  157. {
  158. // Attempt to create file
  159. Open(pszFile, "w+");
  160. }
  161. }
  162. return m_sErrorStatus;
  163. }
  164. extern const char *FindCorrectFile(const char *pszName, const char *mode);
  165. ////////////////////////////////////////////////////////////////////////////////
  166. short RPrefs::Open( // Returns 0 if successfull, non-zero otherwise
  167. const char* pszFile, // In: Name of preference file
  168. const char* pszMode) // In: Mode (same as fopen())
  169. {
  170. ASSERT(pszFile);
  171. ASSERT(pszMode);
  172. // Close (in case a file was already open)
  173. Close();
  174. // If mode contains "a" (append), "w" (write), or "+" (read and write)
  175. // then the file won't be read-only. Otherwise, it will be.
  176. if (strcspn(pszMode, "aAwW+") < strlen(pszMode))
  177. m_sReadOnly = 0;
  178. else
  179. m_sReadOnly = 1;
  180. // Attempt to open file
  181. m_pFile = fopen(FindCorrectFile(pszFile, pszMode), pszMode);
  182. if (m_pFile != NULL)
  183. {
  184. // Make a copy of the file name
  185. delete []m_pszFileName;
  186. m_pszFileName = new char[strlen(pszFile) + 1];
  187. ASSERT(m_pszFileName);
  188. strcpy(m_pszFileName, pszFile);
  189. // Make a copy of the file mode
  190. delete []m_pszFileMode;
  191. m_pszFileMode = new char[strlen(pszMode) + 1];
  192. ASSERT(m_pszFileMode);
  193. strcpy(m_pszFileMode, pszMode);
  194. // Clear error status
  195. m_sErrorStatus = 0;
  196. }
  197. else
  198. {
  199. TRACE("RPrefs::Open(): %s\n",strerror(errno));
  200. m_sErrorStatus = -1;
  201. }
  202. return m_sErrorStatus;
  203. }
  204. ////////////////////////////////////////////////////////////////////////////////
  205. //
  206. // Read and parse ini file into list of lines
  207. //
  208. // If an I/O error occurs, the function returns a negative value.
  209. //
  210. ////////////////////////////////////////////////////////////////////////////////
  211. short RPrefs::Read() // Returns 0 if successfull, non-zero otherwise
  212. {
  213. if (!m_sErrorStatus)
  214. {
  215. if (!m_sDidRead)
  216. {
  217. if (m_pFile != NULL)
  218. {
  219. // Seek to start of file
  220. if (fseek(m_pFile, SEEK_SET, 0) == 0)
  221. {
  222. // process lines until EOF is reached or an error occurrs
  223. //
  224. // In files written by DOS/Windows, lines are terminated by a CR/LF pair,
  225. // which is "\n" followed by "\r". In files written by Mac OS, lines are
  226. // terminated by a CR ("\n") only. Under Win32, the standard library
  227. // functions convert CR/LF into a single CR, but this is NOT done by
  228. // the Mac versions of these libraries. On the Mac, fgets() will return
  229. // a line terminated by a "\n". The next fgets() will return the "\r"
  230. // from the previous line along with whatever follows, up to the next
  231. // "\n". Therefore, on the Mac, we check if the line begins with a "\r",
  232. // and if so, we set a flag and then skip over the "\r". The flag tells
  233. // us that when we write the file back out, we should use CR/LF pairs to
  234. // preserve the file's original format.
  235. char pszLine[RPrefs::MaxStrLen+1];
  236. RPrefsLine *plTemp;
  237. while (fgets(pszLine, RPrefs::MaxStrLen, m_pFile) != NULL)
  238. {
  239. // Check for "/r". This is only required by Mac code, but it can't
  240. // hurt DOS/Windows code, where the fgets() should have converted the
  241. // "/n/r" into a "/n".
  242. char* pszFixedLine = pszLine;
  243. if (*pszFixedLine == '\r')
  244. {
  245. // Set flag so we'll know to write file out with CR/LF instead of just CR
  246. m_sUseCRLF = 1;
  247. // Skip over the "/r"
  248. pszFixedLine++;
  249. // If there's nothing after the "\r" it means the previous line
  250. // was really the last line of the file and this "\r" is just a
  251. // meaningless, left-over, piece of crap that should be ignored.
  252. if (*pszFixedLine == '\0')
  253. continue;
  254. }
  255. // Remove newline (if any) from end of line
  256. short len = strlen(pszFixedLine);
  257. if (pszFixedLine[len - 1] == '\n')
  258. pszFixedLine[len - 1] = '\0';
  259. // Find first non-space char
  260. char* pszToken = pszFixedLine;
  261. while ((*pszToken != '\0') && isspace(*pszToken))
  262. pszToken++;
  263. // Process line based on whether it's a comment/blank, section, or variable
  264. switch (*pszToken)
  265. {
  266. case '\0': // Empty line counts as a comment line
  267. case ';': // Create comment line
  268. plTemp = new RPrefsLine(RPrefsLine::Comment, pszFixedLine);
  269. ASSERT(plTemp);
  270. break;
  271. case '[': // Create section line
  272. plTemp = new RPrefsLine(RPrefsLine::Section, pszFixedLine);
  273. ASSERT(plTemp);
  274. break;
  275. default: // Default must be a variable
  276. plTemp = new RPrefsLine(RPrefsLine::Variable, pszFixedLine);
  277. ASSERT(plTemp);
  278. break;
  279. }
  280. // Add line to list of lines
  281. m_pllLines.InsertTail(plTemp);
  282. } // end while
  283. if (ferror(m_pFile) == 0)
  284. {
  285. // Set flag indicating read was successfully performed
  286. m_sDidRead = 1;
  287. }
  288. else
  289. {
  290. m_sErrorStatus = -3;
  291. TRACE("RPrefs::Read(): fgets(): %s\n", strerror(errno));
  292. }
  293. }
  294. else
  295. {
  296. m_sErrorStatus = -2;
  297. TRACE("RPrefs::Read(): fseek(): %s\n",strerror(errno));
  298. }
  299. }
  300. else
  301. {
  302. m_sErrorStatus = -1;
  303. TRACE("RPrefs::Read(): File not open!\n");
  304. }
  305. }
  306. }
  307. return m_sErrorStatus;
  308. }
  309. ////////////////////////////////////////////////////////////////////////////////
  310. //
  311. // Write current preference file
  312. //
  313. ////////////////////////////////////////////////////////////////////////////////
  314. short RPrefs::Write()
  315. {
  316. if (!m_sErrorStatus)
  317. {
  318. // Make sure we can and should do a write
  319. if (!m_sReadOnly && m_sModified)
  320. {
  321. if (m_pFile != NULL)
  322. {
  323. // Read file in case it wasn't already read
  324. if(Read() == 0)
  325. {
  326. // Close file before it gets deleted (and replaced by a new file)
  327. fclose(m_pFile);
  328. m_pFile = 0;
  329. // Create a temporary name. We search backwards from the end
  330. // of the real filename, looking for the first system separator,
  331. // or the beginning of the string, whichever comes first. We
  332. // then change from that point forward to be "t0000000.tmp",
  333. // which will work on all systems, even DOS 8.3 file systems.
  334. // We then check if that filename exists, and if so, we inc the
  335. // number portion of it and try again until we find a file that
  336. // doesn't exist, and that becomes our temp file name.
  337. bool bGotTmp = false;
  338. char acTmpFileName[RSP_MAX_PATH + 20];
  339. strcpy(acTmpFileName, m_pszFileName);
  340. char* pTmp = strrchr(acTmpFileName, RSP_SYSTEM_PATH_SEPARATOR);
  341. pTmp = (pTmp != NULL) ? pTmp + 1 : acTmpFileName;
  342. for (long lCount = 0; !bGotTmp && (lCount < 9999999L); lCount++)
  343. {
  344. sprintf(pTmp, "t%0.7ld.tmp", (long)lCount);
  345. FILE* fpTmp = fopen(FindCorrectFile(acTmpFileName, "r"), "r");
  346. if (fpTmp != NULL)
  347. fclose(fpTmp);
  348. else
  349. bGotTmp = true;
  350. }
  351. if (bGotTmp)
  352. {
  353. // Create temp file that will contain new ini stuff
  354. FILE *pfileTmp = fopen(FindCorrectFile(acTmpFileName, "w"), "w");
  355. if (pfileTmp != NULL)
  356. {
  357. // Write lines out to temp file
  358. for (RPrefsLineList::Pointer i = m_pllLines.GetHead(); i != 0; i = m_pllLines.GetNext(i))
  359. {
  360. int res = fprintf(pfileTmp, "%s\n", m_pllLines.GetData(i)->GetLine());
  361. if ((res >= 0) && m_sUseCRLF)
  362. res = fprintf(pfileTmp, "\r");
  363. if(res < 0)
  364. {
  365. TRACE("RPrefs::Write(): fprintf() data to temp file: %s\n", strerror(errno));
  366. m_sErrorStatus = -2;
  367. break;
  368. }
  369. }
  370. // Close temp file
  371. fclose(pfileTmp);
  372. if (m_sErrorStatus == 0)
  373. {
  374. // Remove old file
  375. if (remove(FindCorrectFile(m_pszFileName, "w")) == 0)
  376. {
  377. // Rename temp file to whatever old file was named
  378. // rename() isn't reliably across filesystems. --ryan.
  379. //if (rename(FindCorrectFile(acTmpFileName, "w"), FindCorrectFile(m_pszFileName, "w")) == 0)
  380. FILE *in = fopen(FindCorrectFile(acTmpFileName, "w"), "r");
  381. FILE *out = fopen(FindCorrectFile(m_pszFileName, "w"), "w");
  382. if (in && out)
  383. {
  384. while (1)
  385. {
  386. int ch = fgetc(in);
  387. if (ch == EOF) break;
  388. fputc(ch, out);
  389. }
  390. }
  391. if (in) fclose(in);
  392. if (out) fclose(out);
  393. remove(FindCorrectFile(acTmpFileName, "w"));
  394. if (in && out)
  395. {
  396. // Open the new file using the original mode
  397. m_pFile = fopen(FindCorrectFile(m_pszFileName, m_pszFileMode), m_pszFileMode);
  398. if (m_pFile != NULL)
  399. {
  400. // Set flag to indicate ini file in memory is in sync with disk
  401. m_sModified = 0;
  402. }
  403. else
  404. {
  405. TRACE("RPrefs::Write(): fopen() of new file: %s\n", strerror(errno));
  406. m_sErrorStatus = -1;
  407. }
  408. }
  409. else
  410. {
  411. TRACE("RPrefs::Write(): rename() of temp file to original file: %s\n", strerror(errno));
  412. m_sErrorStatus = -4;
  413. }
  414. }
  415. else
  416. {
  417. TRACE("RPrefs::Write(): remove() of old ini file: %s\n", strerror(errno));
  418. m_sErrorStatus = -3;
  419. }
  420. }
  421. }
  422. else
  423. {
  424. TRACE("RPrefs::Write(): fopen() of temp file: %s\n", strerror(errno));
  425. m_sErrorStatus = -1;
  426. }
  427. }
  428. else
  429. {
  430. TRACE("RPrefs::Write(): Couldn't get temp file name!\n");
  431. m_sErrorStatus = -5;
  432. }
  433. }
  434. else
  435. {
  436. TRACE("RPrefs::Write(): Couldn't Read() file!\n");
  437. }
  438. }
  439. else
  440. {
  441. m_sErrorStatus = -1;
  442. TRACE("RPrefs::Write(): File not open!\n");
  443. }
  444. }
  445. }
  446. return m_sErrorStatus;
  447. }
  448. ////////////////////////////////////////////////////////////////////////////////
  449. //
  450. // Close current preference file
  451. //
  452. ////////////////////////////////////////////////////////////////////////////////
  453. short RPrefs::Close()
  454. {
  455. if (m_pFile != NULL)
  456. {
  457. // If data was read and was modified and files is NOT read only then write it now!
  458. if (m_sDidRead && !m_sReadOnly && m_sModified)
  459. Write();
  460. // Close the file. We need to check if the file is still valid because
  461. // something might have gone wrong in Write().
  462. if (m_pFile != NULL)
  463. {
  464. fclose(m_pFile);
  465. m_pFile = NULL;
  466. }
  467. }
  468. return m_sErrorStatus;
  469. }
  470. ////////////////////////////////////////////////////////////////////////////////
  471. //
  472. // Delete the specified entry in the specified section
  473. //
  474. ////////////////////////////////////////////////////////////////////////////////
  475. short RPrefs::DeleteVariable( // Returns 0 if successfull, non-zero otherwise
  476. const char* pszSection, // In: Section name (without brackets)
  477. const char* pszVariable) // In: Variable name
  478. {
  479. ASSERT(pszSection);
  480. ASSERT(pszVariable);
  481. if (!m_sErrorStatus)
  482. {
  483. // Make sure there's a copy in memory
  484. if(Read() == 0)
  485. {
  486. // Get iterator to variable
  487. RPrefsLineList::Pointer i;
  488. if (GetIteratorToVariable(pszSection, pszVariable, &i) != 0)
  489. {
  490. TRACE("RPrefs::DeleteVariable():GetIteratorToVariable() "
  491. "unable to find variable.\n");
  492. m_sErrorStatus = 1;
  493. }
  494. else
  495. {
  496. m_pllLines.Remove(i);
  497. m_sModified = 1;
  498. }
  499. }
  500. else
  501. TRACE("RPrefs::DeleteVariable():RPrefs::Read() read failed: %s\n", strerror(errno));
  502. }
  503. return m_sErrorStatus;
  504. }
  505. ////////////////////////////////////////////////////////////////////////////////
  506. //
  507. // Delete the specified section
  508. //
  509. ////////////////////////////////////////////////////////////////////////////////
  510. short RPrefs::DeleteSection( // Returns 0 if successfull, non-zero otherwise
  511. const char* pszSection) // In: Section name (without brackets)
  512. {
  513. ASSERT(pszSection);
  514. if (!m_sErrorStatus)
  515. {
  516. // Make sure there's a copy in memory
  517. if(Read() == 0)
  518. {
  519. // Get iterator to section
  520. RPrefsLineList::Pointer i;
  521. if (GetIteratorToSection(pszSection, &i) != 0)
  522. {
  523. TRACE("RPrefs::DeleteSection():GetIteratorToSection() unable to find section");
  524. m_sErrorStatus = 1;
  525. }
  526. else
  527. {
  528. // Remove everything from this section name up to next section name
  529. do {
  530. RPrefsLineList::Pointer j = m_pllLines.GetNext(i);
  531. m_pllLines.Remove(i);
  532. i = j;
  533. if (i == 0)
  534. break;
  535. } while (m_pllLines.GetData(i)->GetType() != RPrefsLine::Section);
  536. m_sModified = 1;
  537. }
  538. }
  539. else
  540. TRACE("RPrefs::DeleteSection():RPrefs::Read() read failed: %s\n", strerror(errno));
  541. }
  542. return m_sErrorStatus;
  543. }
  544. ////////////////////////////////////////////////////////////////////////////////
  545. //
  546. // Set specified entry in the specified section to the specified value.
  547. //
  548. // Several overloaded versions of this function exist, each dealing with
  549. // different types, ranging from a string to all the basic integer and
  550. // floating-point types.
  551. //
  552. // If the section does not exist, it will be created. Likewise, if the entry
  553. // does not exist, it will be created.
  554. //
  555. // If an I/O error occurs, the function returns a non-zero negative value.
  556. //
  557. ////////////////////////////////////////////////////////////////////////////////
  558. short RPrefs::SetVal( // Returns 0 if successfull, non-zero otherwise
  559. const char* pszSection, // In: Section name (without brackets)
  560. const char* pszVariable, // In: Variable name
  561. const char* pszValue) // In: Value
  562. {
  563. // Iterator for section and variable in list of lines
  564. RPrefsLineList::Pointer iSection, iVariable;
  565. RPrefsLine *pplTemp;
  566. char pszLine[128];
  567. ASSERT(pszSection);
  568. ASSERT(pszVariable);
  569. ASSERT(pszValue);
  570. // Make sure there's a copy in memory
  571. if(Read() == 0)
  572. {
  573. // Determine if section exists by trying to get an iterator to the section
  574. if (GetIteratorToSection(pszSection, &iSection) == 0)
  575. {
  576. // Section exists. No need to create a new one.
  577. // Determine if variable exists by trying to get an iterator to the variable
  578. if (GetIteratorToVariable(pszSection, pszVariable, &iVariable) == 0)
  579. // Found variable and section. Must change value of existing variable
  580. m_pllLines.GetData(iVariable)->SetVariableValue(pszValue);
  581. else
  582. { // Variable not found but section was. Add a new variable
  583. sprintf(pszLine, "%s = %s", pszVariable, pszValue);
  584. pplTemp = new RPrefsLine(RPrefsLine::Variable, pszLine);
  585. ASSERT(pplTemp);
  586. m_pllLines.InsertAfter(pplTemp, iSection);
  587. m_sErrorStatus = 0;
  588. }
  589. }
  590. else
  591. { // Section Not found. Create empty comment line followed by new section and variable
  592. pplTemp = new RPrefsLine(RPrefsLine::Comment, "");
  593. ASSERT(pplTemp);
  594. m_pllLines.InsertTail(pplTemp);
  595. sprintf(pszLine, "[%s]", pszSection);
  596. pplTemp = new RPrefsLine(RPrefsLine::Section, pszLine);
  597. ASSERT(pplTemp);
  598. m_pllLines.InsertTail(pplTemp);
  599. sprintf(pszLine, "%s = %s", pszVariable, pszValue);
  600. pplTemp = new RPrefsLine(RPrefsLine::Variable, pszLine);
  601. ASSERT(pplTemp);
  602. m_pllLines.InsertTail(pplTemp);
  603. m_sErrorStatus = 0;
  604. }
  605. m_sModified = 1;
  606. }
  607. else
  608. TRACE("RPrefs::SetVal():RPrefs::Read() read failed: %s\n", strerror(errno));
  609. return m_sErrorStatus;
  610. }
  611. ////////////////////////////////////////////////////////////////////////////////
  612. short RPrefs::SetVal( // Returns 0 if successfull, non-zero otherwise
  613. const char* pszSection, // In: Section name (without brackets)
  614. const char* pszVariable, // In: Variable name
  615. S8 s8Value) // In: Value
  616. {
  617. char pszValue[8];
  618. ASSERT(pszSection);
  619. ASSERT(pszVariable);
  620. sprintf(pszValue, "%d", (int) s8Value);
  621. SetVal(pszSection, pszVariable, pszValue);
  622. return m_sErrorStatus;
  623. }
  624. ////////////////////////////////////////////////////////////////////////////////
  625. short RPrefs::SetVal( // Returns 0 if successfull, non-zero otherwise
  626. const char* pszSection, // In: Section name (without brackets)
  627. const char* pszVariable, // In: Variable name
  628. U8 u8Value) // In: Value
  629. {
  630. char pszValue[8];
  631. ASSERT(pszSection);
  632. ASSERT(pszVariable);
  633. sprintf(pszValue, "%u", (unsigned) u8Value);
  634. SetVal(pszSection, pszVariable, pszValue);
  635. return m_sErrorStatus;
  636. }
  637. ////////////////////////////////////////////////////////////////////////////////
  638. short RPrefs::SetVal( // Returns 0 if successfull, non-zero otherwise
  639. const char* pszSection, // In: Section name (without brackets)
  640. const char* pszVariable, // In: Variable name
  641. S16 s16Value) // In: Value
  642. {
  643. char pszValue[8];
  644. ASSERT(pszSection);
  645. ASSERT(pszVariable);
  646. sprintf(pszValue, "%d", (int) s16Value);
  647. SetVal(pszSection, pszVariable, pszValue);
  648. return m_sErrorStatus;
  649. }
  650. ////////////////////////////////////////////////////////////////////////////////
  651. short RPrefs::SetVal( // Returns 0 if successfull, non-zero otherwise
  652. const char* pszSection, // In: Section name (without brackets)
  653. const char* pszVariable, // In: Variable name
  654. U16 u16Value) // In: Value
  655. {
  656. char pszValue[8];
  657. ASSERT(pszSection);
  658. ASSERT(pszVariable);
  659. sprintf(pszValue, "%u", (unsigned) u16Value);
  660. SetVal(pszSection, pszVariable, pszValue);
  661. return m_sErrorStatus;
  662. }
  663. ////////////////////////////////////////////////////////////////////////////////
  664. short RPrefs::SetVal( // Returns 0 if successfull, non-zero otherwise
  665. const char* pszSection, // In: Section name (without brackets)
  666. const char* pszVariable, // In: Variable name
  667. S32 s32Value) // In: Value
  668. {
  669. char pszValue[16];
  670. ASSERT(pszSection);
  671. ASSERT(pszVariable);
  672. sprintf(pszValue, "%ld", (long) s32Value);
  673. SetVal(pszSection, pszVariable, pszValue);
  674. return m_sErrorStatus;
  675. }
  676. ////////////////////////////////////////////////////////////////////////////////
  677. short RPrefs::SetVal( // Returns 0 if successfull, non-zero otherwise
  678. const char* pszSection, // In: Section name (without brackets)
  679. const char* pszVariable, // In: Variable name
  680. U32 u32Value) // In: Value
  681. {
  682. char pszValue[16];
  683. ASSERT(pszSection);
  684. ASSERT(pszVariable);
  685. sprintf(pszValue, "%lu", (unsigned long) u32Value);
  686. SetVal(pszSection, pszVariable, pszValue);
  687. return m_sErrorStatus;
  688. }
  689. ////////////////////////////////////////////////////////////////////////////////
  690. short RPrefs::SetVal( // Returns 0 if successfull, non-zero otherwise
  691. const char* pszSection, // In: Section name (without brackets)
  692. const char* pszVariable, // In: Variable name
  693. float fValue) // In: Value
  694. {
  695. char pszValue[32];
  696. ASSERT(pszSection);
  697. ASSERT(pszVariable);
  698. sprintf(pszValue, "%f", fValue);
  699. SetVal(pszSection, pszVariable, pszValue);
  700. return m_sErrorStatus;
  701. }
  702. ////////////////////////////////////////////////////////////////////////////////
  703. short RPrefs::SetVal( // Returns 0 if successfull, non-zero otherwise
  704. const char* pszSection, // In: Section name (without brackets)
  705. const char* pszVariable, // In: Variable name
  706. double dValue) // In: Value
  707. {
  708. char pszValue[32];
  709. ASSERT(pszSection);
  710. ASSERT(pszVariable);
  711. sprintf(pszValue, "%f", dValue);
  712. SetVal(pszSection, pszVariable, pszValue);
  713. return m_sErrorStatus;
  714. }
  715. ////////////////////////////////////////////////////////////////////////////////
  716. // Get iterator to a section
  717. ////////////////////////////////////////////////////////////////////////////////
  718. short RPrefs::GetIteratorToSection( // Returns 0 if successfull, non-zero otherwise
  719. const char* pszSection, // In: Section name (without brackets)
  720. RPrefsLineList::Pointer* pi) // Out: iterator to line in list
  721. {
  722. assert (pszSection);
  723. assert (pi);
  724. if (!m_sErrorStatus)
  725. {
  726. if (m_pllLines.GetHead() == 0)
  727. {
  728. TRACE("RPrefs::GetIteratorToSection():m_pllLines.empty(): list is empty.\n");
  729. m_sErrorStatus = 1;
  730. }
  731. else
  732. {
  733. char pszSectionName[RPrefs::MaxStrLen];
  734. // Find section
  735. short sFoundSection = 0;
  736. for (*pi = m_pllLines.GetHead(); *pi != 0; *pi = m_pllLines.GetNext(*pi))
  737. {
  738. // Only looking for sections
  739. if (m_pllLines.GetData(*pi)->GetType() == RPrefsLine::Section)
  740. {
  741. // Get section name
  742. if (m_pllLines.GetData(*pi)->GetSectionName(pszSectionName) == 0)
  743. {
  744. // Is this the section name we are looking for?
  745. if (rspStricmp(pszSectionName, pszSection) == 0)
  746. {
  747. sFoundSection = 1;
  748. break;
  749. }
  750. }
  751. }
  752. }
  753. if (!sFoundSection) // If we didn't find section, return non-zero
  754. {
  755. // TRACE("RPrefs::GetIteratorToSection(): section not found.\n");
  756. m_sErrorStatus = 2;
  757. }
  758. }
  759. }
  760. return m_sErrorStatus;
  761. }
  762. ////////////////////////////////////////////////////////////////////////////////
  763. // Get iterator to a variable
  764. ////////////////////////////////////////////////////////////////////////////////
  765. short RPrefs::GetIteratorToVariable( // Returns 0 if successfull, non-zero otherwise
  766. const char* pszSection, // In: Section name (without brackets)
  767. const char* pszVariable, // In: Variable name
  768. RPrefsLineList::Pointer* pi) // Out: iterator to line in list
  769. {
  770. ASSERT(pszSection);
  771. ASSERT(pszVariable);
  772. ASSERT(pi);
  773. if (!m_sErrorStatus)
  774. {
  775. if (m_pllLines.GetHead() == 0)
  776. {
  777. TRACE("RPrefs::GetIteratorToVariable():m_pllLines.empty(): list is empty.\n");
  778. m_sErrorStatus = 1;
  779. }
  780. else
  781. {
  782. char pszVariableName[RPrefs::MaxStrLen];
  783. // Get iterator to section
  784. m_sErrorStatus = GetIteratorToSection(pszSection, pi);
  785. if (m_sErrorStatus == 0)
  786. {
  787. // Search for variable (note that we start on the line after the section name)
  788. short sFoundVariable = 0;
  789. for (*pi = m_pllLines.GetNext(*pi); *pi != 0; *pi = m_pllLines.GetNext(*pi))
  790. {
  791. // Stop if we reach the next section
  792. if (m_pllLines.GetData(*pi)->GetType() == RPrefsLine::Section)
  793. break;
  794. // Only looking for variables
  795. if (m_pllLines.GetData(*pi)->GetType() == RPrefsLine::Variable)
  796. {
  797. // Get variable name
  798. if (m_pllLines.GetData(*pi)->GetVariableName(pszVariableName) == 0)
  799. {
  800. // Is this the variable name we are looking for
  801. if (rspStricmp(pszVariableName, pszVariable) == 0)
  802. {
  803. sFoundVariable = 1;
  804. break;
  805. }
  806. }
  807. }
  808. }
  809. if (!sFoundVariable)
  810. {
  811. // TRACE("RPrefs::GetIteratorToVariable(): variable not found.\n");
  812. m_sErrorStatus = 2;
  813. }
  814. }
  815. }
  816. }
  817. return m_sErrorStatus;
  818. }
  819. ////////////////////////////////////////////////////////////////////////////////
  820. //
  821. // Get the value associated with the specified entry in the specified section.
  822. //
  823. // Several overloaded versions of this function exist, each dealing with
  824. // different types, ranging from a string to all the basic integer and
  825. // floating-point types.
  826. //
  827. // If the entry does not exist in the file, then the specified default value
  828. // is used.
  829. //
  830. // If the value cannot be converted to the requested type (invalid characters,
  831. // overflow, etc.) then the value is set to 0 and the function returns a non-
  832. // zero, positive value to indicate an error.
  833. //
  834. ////////////////////////////////////////////////////////////////////////////////
  835. short RPrefs::GetVal( // Returns 0 if successfull, non-zero otherwise
  836. const char* pszSection, // In: Section name (without brackets)
  837. const char* pszVariable, // In: Variable name
  838. const char* pszDefault, // In: Default value
  839. char* pszValue) // Out: Value returned here
  840. {
  841. ASSERT(pszSection);
  842. ASSERT(pszVariable);
  843. ASSERT(pszDefault);
  844. ASSERT(pszValue);
  845. //if (m_sDidRead != 1)
  846. if (Read() == 0)
  847. {
  848. // Get iterator to variable
  849. RPrefsLineList::Pointer i;
  850. m_sErrorStatus = GetIteratorToVariable(pszSection, pszVariable, &i);
  851. // Process variable if it was found
  852. if (m_sErrorStatus == 0)
  853. {
  854. // Get variable's value
  855. m_sErrorStatus = m_pllLines.GetData(i)->GetVariableValue(pszValue);
  856. // Return code of 3 indicates an empty value
  857. if (m_sErrorStatus == 3)
  858. {
  859. strcpy(pszValue, pszDefault); // Go with default
  860. m_sErrorStatus = 0;
  861. }
  862. else
  863. if (m_sErrorStatus != 0) // Any other error code means a syntax error
  864. m_sErrorStatus = 1;
  865. }
  866. else
  867. {
  868. if (pszValue != pszDefault) // pointer comparison.
  869. strcpy(pszValue, pszDefault); // var not found, go with default
  870. m_sErrorStatus = 0; // Not finding a var should not be reported
  871. } // as an error on by return
  872. }
  873. else
  874. TRACE("RPrefs::GetVal():RPrefs::Read() read failed: %s\n", strerror(errno));
  875. return m_sErrorStatus;
  876. }
  877. ////////////////////////////////////////////////////////////////////////////////
  878. short RPrefs::GetVal( // Returns 0 if successfull, non-zero otherwise
  879. const char* pszSection, // In: Section name (without brackets)
  880. const char* pszVariable, // In: Variable name
  881. S8 s8Default, // In: Default value
  882. S8* s8Value) // Out: Value returned here
  883. {
  884. char pszValue[RPrefs::MaxStrLen], pszDefault[RPrefs::MaxStrLen], *pszEndPtr;
  885. long lRes;
  886. ASSERT(pszSection);
  887. ASSERT(pszVariable);
  888. ASSERT(s8Value);
  889. sprintf(pszDefault, "%d", (int)s8Default);
  890. m_sErrorStatus = GetVal(pszSection, pszVariable, pszDefault, pszValue);
  891. if (m_sErrorStatus == 0)
  892. {
  893. lRes = strtol(pszValue, &pszEndPtr, 10);
  894. if (((*pszEndPtr == '\0') || isspace(*pszEndPtr)) &&
  895. lRes >= S8_MIN && lRes <= S8_MAX)
  896. *s8Value = (S8) lRes;
  897. else
  898. {
  899. m_sErrorStatus = 1;
  900. *s8Value = 0;
  901. }
  902. }
  903. return m_sErrorStatus;
  904. }
  905. ////////////////////////////////////////////////////////////////////////////////
  906. short RPrefs::GetVal( // Returns 0 if successfull, non-zero otherwise
  907. const char* pszSection, // In: Section name (without brackets)
  908. const char* pszVariable, // In: Variable name
  909. U8 u8Default, // In: Default value
  910. U8* u8Value) // Out: Value returned here
  911. {
  912. char pszValue[RPrefs::MaxStrLen], pszDefault[RPrefs::MaxStrLen], *pszEndPtr;
  913. long lRes;
  914. ASSERT(pszSection);
  915. ASSERT(pszVariable);
  916. ASSERT(u8Value);
  917. sprintf(pszDefault, "%u", (unsigned)u8Default);
  918. m_sErrorStatus = GetVal(pszSection, pszVariable, pszDefault, pszValue);
  919. if (m_sErrorStatus == 0)
  920. {
  921. lRes = strtol(pszValue, &pszEndPtr, 10);
  922. if (((*pszEndPtr == '\0') || isspace(*pszEndPtr)) && lRes >= U8_MIN && lRes <= U8_MAX)
  923. *u8Value = (U8) lRes;
  924. else
  925. {
  926. m_sErrorStatus = 1;
  927. *u8Value = 0;
  928. }
  929. }
  930. return m_sErrorStatus;
  931. }
  932. ////////////////////////////////////////////////////////////////////////////////
  933. short RPrefs::GetVal( // Returns 0 if successfull, non-zero otherwise
  934. const char* pszSection, // In: Section name (without brackets)
  935. const char* pszVariable, // In: Variable name
  936. S16 s16Default, // In: Default value
  937. S16* s16Value) // Out: Value returned here
  938. {
  939. char pszValue[RPrefs::MaxStrLen], pszDefault[RPrefs::MaxStrLen], *pszEndPtr;
  940. long lRes;
  941. ASSERT(pszSection);
  942. ASSERT(pszVariable);
  943. ASSERT(s16Value);
  944. sprintf(pszDefault, "%d", (int)s16Default);
  945. m_sErrorStatus = GetVal(pszSection, pszVariable, pszDefault, pszValue);
  946. if (m_sErrorStatus == 0)
  947. {
  948. lRes = strtol(pszValue, &pszEndPtr, 10);
  949. if (((*pszEndPtr == '\0') || isspace(*pszEndPtr)) && lRes >= S16_MIN && lRes <= S16_MAX)
  950. *s16Value = (S16) lRes;
  951. else
  952. {
  953. m_sErrorStatus = 1;
  954. *s16Value = 0;
  955. }
  956. }
  957. return m_sErrorStatus;
  958. }
  959. ////////////////////////////////////////////////////////////////////////////////
  960. short RPrefs::GetVal( // Returns 0 if successfull, non-zero otherwise
  961. const char* pszSection, // In: Section name (without brackets)
  962. const char* pszVariable, // In: Variable name
  963. U16 u16Default, // In: Default value
  964. U16* u16Value) // Out: Value returned here
  965. {
  966. char pszValue[RPrefs::MaxStrLen], pszDefault[RPrefs::MaxStrLen], *pszEndPtr;
  967. long lRes;
  968. ASSERT(pszSection);
  969. ASSERT(pszVariable);
  970. ASSERT(u16Value);
  971. sprintf(pszDefault, "%u", (unsigned)u16Default);
  972. m_sErrorStatus = GetVal(pszSection, pszVariable, pszDefault, pszValue);
  973. if (m_sErrorStatus == 0)
  974. {
  975. lRes = strtol(pszValue, &pszEndPtr, 10);
  976. if (((*pszEndPtr == '\0') || isspace(*pszEndPtr))
  977. && lRes >= U16_MIN && lRes <= U16_MAX)
  978. *u16Value = (U16) lRes;
  979. else
  980. {
  981. m_sErrorStatus = 1;
  982. *u16Value = 0;
  983. }
  984. }
  985. return m_sErrorStatus;
  986. }
  987. ////////////////////////////////////////////////////////////////////////////////
  988. short RPrefs::GetVal( // Returns 0 if successfull, non-zero otherwise
  989. const char* pszSection, // In: Section name (without brackets)
  990. const char* pszVariable, // In: Variable name
  991. S32 s32Default, // In: Default value
  992. S32* s32Value) // Out: Value returned here
  993. {
  994. char pszValue[RPrefs::MaxStrLen], pszDefault[RPrefs::MaxStrLen], *pszEndPtr;
  995. double dRes;
  996. ASSERT(pszSection);
  997. ASSERT(pszVariable);
  998. ASSERT(s32Value);
  999. sprintf(pszDefault, "%ld", (int)s32Default);
  1000. m_sErrorStatus = GetVal(pszSection, pszVariable, pszDefault, pszValue);
  1001. if (m_sErrorStatus == 0)
  1002. {
  1003. dRes = strtod(pszValue, &pszEndPtr);
  1004. if (((*pszEndPtr == '\0') || isspace(*pszEndPtr)) &&
  1005. dRes >= S32_MIN && dRes <= S32_MAX)
  1006. *s32Value = (S32) dRes;
  1007. else
  1008. {
  1009. m_sErrorStatus = 1;
  1010. *s32Value = 0;
  1011. }
  1012. }
  1013. return m_sErrorStatus;
  1014. }
  1015. ////////////////////////////////////////////////////////////////////////////////
  1016. short RPrefs::GetVal( // Returns 0 if successfull, non-zero otherwise
  1017. const char* pszSection, // In: Section name (without brackets)
  1018. const char* pszVariable, // In: Variable name
  1019. U32 u32Default, // In: Default value
  1020. U32* u32Value) // Out: Value returned here
  1021. {
  1022. char pszValue[RPrefs::MaxStrLen], pszDefault[RPrefs::MaxStrLen], *pszEndPtr;
  1023. double dRes;
  1024. ASSERT(pszSection);
  1025. ASSERT(pszVariable);
  1026. ASSERT(u32Value);
  1027. sprintf(pszDefault, "%lu", (unsigned)u32Default);
  1028. m_sErrorStatus = GetVal(pszSection, pszVariable, pszDefault, pszValue);
  1029. if (m_sErrorStatus == 0)
  1030. {
  1031. dRes = strtod(pszValue, &pszEndPtr);
  1032. if (((*pszEndPtr == '\0') || isspace(*pszEndPtr))
  1033. && dRes >= U32_MIN && dRes <= U32_MAX)
  1034. *u32Value = (U32) dRes;
  1035. else
  1036. {
  1037. m_sErrorStatus = 1;
  1038. *u32Value = 0;
  1039. }
  1040. }
  1041. return m_sErrorStatus;
  1042. }
  1043. ////////////////////////////////////////////////////////////////////////////////
  1044. short RPrefs::GetVal( // Returns 0 if successfull, non-zero otherwise
  1045. const char* pszSection, // In: Section name (without brackets)
  1046. const char* pszVariable, // In: Variable name
  1047. float fDefault, // In: Default value
  1048. float* fValue) // Out: Value returned here
  1049. {
  1050. char pszValue[RPrefs::MaxStrLen], pszDefault[RPrefs::MaxStrLen], *pszEndPtr;
  1051. double dRes;
  1052. ASSERT(pszSection);
  1053. ASSERT(pszVariable);
  1054. ASSERT(fValue);
  1055. sprintf(pszDefault, "%f", fDefault);
  1056. m_sErrorStatus = GetVal(pszSection, pszVariable, pszDefault, pszValue);
  1057. if (m_sErrorStatus == 0)
  1058. {
  1059. dRes = strtod(pszValue, &pszEndPtr);
  1060. if (((*pszEndPtr == '\0') || isspace(*pszEndPtr)) && dRes >= FLT_MIN && dRes <= FLT_MAX)
  1061. *fValue = (float) dRes;
  1062. else
  1063. {
  1064. m_sErrorStatus = 1;
  1065. *fValue = (float) 0;
  1066. }
  1067. }
  1068. return m_sErrorStatus;
  1069. }
  1070. ////////////////////////////////////////////////////////////////////////////////
  1071. short RPrefs::GetVal( // Returns 0 if successfull, non-zero otherwise
  1072. const char* pszSection, // In: Section name (without brackets)
  1073. const char* pszVariable, // In: Variable name
  1074. double dDefault, // In: Default value
  1075. double* dValue) // Out: Value returned here
  1076. {
  1077. char pszValue[RPrefs::MaxStrLen], pszDefault[RPrefs::MaxStrLen], *pszEndPtr;
  1078. double dRes;
  1079. ASSERT(pszSection);
  1080. ASSERT(pszVariable);
  1081. ASSERT(dValue);
  1082. sprintf(pszDefault, "%f", dDefault);
  1083. m_sErrorStatus = GetVal(pszSection, pszVariable, pszDefault, pszValue);
  1084. if (m_sErrorStatus == 0)
  1085. {
  1086. dRes = strtod(pszValue, &pszEndPtr);
  1087. if ((*pszEndPtr == '\0') || isspace(*pszEndPtr))
  1088. *dValue = dRes;
  1089. else
  1090. {
  1091. m_sErrorStatus = 1;
  1092. *dValue = 0;
  1093. }
  1094. }
  1095. return m_sErrorStatus;
  1096. }
  1097. ////////////////////////////////////////////////////////////////////////////////
  1098. short RPrefs::Print()
  1099. {
  1100. if (Read() == 0)
  1101. {
  1102. if (m_pllLines.GetHead() == 0)
  1103. m_sErrorStatus = 1;
  1104. else
  1105. {
  1106. for (RPrefsLineList::Pointer i = m_pllLines.GetHead(); i != 0; i = m_pllLines.GetNext(i))
  1107. {
  1108. switch (m_pllLines.GetData(i)->GetType())
  1109. {
  1110. case RPrefsLine::Comment:
  1111. printf("[comment] ");
  1112. break;
  1113. case RPrefsLine::Section:
  1114. printf("[section] ");
  1115. break;
  1116. case RPrefsLine::Variable:
  1117. printf("[variable] ");
  1118. break;
  1119. default:
  1120. break;
  1121. }
  1122. printf("%s\n", m_pllLines.GetData(i)->GetLine());
  1123. }
  1124. }
  1125. }
  1126. else
  1127. TRACE("RPrefs::Print():RPrefs::Read() read failed: %s\n", strerror(errno));
  1128. return m_sErrorStatus;
  1129. }
  1130. ////////////////////////////////////////////////////////////////////////////////
  1131. // EOF
  1132. ////////////////////////////////////////////////////////////////////////////////