AccessCCDF.c 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $XConsortium: AccessCCDF.c /main/10 1996/11/01 10:09:50 drk $ */
  24. /************************************<+>*************************************
  25. ****************************************************************************
  26. **
  27. ** File: AccessCCDF.c
  28. **
  29. ** Project: Cde 1.0 Help Library
  30. **
  31. ** Description: This body of code handles the access routines to the
  32. ** legacy CCDF Help files.
  33. **
  34. **
  35. ** (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
  36. **
  37. ** (c) Copyright 1993, 1994 Hewlett-Packard Company
  38. ** (c) Copyright 1993, 1994 International Business Machines Corp.
  39. ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  40. ** (c) Copyright 1993, 1994 Novell, Inc.
  41. **
  42. **
  43. ****************************************************************************
  44. ************************************<+>*************************************/
  45. /*
  46. * system includes
  47. */
  48. #include <errno.h>
  49. #include <stdlib.h>
  50. #include <stdio.h>
  51. #include <string.h>
  52. #include <unistd.h>
  53. #include <X11/Xlib.h>
  54. #include <X11/Xresource.h>
  55. #include <X11/Xos.h>
  56. #ifdef X_NOT_STDC_ENV
  57. extern int errno;
  58. #endif
  59. extern char *_DtHelpGetLocale(void);
  60. /*
  61. * Canvas Engine includes
  62. */
  63. #include "CanvasP.h"
  64. #include "CanvasSegP.h"
  65. /*
  66. * private includes
  67. */
  68. #include "CanvasError.h"
  69. #include "AccessP.h"
  70. #include "bufioI.h"
  71. #include "AccessCCDFP.h"
  72. #include "AccessCCDFI.h"
  73. #include "FormatUtilI.h"
  74. #include "StringFuncsI.h"
  75. #include "HelpXlate.h"
  76. #ifdef NLS16
  77. #endif
  78. /******** Private Defines ********/
  79. #define LIST_INCREMENT 10
  80. #define BUFF_SIZE 256
  81. /******** End Private Defines ********/
  82. /******** Private Function Declarations ********/
  83. static char *CreateFileName(
  84. char *path,
  85. char *string );
  86. static int GetResourceInt (
  87. XrmDatabase db,
  88. char *topic,
  89. char *resClass,
  90. char *resName,
  91. int *ret_value);
  92. static char *GetResourceString (
  93. XrmDatabase db,
  94. char *topic,
  95. char *resClass,
  96. char *resName);
  97. static char **GetResourceStringArray (
  98. XrmDatabase db,
  99. char *topic,
  100. char *resClass,
  101. char *resName);
  102. static int GetTopicMap (
  103. _DtHelpVolume vol,
  104. char *target_id,
  105. int level,
  106. char ***ret_ids );
  107. /******** End Private Function Declarations ********/
  108. /******** Private Macro Declarations ********/
  109. #define GetCcdfVolumePtr(vol) \
  110. ((CcdfVolumePtr)((vol)->vols.ccdf_vol))
  111. #define GetFilenameResource(vol, topic) \
  112. GetResourceString((vol)->volDb, topic, "Filename", "filename")
  113. /******** End Private Macro Declarations ********/
  114. /******************************************************************************
  115. *
  116. * Private variables used within this file.
  117. *
  118. *******************************************************************************/
  119. static const char *Period = ".";
  120. static const char *Slash = "/";
  121. static const char *VolumeStr = "Volume.";
  122. static const char *volumeStr = "Volume.";
  123. static const struct _CcdfVolumeInfo DefaultCcdfVol =
  124. {
  125. NULL, /* XrmDatabase volDb; */
  126. NULL, /* char **topicList; */
  127. NULL, /* char *keywordFile; */
  128. };
  129. /******************************************************************************
  130. * Private Functions
  131. ******************************************************************************/
  132. /******************************************************************************
  133. * Function: CreateFileName (char *path, char *string)
  134. *
  135. * Parameters: path Specifies the path to the volume.
  136. * string Specifies the file's name including the extension.
  137. *
  138. * Memory owned by caller:
  139. * ptr returned
  140. *
  141. * Returns: Non null ptr if successful, null if a failure occurs.
  142. *
  143. * errno Values: CEErrorMalloc
  144. *
  145. * Purpose: Creates a fully qualified path to a file based on the
  146. * path given.
  147. *
  148. ******************************************************************************/
  149. static char *
  150. CreateFileName (
  151. char *path,
  152. char *string )
  153. {
  154. int len = 0;
  155. char *ptr;
  156. if ((MB_CUR_MAX == 1 || mblen (string, MB_CUR_MAX) == 1) && *string != '/'
  157. && path)
  158. {
  159. /*
  160. * determine the length of the path.
  161. */
  162. _DtHelpCeStrrchr (path, Slash, MB_CUR_MAX, &ptr);
  163. if (ptr)
  164. len = ptr - path + 1;
  165. }
  166. /*
  167. * malloc the room for the path and file name.
  168. */
  169. ptr = (char *) malloc (len + strlen(string) + 1);
  170. if (ptr)
  171. {
  172. /*
  173. * copy the name into the destination string.
  174. */
  175. ptr[0] = '\0';
  176. if (len && path)
  177. strncat (ptr, path, len);
  178. strcat (ptr, string);
  179. }
  180. return ptr;
  181. }
  182. /*****************************************************************************
  183. * Function: GetTopicMap (_DtHelpVolume vol, char *target_id,
  184. * int level, char ***ret_ids)
  185. *
  186. * Parameters: vol Specifies the loaded volume
  187. * target_id The target location ID of a topic.
  188. * level The levels progressed so far. It is
  189. * used to calculate how much memory
  190. * is required to hold all the ids.
  191. * ret_ids Returns a null terminated list of the
  192. * location IDs of the topics between the
  193. * target and the parent.
  194. * Memory own by caller:
  195. * ret_ids
  196. *
  197. * Returns: The number of ids put in the list so far,
  198. * -1 for failure.
  199. *
  200. * errno Values: CEErrorMalloc
  201. *
  202. *
  203. * Purpose: Recursively build a list of id strings containing all of
  204. * the target_id's ancestors.
  205. *
  206. *****************************************************************************/
  207. static int
  208. GetTopicMap (
  209. _DtHelpVolume vol,
  210. char *target_id,
  211. int level,
  212. char ***ret_ids )
  213. {
  214. int result = -1;
  215. char *idParent;
  216. if (_DtHelpCeGetCcdfTopicParent (vol, target_id, &idParent) == 0)
  217. {
  218. /*
  219. * still not at the top
  220. */
  221. if (idParent)
  222. {
  223. result = GetTopicMap (vol, idParent, level + 1, ret_ids);
  224. if (result != -1)
  225. {
  226. (*ret_ids)[result] = strdup (idParent);
  227. result++;
  228. }
  229. }
  230. else
  231. {
  232. *ret_ids = (char **) malloc (sizeof(char *) * (level + 2));
  233. if ((*ret_ids) == NULL)
  234. return -1;
  235. (*ret_ids)[level + 1] = NULL;
  236. result = 0;
  237. }
  238. }
  239. return result;
  240. } /* End GetTopicMap */
  241. /******************************************************************************
  242. * Function: char *GetResourceString (XrmDatabase db, char *topic,
  243. * char *resClass, char *resName)
  244. *
  245. * Parameters: db Specifies the handle to a resource database.
  246. * topic Specifies the topic whose resource value is
  247. * desired. If 'topic' is NULL, the
  248. * desired resource is for the volume and
  249. * not a specific topic.
  250. * resClass Specifies the resource class name.
  251. * resName Specifies the resource name.
  252. *
  253. * Return Value: Returns the desired resource as string.
  254. * This string is NOT owned by the caller and
  255. * should only be read or copied.
  256. *
  257. * Returns NULL if an error occurs.
  258. *
  259. * errno Values: CEErrorMalloc
  260. * CEErrorIllegalResource If the resource is not in
  261. * the database or if the
  262. * resource NULL
  263. *
  264. * Purpose: Get a resource value for a volume or topic.
  265. *
  266. ******************************************************************************/
  267. static char *
  268. GetResourceString (
  269. XrmDatabase db,
  270. char *topic,
  271. char *resClass,
  272. char *resName)
  273. {
  274. int len;
  275. int topicLen = 0;
  276. char *retVal = NULL;
  277. char *fullResName;
  278. char *fullResClass;
  279. char *resType;
  280. XrmValue resValue;
  281. if (topic != NULL)
  282. topicLen = strlen(topic) + strlen(Period);
  283. len = strlen(volumeStr) + topicLen + 1;
  284. fullResName = (char *) malloc (len + strlen (resName));
  285. fullResClass = (char *) malloc (len + strlen (resClass));
  286. if (fullResName != NULL && fullResClass != NULL)
  287. {
  288. strcpy (fullResName, volumeStr);
  289. strcpy (fullResClass, VolumeStr);
  290. if (topic != NULL)
  291. {
  292. strcat (fullResName, topic);
  293. strcat (fullResName, Period);
  294. strcat (fullResClass, topic);
  295. strcat (fullResClass, Period);
  296. }
  297. strcat (fullResName , resName);
  298. strcat (fullResClass, resClass);
  299. }
  300. else
  301. errno = CEErrorMalloc;
  302. if (fullResClass != NULL && fullResName != NULL)
  303. {
  304. if (XrmGetResource (db, fullResClass, fullResName, &resType, &resValue)
  305. && strlen ((char *) resValue.addr))
  306. retVal = (char *) resValue.addr;
  307. else
  308. errno = CEErrorIllegalResource;
  309. }
  310. if (fullResName)
  311. free (fullResName);
  312. if (fullResClass)
  313. free (fullResClass);
  314. return (retVal);
  315. }
  316. /******************************************************************************
  317. * Function: char **GetResourceStringArray (XrmDatabase db, char *topic,
  318. * char *resClass, char *resName)
  319. *
  320. * Parameters: db Specifies the handle to a resource database.
  321. * topic Specifies the topic whose resource value is
  322. * desired. If 'topic' is NULL, the
  323. * desired resource is for the volume and
  324. * not a specific topic.
  325. * resClass Specifies the resource class name.
  326. * resName Specifies the resource name.
  327. *
  328. * Return Value: Returns a NULL-terminated string array containing the
  329. * value of the desired resource. The elements of the
  330. * array are the strings of non-whitespace characters in
  331. * the resource value. This array is owned by the caller
  332. * and should be freed (using _DtHelpCeFreeStringArray) when
  333. * not needed.
  334. *
  335. * Purpose: Get am array-valued resource for a volume or topic.
  336. *
  337. ******************************************************************************/
  338. static char **
  339. GetResourceStringArray (
  340. XrmDatabase db,
  341. char *topic,
  342. char *resClass,
  343. char *resName)
  344. {
  345. char *val;
  346. char **valArray = NULL;
  347. char *token;
  348. char *nextC;
  349. /* Get the resource value which is a single string where the elements are
  350. separated by white space. */
  351. val = GetResourceString (db, topic, resClass, resName);
  352. if (val != NULL)
  353. {
  354. nextC = val;
  355. while (nextC && *nextC != '\0')
  356. {
  357. nextC = _DtHelpGetNxtToken (nextC, &token);
  358. if (token == NULL)
  359. {
  360. _DtHelpCeFreeStringArray (valArray);
  361. return NULL;
  362. }
  363. /* If the token is a '\0' then we are at the end and we can quit.
  364. If the token is a '\n', then ignore it. Otherwise the token
  365. is an element of the array we are building. */
  366. if (*token == '\0')
  367. break;
  368. if (*token != '\n')
  369. {
  370. valArray = (char **) _DtHelpCeAddPtrToArray (
  371. (void **) valArray, (void *) token);
  372. /*
  373. * If we malloc'ed ourselves out of existence...stop processing.
  374. */
  375. if (!valArray)
  376. break;
  377. }
  378. }
  379. }
  380. return (valArray);
  381. }
  382. /******************************************************************************
  383. * Function: char *GetNextKeyword (char *str, char *delimiter,
  384. char **ret_token)
  385. *
  386. * Parameters: str Specifies the string which is being parsed.
  387. * delimiter Specifies the delimiter string.
  388. * ret_token Returns the string found between the current
  389. * position of the input string and the delimiter
  390. * string.
  391. *
  392. * Newline or Null strings are
  393. * not owned by the caller.
  394. *
  395. * Otherwise, the memory for the returned
  396. * token is owned by the caller.
  397. *
  398. * Return Value: Returns a pointer to the next unparsed character
  399. * in the input string. A NULL value indicates an error.
  400. *
  401. * Purpose: Load the keywords associated with a volume.
  402. *
  403. ******************************************************************************/
  404. static char *
  405. GetNextKeyword (
  406. char *str,
  407. char *delimiter,
  408. char **ret_token )
  409. {
  410. int len;
  411. char *start;
  412. char *token;
  413. short done;
  414. /* Find the next token in the string. The parsing rules are:
  415. - The deliminater (except for \n) separate a keyword from
  416. its list of location IDs.
  417. - \n is a token itself.
  418. - The \0 at the end of the string is a token.
  419. */
  420. /* Skip all of the whitespace and \n. */
  421. (void) _DtHelpCeStrspn (str, " \n", MB_CUR_MAX, &len);
  422. str += len;
  423. /* Str is pointing at the start of the next keyword. Depending on the
  424. type of token, malloc the memory and copy the token value. */
  425. if (*str == '\0')
  426. token = str;
  427. else
  428. {
  429. /* We have some non-whitespace characters. Find the end of */
  430. /* them and copy them into new memory. */
  431. start = str;
  432. done = False;
  433. do
  434. {
  435. _DtHelpCeStrchr (str, delimiter, MB_CUR_MAX, &str);
  436. if (str)
  437. {
  438. if (strncmp (str, delimiter, strlen(delimiter)) == 0)
  439. done = True;
  440. else
  441. str++;
  442. }
  443. else /* if (str == NULL) */
  444. {
  445. str = start + strlen (start);
  446. done = -1;
  447. }
  448. } while (!done);
  449. token = (char *) malloc ((str - start + 1) * sizeof (char));
  450. if (token)
  451. {
  452. strncpy (token, start, str - start);
  453. *(token + (str - start)) = '\0';
  454. if (done == True)
  455. str += strlen (delimiter);
  456. }
  457. }
  458. *ret_token = token;
  459. return (str);
  460. }
  461. /******************************************************************************
  462. * Function: int TopicFilename (_DtHelpVolume vol, char *topic,
  463. * char **retFname);
  464. *
  465. * Parameters: vol Specifies the loaded volume
  466. * topic Specifies locationID for the topic
  467. * retFname Returns the name of the file where the topic
  468. * is located.
  469. * Memory own by caller:
  470. * retFname
  471. *
  472. * Returns: 0 if successful, -1 if a failure occurs
  473. *
  474. * Purpose: Get the name of the file where a topic is stored.
  475. *
  476. ******************************************************************************/
  477. static int
  478. TopicFilename (
  479. _DtHelpVolume vol,
  480. char *topic,
  481. char **retFname)
  482. {
  483. CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
  484. *retFname = GetFilenameResource (ccdfVol, topic);
  485. if (*retFname == NULL && errno == CEErrorIllegalResource)
  486. errno = CEErrorMissingFilenameRes;
  487. else
  488. *retFname = CreateFileName (vol->volFile, *retFname);
  489. if (*retFname == NULL)
  490. return (-1);
  491. return (0);
  492. }
  493. /******************************************************************************
  494. * Function: int TopicFilepos (_DtHelpVolume vol, char *topic, int *retFpos);
  495. *
  496. * Parameters: vol Specifies the loaded volume
  497. * topic The locationID for the topic
  498. * retFpos Returns the byte offset of the start of the
  499. * topic within the topic file.
  500. *
  501. * Return Value: 0 if successful, -1 if a failure occurs.
  502. *
  503. * Purpose: Determine the position of the topic within the topic file.
  504. ******************************************************************************/
  505. static int
  506. TopicFilepos (
  507. _DtHelpVolume vol,
  508. char *topic,
  509. int *retFpos)
  510. {
  511. CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
  512. if (GetResourceInt(ccdfVol->volDb, topic, "Filepos", "filepos", retFpos) == -1)
  513. return -1;
  514. return (0);
  515. }
  516. /******************************************************************************
  517. * Function: int GetResourceInt (XrmDatabase db, char *topic,
  518. * char *resClass, char *resName, ret_value)
  519. *
  520. * Parameters: db Specifies the handle to a resource database.
  521. * topic Specifies the topic whose resource value is
  522. * desired. If 'topic' is NULL, the
  523. * desired resource is for the volume and
  524. * not a specific topic.
  525. * resClass Specifies the resource class name.
  526. * resName Specifies the resource name.
  527. * ret_value Returns an int containing the resource value.
  528. *
  529. * Return Value: 0 if successful, -1 if a failure occurs.
  530. *
  531. * Purpose: Get an integer-valued resource for a volume or topic.
  532. ******************************************************************************/
  533. static int
  534. GetResourceInt (
  535. XrmDatabase db,
  536. char *topic,
  537. char *resClass,
  538. char *resName,
  539. int *ret_value)
  540. {
  541. char *retValue;
  542. retValue = GetResourceString (db, topic, resClass, resName);
  543. if (retValue)
  544. {
  545. *ret_value = atoi(retValue);
  546. return 0;
  547. }
  548. return -1;
  549. }
  550. /******************************************************************************
  551. * Function: static int LocationIDTopic (_DtHelpVolume vol, char *locId,
  552. * char **retTopic);
  553. *
  554. * Parameters: vol Specifies the loaded volume
  555. * locId Specifies locationID desired.
  556. * retTopic Returns the locationID of the topic with
  557. * contains 'locId'. This string IS owned by
  558. * the caller and must be freed when no longer
  559. * needed.
  560. *
  561. * Return Value: 0 if successful, -1 if a failure occurs
  562. *
  563. * Purpose: Find which topic contains a specified locationID.
  564. ******************************************************************************/
  565. static int
  566. LocationIDTopic (
  567. _DtHelpVolume vol,
  568. char *locId,
  569. char **retTopic)
  570. {
  571. char **allTopics;
  572. char **nextTopic;
  573. char **locIdList = NULL;
  574. char **nextLocId;
  575. CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
  576. *retTopic = NULL;
  577. if (_DtHelpCeGetCcdfVolIdList (vol, &allTopics) != 0)
  578. return (-1);
  579. /* Check whether the locationID is a topic. */
  580. for (nextTopic = allTopics;
  581. nextTopic && *nextTopic != NULL && *retTopic == NULL; nextTopic++)
  582. {
  583. if (_DtHelpCeStrCaseCmpLatin1 (locId, *nextTopic) == 0)
  584. *retTopic = strdup(*nextTopic);
  585. }
  586. /* For each topic in the volume, get its list of locationIDs and
  587. check them. NOTE: This code should be separated out into a public
  588. _DtTopicLocationIDs function. Then we would have a function
  589. that returns all of the locationIDs in a topic, which might
  590. prove useful someday. */
  591. if (*retTopic == NULL)
  592. {
  593. for (nextTopic = allTopics;
  594. nextTopic && *nextTopic != NULL && *retTopic == NULL;
  595. nextTopic++)
  596. {
  597. /*
  598. * valid to get a NULL on this resource, but not good
  599. */
  600. errno = 0;
  601. locIdList = GetResourceStringArray (ccdfVol->volDb, *nextTopic,
  602. "LocationIDs", "locationIDs");
  603. if (locIdList == NULL && errno != CEErrorIllegalResource)
  604. break;
  605. errno = CEErrorLocIdNotFound;
  606. for (nextLocId = locIdList;
  607. nextLocId != NULL && *nextLocId != NULL && *retTopic == NULL;
  608. nextLocId++)
  609. {
  610. if (_DtHelpCeStrCaseCmpLatin1 (locId, *nextLocId) == 0)
  611. *retTopic = strdup(*nextTopic);
  612. }
  613. if (NULL != locIdList)
  614. _DtHelpCeFreeStringArray (locIdList);
  615. }
  616. }
  617. if (*retTopic == NULL)
  618. return (-1);
  619. return (0);
  620. }
  621. /******************************************************************************
  622. * Semi-Public CCDF Access Functions
  623. ******************************************************************************/
  624. /*****************************************************************************
  625. * Function: int _DtHelpCeGetCcdfIdPath (_DtHelpVolume vol, char *target_id,
  626. * char ***ret_ids)
  627. *
  628. * Parameters: vol Specifies the loaded volume
  629. * target_id The target location ID of a topic.
  630. * ret_ids Returns a null terminated list of the
  631. * location IDs of the topics between the
  632. * target and the parent.
  633. * Memory own by caller:
  634. * ret_ids
  635. *
  636. * Returns: The number of ids in the list, -1 for failure. If successful,
  637. * the list will always contain at least the target_id.
  638. *
  639. * Purpose: Get the list of ids between the top and the target id.
  640. *
  641. *****************************************************************************/
  642. int
  643. _DtHelpCeGetCcdfIdPath (
  644. _DtHelpVolume vol,
  645. char *target_id,
  646. char ***ret_ids )
  647. {
  648. int idCount = 0;
  649. char *topicId = NULL;
  650. if (LocationIDTopic (vol, target_id, &topicId) != 0)
  651. return -1;
  652. idCount = GetTopicMap (vol, topicId, 0, ret_ids);
  653. if (idCount != -1)
  654. {
  655. /*
  656. * include this entry in the count
  657. */
  658. (*ret_ids)[idCount] = topicId;
  659. idCount++;
  660. }
  661. else
  662. {
  663. free(topicId);
  664. }
  665. return idCount;
  666. } /* End _DtHelpCeGetCcdfIdPath */
  667. /******************************************************************************
  668. * Function: int _DtHelpCeGetCcdfTopicChildren (_DtHelpVolume vol,
  669. * char *topic_id,
  670. * char ***topics);
  671. *
  672. * Parameters: vol Specifies the loaded volume.
  673. * topic_id Specifies the topic for which children
  674. * are desired.
  675. * retTopics Returns a NULL-terminated string array
  676. * containing the list of children for a topic
  677. * in the volume. This array is owned by the
  678. * caller and should be freed (using
  679. * _DtHelpCeFreeStringArray) when not needed.
  680. *
  681. * Memory own by caller:
  682. * retTopics
  683. *
  684. * Return Value: > 0 if successful, -1 if a failure occurs
  685. *
  686. * Purpose: Get the list of children for a topic contained in a volume.
  687. *
  688. ******************************************************************************/
  689. int
  690. _DtHelpCeGetCcdfTopicChildren (
  691. _DtHelpVolume vol,
  692. char *topic_id,
  693. char ***retTopics)
  694. {
  695. int result;
  696. int count = 0;
  697. char *parent_id;
  698. char *child_id;
  699. char *topicId = NULL;
  700. char **topicList;
  701. if (LocationIDTopic (vol, topic_id, &topicId) != 0)
  702. return -1;
  703. /*
  704. * initialize the return value
  705. */
  706. *retTopics = NULL;
  707. /*
  708. * get the list
  709. */
  710. result = _DtHelpCeGetCcdfVolIdList (vol, &topicList);
  711. if (result == 0)
  712. {
  713. while (*topicList && result == 0)
  714. {
  715. result = _DtHelpCeGetCcdfTopicParent (vol, *topicList, &parent_id);
  716. if (result == 0)
  717. {
  718. /*
  719. * It's legal to get a NULL back - means the topic
  720. * doesn't have a parent.
  721. */
  722. if (parent_id &&
  723. _DtHelpCeStrCaseCmpLatin1 (parent_id, topicId) == 0)
  724. {
  725. child_id = strdup (*topicList);
  726. if (child_id)
  727. {
  728. *retTopics = (char **) _DtHelpCeAddPtrToArray (
  729. (void **) (*retTopics), child_id);
  730. if (*retTopics == NULL)
  731. result = -1;
  732. count++;
  733. }
  734. else
  735. {
  736. /*
  737. * lost the previous data...stop processing.
  738. */
  739. if (*retTopics)
  740. _DtHelpCeFreeStringArray (*retTopics);
  741. *retTopics = NULL;
  742. result = -1;
  743. break;
  744. }
  745. }
  746. }
  747. else
  748. {
  749. /*
  750. * problems processing TopicParent...stop processing
  751. */
  752. if (*retTopics)
  753. _DtHelpCeFreeStringArray (*retTopics);
  754. *retTopics = NULL;
  755. break;
  756. }
  757. topicList++;
  758. }
  759. }
  760. /*
  761. * free the duplicate string
  762. */
  763. if (topicId)
  764. free (topicId);
  765. if (result != 0)
  766. return -1;
  767. return count;
  768. }
  769. /******************************************************************************
  770. * Function: int _DtHelpCeGetCcdfVolIdList (_DtHelpVolume vol, char ***topics);
  771. *
  772. * Parameters: vol Specifies the loaded volume.
  773. * topics Returns a NULL-terminated string array
  774. * containing the ordered list of topics in the
  775. * volume. This array is NOT owned by the caller
  776. * and should only be read or copied.
  777. *
  778. * Return Value: 0 if successful, -1 if a failure occurs
  779. *
  780. * Purpose: Get the list of topics contained in a volume.
  781. *
  782. ******************************************************************************/
  783. int
  784. _DtHelpCeGetCcdfVolIdList (
  785. _DtHelpVolume vol,
  786. char ***retTopics)
  787. {
  788. CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
  789. if (ccdfVol->topicList == NULL)
  790. ccdfVol->topicList = GetResourceStringArray (ccdfVol->volDb, NULL,
  791. "TopicList", "topicList");
  792. *retTopics = ccdfVol->topicList;
  793. if (*retTopics == NULL)
  794. {
  795. if (errno == CEErrorIllegalResource)
  796. errno = CEErrorMissingTopicList;
  797. return -1;
  798. }
  799. return 0;
  800. }
  801. /*****************************************************************************
  802. * Function: int _DtHelpCeFindCcdfId (_DtHelpVolume vol, char *target_id,
  803. * char *ret_name, int *ret_offset)
  804. *
  805. * Parameters: vol Specifies the loaded volume
  806. * target_id Specifies target location ID
  807. * ret_name Returns a null terminated string
  808. * containing a fully qualified path to
  809. * the file that contains 'target_id'.
  810. * ret_offset Returns the offset into 'ret_name'
  811. * to the topic that contains 'target_id'.
  812. *
  813. * Memory own by caller:
  814. * ret_name
  815. *
  816. * Returns: True if successful, False if a failure occurs
  817. *
  818. * Purpose: Find which topic contains a specified locationID.
  819. *****************************************************************************/
  820. int
  821. _DtHelpCeFindCcdfId (
  822. _DtHelpVolume vol,
  823. char *target_id,
  824. char **ret_name,
  825. int *ret_offset )
  826. {
  827. char newTarget[65];
  828. char *topicId = NULL;
  829. int found = False;
  830. snprintf(newTarget, sizeof(newTarget), "%s", target_id);
  831. _DtHelpCeUpperCase(newTarget);
  832. /*
  833. * find the location id for the topic that contains the
  834. * target_id (they may be the same). Then find the filename
  835. * and offset.
  836. */
  837. if (TopicFilename (vol, newTarget, ret_name) == -1)
  838. {
  839. /*
  840. * if the reason TopicFilename failed was because we couldn't
  841. * find a resource, try looking for it in the LocationIDs.
  842. */
  843. if (errno == CEErrorMissingFilenameRes &&
  844. LocationIDTopic (vol, newTarget, &topicId) == 0 &&
  845. TopicFilename (vol, topicId, ret_name) == 0 &&
  846. TopicFilepos (vol, topicId, ret_offset) == 0)
  847. found = True;
  848. }
  849. else if (TopicFilepos (vol, newTarget, ret_offset) != -1)
  850. found = True;
  851. /*
  852. * free the excess strings
  853. */
  854. if (topicId)
  855. free (topicId);
  856. return found;
  857. } /* End _DtHelpCeFindCcdfId */
  858. /******************************************************************************
  859. * Function: int _DtHelpCeGetCcdfTopicParent (_DtHelpVolume vol, char *topic,
  860. * char **retParent)
  861. *
  862. * Parameters: vol Specifies the loaded volume
  863. * topic Specifies locationID for the topic
  864. * retParent Returns a string with the locationID for the
  865. * topic which is the parent of the current
  866. * topic. If the current topic is at the top of
  867. * the hierarchy, a NULL string is returned.
  868. * This string is NOT owned by the caller and
  869. * should only be read or copied.
  870. *
  871. * Return Value: 0 if successful, -1 if a failure occurs
  872. *
  873. * Purpose: Find the parent for a topic.
  874. ******************************************************************************/
  875. int
  876. _DtHelpCeGetCcdfTopicParent (
  877. _DtHelpVolume vol,
  878. char *topic,
  879. char **retParent)
  880. {
  881. CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
  882. /* Don't return an error if we are asked for the parent of NULL, or if
  883. the topic has no parent. Both cases are valid (and used by
  884. _DtTopicPath). */
  885. *retParent = NULL;
  886. if (topic != NULL)
  887. {
  888. errno = 0;
  889. *retParent = GetResourceString(ccdfVol->volDb, topic,
  890. "Parent", "parent");
  891. if (*retParent == NULL && errno != CEErrorIllegalResource)
  892. return -1;
  893. }
  894. return (0);
  895. }
  896. /*****************************************************************************
  897. * Function: int _DtHelpCeGetCcdfKeywordList (_DtHelpVolume vol,
  898. *
  899. * Parameters: vol Specifies the volume whose keywords need to be
  900. * loaded from disk. Once loaded, they can be
  901. * accessed through the fields of the volume structure.
  902. *
  903. * Return Value: 0 if successful, -1 if a failure occurs
  904. *
  905. * Purpose: Load the keywords associated with a volume.
  906. *****************************************************************************/
  907. int
  908. _DtHelpCeGetCcdfKeywordList (
  909. _DtHelpVolume vol)
  910. {
  911. XrmDatabase kDb;
  912. char *keywordString;
  913. char *nextC;
  914. char **topics;
  915. char ***topicList;
  916. char *token;
  917. char *currKeyword;
  918. CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
  919. /* Generate the name of the keyword file. Because volume files
  920. use the ".hv" suffix and keyword files use ".hvk", all we have
  921. to do is append a "k". */
  922. /*
  923. * If the keywordFile is non-null, we've already tried once.
  924. * We want to try again, because the problem may have been
  925. * fixed without restarting this process.
  926. *
  927. * But don't malloc memory again, because we'll leak memory.
  928. * Just use what is given.
  929. */
  930. if (ccdfVol->keywordFile == NULL)
  931. {
  932. ccdfVol->keywordFile = (char *) malloc (strlen (vol->volFile) + 2);
  933. if (ccdfVol->keywordFile == NULL)
  934. return -1;
  935. strcpy (ccdfVol->keywordFile, vol->volFile);
  936. strcat (ccdfVol->keywordFile, "k");
  937. }
  938. /*
  939. * check to see if it exists
  940. */
  941. if (access (ccdfVol->keywordFile, R_OK) == -1)
  942. return -1;
  943. /* Load the keyword file and get the "keywords" resource. */
  944. kDb = XrmGetFileDatabase (ccdfVol->keywordFile);
  945. if (kDb == NULL)
  946. return -1;
  947. keywordString = GetResourceString (kDb, NULL, "Keywords", "keywords");
  948. if (keywordString == NULL)
  949. {
  950. if (errno == CEErrorIllegalResource)
  951. errno = CEErrorMissingKeywordsRes;
  952. XrmDestroyDatabase (kDb);
  953. return (-1);
  954. }
  955. /* Now parse the string into the appropriate arrays. The string has the
  956. following syntax:
  957. keyword1<\>topic topic topic ... \n
  958. keyword2<\>topic topic topic ... \n
  959. */
  960. nextC = (char *) keywordString;
  961. while (nextC && *nextC)
  962. {
  963. /* Get the next keyword. If we find newlines while looking for
  964. the keyword, throw them away. If the next token is the end-
  965. of-file (\0), quit.
  966. */
  967. nextC = GetNextKeyword (nextC, "<\\>", &token);
  968. if (token == NULL)
  969. {
  970. XrmDestroyDatabase (kDb);
  971. if (vol->keywords)
  972. {
  973. _DtHelpCeFreeStringArray (vol->keywords);
  974. vol->keywords = NULL;
  975. }
  976. if (vol->keywordTopics)
  977. {
  978. for (topicList = vol->keywordTopics;
  979. topicList; topicList++)
  980. _DtHelpCeFreeStringArray (*topicList);
  981. free (vol->keywordTopics);
  982. vol->keywordTopics = NULL;
  983. }
  984. return -1;
  985. }
  986. if (*token == '\0')
  987. break;
  988. /* We have the next keyword. Hang onto it and add it to the list
  989. once we get the array of topics. We don't add it yet because if
  990. there are no topics we want to throw it away. (Silently ignoring
  991. keywords which specify no topics is an undocumented feature.) */
  992. currKeyword = token;
  993. /* Now get the list of topics. */
  994. topics = NULL;
  995. do
  996. {
  997. nextC = _DtHelpGetNxtToken (nextC, &token);
  998. if (token == NULL)
  999. {
  1000. XrmDestroyDatabase (kDb);
  1001. if (vol->keywords)
  1002. {
  1003. _DtHelpCeFreeStringArray (vol->keywords);
  1004. vol->keywords = NULL;
  1005. }
  1006. if (vol->keywordTopics)
  1007. {
  1008. for (topicList = vol->keywordTopics;
  1009. topicList; topicList++)
  1010. _DtHelpCeFreeStringArray (*topicList);
  1011. free (vol->keywordTopics);
  1012. vol->keywordTopics = NULL;
  1013. }
  1014. if (topics)
  1015. _DtHelpCeFreeStringArray (topics);
  1016. free (currKeyword);
  1017. return -1;
  1018. }
  1019. /* If the next token is end-of-file (\0), then quit. Otherwise
  1020. if the next token is a newline, then we have gotten all of
  1021. the topics and we need to add them to the array of topic
  1022. arrays. The final choice is that the token is a string so
  1023. we add it to the current array of topics. */
  1024. if (*token == '\0')
  1025. break;
  1026. if (*token == '\n')
  1027. {
  1028. /* We have all of the topics. If the array of topics isn't
  1029. empty, add everything to the data structures.
  1030. */
  1031. if (topics != NULL)
  1032. {
  1033. vol->keywords = (char **) _DtHelpCeAddPtrToArray (
  1034. (void **) vol->keywords,
  1035. (void *) currKeyword);
  1036. vol->keywordTopics = (char ***) _DtHelpCeAddPtrToArray (
  1037. (void **) vol->keywordTopics,
  1038. (void *) topics);
  1039. /*
  1040. * If we just malloc'ed ourselves out of existence...
  1041. * stop here.
  1042. */
  1043. if (vol->keywords == 0 || vol->keywordTopics == 0)
  1044. {
  1045. XrmDestroyDatabase (kDb);
  1046. if (vol->keywords)
  1047. {
  1048. free (currKeyword);
  1049. _DtHelpCeFreeStringArray (vol->keywords);
  1050. _DtHelpCeFreeStringArray (topics);
  1051. vol->keywords = NULL;
  1052. }
  1053. if (vol->keywordTopics)
  1054. {
  1055. for (topicList = vol->keywordTopics;
  1056. topicList; topicList++)
  1057. _DtHelpCeFreeStringArray (*topicList);
  1058. free (vol->keywordTopics);
  1059. vol->keywordTopics = NULL;
  1060. }
  1061. return -1;
  1062. }
  1063. }
  1064. break;
  1065. }
  1066. else
  1067. {
  1068. topics = (char **) _DtHelpCeAddPtrToArray ((void **) topics,
  1069. (void *) token);
  1070. /*
  1071. * If we just malloc'ed ourselves out of existence
  1072. * stop here.
  1073. */
  1074. if (topics == NULL)
  1075. {
  1076. free (currKeyword);
  1077. XrmDestroyDatabase (kDb);
  1078. if (vol->keywords)
  1079. {
  1080. _DtHelpCeFreeStringArray (vol->keywords);
  1081. vol->keywords = NULL;
  1082. }
  1083. if (vol->keywordTopics != NULL)
  1084. {
  1085. for (topicList = vol->keywordTopics;
  1086. topicList; topicList++)
  1087. _DtHelpCeFreeStringArray (*topicList);
  1088. free (vol->keywordTopics);
  1089. vol->keywordTopics = NULL;
  1090. }
  1091. return -1;
  1092. }
  1093. }
  1094. } while (nextC && *nextC);
  1095. if (topics == NULL)
  1096. free (currKeyword);
  1097. }
  1098. XrmDestroyDatabase (kDb);
  1099. return (0);
  1100. } /* End _DtHelpCeGetCcdfKeywordList */
  1101. /******************************************************************************
  1102. * Function: int _DtHelpCeGetCcdfVolumeAbstract (_DtHelpVolume vol,
  1103. * char **abstract);
  1104. *
  1105. * Parameters: vol Specifies the loaded volume.
  1106. * abstract Returns the abstract of the volume. This string
  1107. * is owned by the caller and should be freed.
  1108. *
  1109. * Return Value: 0 if successful, -1 if a failure occurs
  1110. *
  1111. * Purpose: Get the abstract of a volume.
  1112. ******************************************************************************/
  1113. int
  1114. _DtHelpCeGetCcdfVolumeAbstract (
  1115. _DtHelpVolume vol,
  1116. char **retAbs)
  1117. {
  1118. char *abstract;
  1119. CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
  1120. *retAbs = NULL;
  1121. abstract = GetResourceString(ccdfVol->volDb, NULL, "Abstract", "abstract");
  1122. if (abstract == NULL)
  1123. {
  1124. if (errno == CEErrorIllegalResource)
  1125. errno = CEErrorMissingAbstractRes;
  1126. }
  1127. else
  1128. *retAbs = strdup(abstract);
  1129. if (*retAbs == NULL)
  1130. return (-1);
  1131. return (0);
  1132. }
  1133. /*****************************************************************************
  1134. * Function: int _DtHelpCeMapCcdfTargetToId (_DtHelpVolume vol,
  1135. * char *target_id,
  1136. * char *ret_id)
  1137. *
  1138. * Parameters: vol Specifies the loaded volume
  1139. * target_id Specifies target location ID
  1140. * ret_id Returns the id containing the target_id.
  1141. * This memory *IS NOT* owned by the caller.
  1142. * And *MAY* point to target_id.
  1143. *
  1144. * Returns: 0 if successful, -1 if a failure occurs
  1145. *
  1146. * Purpose: Find which topic contains a specified locationID.
  1147. *
  1148. *****************************************************************************/
  1149. int
  1150. _DtHelpCeMapCcdfTargetToId (
  1151. _DtHelpVolume vol,
  1152. const char *target_id,
  1153. char **ret_id)
  1154. {
  1155. char newTarget[128];
  1156. CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
  1157. snprintf(newTarget, sizeof(newTarget), "%s", target_id);
  1158. _DtHelpCeUpperCase(newTarget);
  1159. /*
  1160. * find the location id for the topic that contains the
  1161. * target_id (they may be the same). Then find the filename
  1162. * and offset.
  1163. */
  1164. *ret_id = (char *) target_id;
  1165. if (GetFilenameResource (ccdfVol, newTarget) == NULL)
  1166. {
  1167. /*
  1168. * if the reason TopicFilename failed was because we couldn't
  1169. * find a resource, try looking for it in the LocationIDs.
  1170. */
  1171. if (errno == CEErrorIllegalResource &&
  1172. LocationIDTopic (vol, newTarget, ret_id) == 0 &&
  1173. GetFilenameResource(ccdfVol, *ret_id) != NULL)
  1174. return 0;
  1175. return -1;
  1176. }
  1177. return 0;
  1178. } /* End _DtHelpCeMapCcdfTargetToId */
  1179. /*****************************************************************************
  1180. * Function: char * _DtHelpCeGetCcdfVolLocale (_DtHelpVolume vol)
  1181. *
  1182. * Parameters: vol Specifies the loaded volume
  1183. *
  1184. * Returns: The pointer to the locale string if successful. Otherwise
  1185. * NULL.
  1186. *
  1187. * Purpose: Get the locale of the specified volume.
  1188. * Returns the locale in a unix specific format
  1189. * - locale[_ter][.charset] - This memory is owned by
  1190. * the caller.
  1191. *
  1192. *****************************************************************************/
  1193. char *
  1194. _DtHelpCeGetCcdfVolLocale (
  1195. _DtHelpVolume vol)
  1196. {
  1197. char *locale, *ptr, *resStr;
  1198. char *mResStr = NULL;
  1199. char *mLang = NULL;
  1200. char *lang = "C";
  1201. char *defLocale = "C.UTF-8";
  1202. CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
  1203. errno = 0;
  1204. /* resStr is owned by the volume Xrm database; don't free */
  1205. resStr = GetResourceString(ccdfVol->volDb, NULL, "CharSet", "charSet");
  1206. if (resStr == NULL || *resStr == '\0')
  1207. {
  1208. locale = strdup(defLocale);
  1209. goto done;
  1210. }
  1211. mResStr = strdup(resStr);
  1212. if (_DtHelpCeStrchr(mResStr, ".", 1, &ptr) == 0)
  1213. {
  1214. *ptr++ = '\0';
  1215. if (mResStr == NULL || *mResStr == '\0' || ptr == NULL || *ptr == '\0')
  1216. locale = strdup(defLocale);
  1217. else
  1218. locale = strdup(resStr);
  1219. goto done;
  1220. }
  1221. mLang = _DtHelpGetLocale();
  1222. if (_DtHelpCeStrrchr(mLang, ".", 1, &ptr) == 0)
  1223. {
  1224. *ptr = '\0';
  1225. if (mLang != NULL && *mLang != '\0') lang = mLang;
  1226. }
  1227. asprintf(&locale, "%s.%s", lang, resStr);
  1228. done:
  1229. free(mLang);
  1230. free(mResStr);
  1231. return locale;
  1232. } /* End _DtHelpCeGetCcdfVolLocale */
  1233. /*****************************************************************************
  1234. * Function: int _DtHelpCeGetCcdfDocStamp (_DtHelpVolume vol, char **ret_doc,
  1235. * char **ret_time)
  1236. *
  1237. * Parameters: volume Specifies the loaded volume
  1238. * ret_doc Returns the doc id.
  1239. * ret_time Returns the time stamp.
  1240. *
  1241. * Memory: Caller owns the string in ret_doc and ret_time.
  1242. *
  1243. * Returns: 0 if successful, -2 if the volume does not contain
  1244. * one or the other, -1 if any other failure.
  1245. *
  1246. * Purpose: Get doc id and time stamp of a volume.
  1247. *
  1248. *****************************************************************************/
  1249. int
  1250. _DtHelpCeGetCcdfDocStamp (
  1251. _DtHelpVolume vol,
  1252. char **ret_doc,
  1253. char **ret_time)
  1254. {
  1255. int result;
  1256. struct stat buf;
  1257. result = -2;
  1258. if (ret_doc != NULL)
  1259. *ret_doc = NULL;
  1260. if (ret_time != NULL)
  1261. {
  1262. result = -1;
  1263. *ret_time = NULL;
  1264. if (stat(vol->volFile, &buf) == 0)
  1265. {
  1266. *ret_time = (char *) malloc (sizeof(time_t) * 3 + 1);
  1267. if (*ret_time != NULL)
  1268. {
  1269. sprintf(*ret_time, "%u", (unsigned) buf.st_mtime);
  1270. return -2;
  1271. }
  1272. }
  1273. }
  1274. return result;
  1275. } /* End _DtHelpCeGetCcdfDocStamp */
  1276. /******************************************************************************
  1277. * Function: static int _DtHelpCeGetCcdfTopTopic (_DtHelpVolume vol,
  1278. * char **topic);
  1279. *
  1280. * Parameters: vol Specifies the loaded volume.
  1281. * topic Returns the locationID for the top topic in
  1282. * the volume hierarchy. This string is NOT
  1283. * owned by the caller and should only be read or
  1284. * copied.
  1285. *
  1286. * Return Value: 0 if successful, -1 if a failure occurs
  1287. *
  1288. * Purpose: Get the top topic of a volume.
  1289. ******************************************************************************/
  1290. int
  1291. _DtHelpCeGetCcdfTopTopic (
  1292. _DtHelpVolume vol,
  1293. char **retTopic)
  1294. {
  1295. CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
  1296. *retTopic = GetResourceString(ccdfVol->volDb, NULL, "TopTopic", "topTopic");
  1297. if (*retTopic == NULL)
  1298. {
  1299. if (errno == CEErrorIllegalResource)
  1300. errno = CEErrorMissingTopTopicRes;
  1301. return (-1);
  1302. }
  1303. return (0);
  1304. }
  1305. /******************************************************************************
  1306. * Function: char *_DtHelpCeGetCcdfVolTitle (_DtHelpVolume vol);
  1307. *
  1308. * Parameters: vol Specifies the loaded volume.
  1309. *
  1310. * Return Value: The title if successful, NULL otherwise.
  1311. * The caller *DOES NOT* own the memory returned
  1312. * and *MUST NOT* modify the memory.
  1313. *
  1314. * Purpose: Get the title of a volume.
  1315. *
  1316. ******************************************************************************/
  1317. char *
  1318. _DtHelpCeGetCcdfVolTitle (
  1319. _DtHelpVolume vol)
  1320. {
  1321. CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
  1322. return (GetResourceString (ccdfVol->volDb, NULL, "Title", "title"));
  1323. }
  1324. /******************************************************************************
  1325. * Function: int _DtHelpCeGetCcdfVolumeTitle (_DtHelpVolume vol);
  1326. *
  1327. * Parameters: vol Specifies the loaded volume.
  1328. *
  1329. * Return Value: The title if successful, NULL otherwise.
  1330. * The caller *DOES NOT* own the memory returned
  1331. * and *MUST NOT* modify the memory.
  1332. *
  1333. * Purpose: Get the title of a volume.
  1334. *
  1335. ******************************************************************************/
  1336. int
  1337. _DtHelpCeGetCcdfVolumeTitle (
  1338. _DtHelpVolume vol,
  1339. char **ret_title)
  1340. {
  1341. *ret_title = _DtHelpCeGetCcdfVolTitle(vol);
  1342. if (*ret_title == NULL)
  1343. {
  1344. if (errno == CEErrorIllegalResource)
  1345. errno = CEErrorMissingTitleRes;
  1346. return (-1);
  1347. }
  1348. *ret_title = strdup(*ret_title);
  1349. if (*ret_title == NULL)
  1350. {
  1351. errno = CEErrorMalloc;
  1352. return (-1);
  1353. }
  1354. return (0);
  1355. }
  1356. /******************************************************************************
  1357. * Function: int _DtHelpCeOpenCcdfVolume (_DtHelpVolume vol);
  1358. *
  1359. * Parameters: vol Specifies the loaded volume.
  1360. *
  1361. * Return Value:
  1362. *
  1363. * Purpose: Open a CCDF help volume
  1364. *
  1365. ******************************************************************************/
  1366. int
  1367. _DtHelpCeOpenCcdfVolume (
  1368. _DtHelpVolume vol)
  1369. {
  1370. struct stat buf;
  1371. CcdfVolumePtr ccdfVol;
  1372. ccdfVol = (struct _CcdfVolumeInfo *) malloc(sizeof(struct _CcdfVolumeInfo));
  1373. if (ccdfVol != NULL)
  1374. {
  1375. *ccdfVol = DefaultCcdfVol;
  1376. ccdfVol->volDb = XrmGetFileDatabase(vol->volFile);
  1377. if (ccdfVol->volDb != NULL)
  1378. {
  1379. (void) stat(vol->volFile, &buf);
  1380. vol->check_time = buf.st_mtime;
  1381. vol->vols.ccdf_vol = (CcdfVolumeHandle) ccdfVol;
  1382. return 0;
  1383. }
  1384. free(ccdfVol);
  1385. }
  1386. return -1;
  1387. }
  1388. /******************************************************************************
  1389. * Function: void _DtHelpCeCloseCcdfVolume (_DtHelpVolume vol);
  1390. *
  1391. * Parameters: vol Specifies the loaded volume.
  1392. *
  1393. * Return Value:
  1394. *
  1395. * Purpose: Open a CCDF help volume
  1396. *
  1397. ******************************************************************************/
  1398. void
  1399. _DtHelpCeCloseCcdfVolume (
  1400. _DtHelpVolume vol)
  1401. {
  1402. CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
  1403. if (ccdfVol->volDb != NULL)
  1404. XrmDestroyDatabase (ccdfVol->volDb);
  1405. if (ccdfVol->topicList != NULL)
  1406. _DtHelpCeFreeStringArray (ccdfVol->topicList);
  1407. if (ccdfVol->keywordFile != NULL)
  1408. free (ccdfVol->keywordFile);
  1409. free(ccdfVol);
  1410. }
  1411. /******************************************************************************
  1412. * Function: int _DtHelpCeRereadCcdfVolume (_DtHelpVolume vol);
  1413. *
  1414. * Parameters: vol Specifies the loaded volume.
  1415. *
  1416. * Return Value:
  1417. *
  1418. * Purpose: Reread a CCDF volume.
  1419. *
  1420. ******************************************************************************/
  1421. int
  1422. _DtHelpCeRereadCcdfVolume (
  1423. _DtHelpVolume vol)
  1424. {
  1425. CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
  1426. if (ccdfVol->volDb != NULL)
  1427. XrmDestroyDatabase (ccdfVol->volDb);
  1428. if (ccdfVol->topicList != NULL)
  1429. _DtHelpCeFreeStringArray (ccdfVol->topicList);
  1430. if (ccdfVol->keywordFile != NULL)
  1431. free (ccdfVol->keywordFile);
  1432. ccdfVol->topicList = NULL;
  1433. ccdfVol->keywordFile = NULL;
  1434. ccdfVol->volDb = XrmGetFileDatabase(vol->volFile);
  1435. if (ccdfVol->volDb != NULL)
  1436. return 0;
  1437. return -1;
  1438. }
  1439. /******************************************************************************
  1440. * Function: char *_DtHelpCeGetResourceString (XrmDatabase db, char *topic,
  1441. * char *resClass, char *resName)
  1442. *
  1443. * Parameters: db Specifies the handle to a resource database.
  1444. * topic Specifies the topic whose resource value is
  1445. * desired. If 'topic' is NULL, the
  1446. * desired resource is for the volume and
  1447. * not a specific topic.
  1448. * resClass Specifies the resource class name.
  1449. * resName Specifies the resource name.
  1450. *
  1451. * Return Value: Returns the desired resource as string.
  1452. * This string is NOT owned by the caller and
  1453. * should only be read or copied.
  1454. *
  1455. * Returns NULL if an error occurs.
  1456. *
  1457. * errno Values: CEErrorMalloc
  1458. * CEErrorIllegalResource If the resource is not in
  1459. * the database or if the
  1460. * resource NULL
  1461. *
  1462. * Purpose: Get a resource value for a volume or topic.
  1463. *
  1464. ******************************************************************************/
  1465. char *
  1466. _DtHelpCeGetResourceString (
  1467. XrmDatabase db,
  1468. char *topic,
  1469. char *resClass,
  1470. char *resName)
  1471. {
  1472. return (GetResourceString(db, topic, resClass, resName));
  1473. }
  1474. /******************************************************************************
  1475. * Function: char **_DtHelpCeGetResourceStringArray (XrmDatabase db,
  1476. * char *topic, char *resClass, char *resName)
  1477. *
  1478. * Parameters: db Specifies the handle to a resource database.
  1479. * topic Specifies the topic whose resource value
  1480. * is desired. If 'topic' is NULL, the
  1481. * desired resource is for the volume and
  1482. * not a specific topic.
  1483. * resClass Specifies the resource class name.
  1484. * resName Specifies the resource name.
  1485. *
  1486. * Return Value: Returns a NULL-terminated string array
  1487. * containing the value of the desired resource.
  1488. * The elements of the array are the strings of
  1489. * non-whitespace characters in the resource value.
  1490. * This array is owned by the caller and should be
  1491. * freed (using _DtHelpCeFreeStringArray) when not
  1492. * needed.
  1493. *
  1494. * Purpose: Get am array-valued resource for a volume or topic.
  1495. *
  1496. ******************************************************************************/
  1497. char **
  1498. _DtHelpCeGetResourceStringArray (
  1499. XrmDatabase db,
  1500. char *topic,
  1501. char *resClass,
  1502. char *resName)
  1503. {
  1504. return (GetResourceStringArray(db, topic, resClass, resName));
  1505. }