2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
23 /* $XConsortium: AccessCCDF.c /main/10 1996/11/01 10:09:50 drk $ */
24 /************************************<+>*************************************
25 ****************************************************************************
29 ** Project: Cde 1.0 Help Library
31 ** Description: This body of code handles the access routines to the
32 ** legacy CCDF Help files.
35 ** (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
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.
43 ****************************************************************************
44 ************************************<+>*************************************/
55 #include <X11/Xresource.h>
63 * Canvas Engine includes
66 #include "CanvasSegP.h"
71 #include "CanvasError.h"
74 #include "AccessCCDFP.h"
75 #include "AccessCCDFI.h"
76 #include "FormatUtilI.h"
77 #include "StringFuncsI.h"
78 #include "HelpXlate.h"
83 /******** Private Defines ********/
84 #define LIST_INCREMENT 10
86 /******** End Private Defines ********/
88 /******** Private Function Declarations ********/
89 static char *CreateFileName(
92 static int GetResourceInt (
98 static char *GetResourceString (
103 static char **GetResourceStringArray (
108 static int GetTopicMap (
113 /******** End Private Function Declarations ********/
115 /******** Private Macro Declarations ********/
116 #define GetCcdfVolumePtr(vol) \
117 ((CcdfVolumePtr)((vol)->vols.ccdf_vol))
119 #define GetFilenameResource(vol, topic) \
120 GetResourceString((vol)->volDb, topic, "Filename", "filename")
122 /******** End Private Macro Declarations ********/
124 /******************************************************************************
126 * Private variables used within this file.
128 *******************************************************************************/
129 static const char *Period = ".";
130 static const char *Slash = "/";
131 static const char *VolumeStr = "Volume.";
132 static const char *volumeStr = "Volume.";
134 static const struct _CcdfVolumeInfo DefaultCcdfVol =
136 NULL, /* XrmDatabase volDb; */
137 NULL, /* char **topicList; */
138 NULL, /* char *keywordFile; */
141 /******************************************************************************
143 ******************************************************************************/
144 /******************************************************************************
145 * Function: CreateFileName (char *path, char *string)
147 * Parameters: path Specifies the path to the volume.
148 * string Specifies the file's name including the extension.
150 * Memory owned by caller:
153 * Returns: Non null ptr if successful, null if a failure occurs.
155 * errno Values: CEErrorMalloc
157 * Purpose: Creates a fully qualified path to a file based on the
160 ******************************************************************************/
169 if ((MB_CUR_MAX == 1 || mblen (string, MB_CUR_MAX) == 1) && *string != '/'
173 * determine the length of the path.
175 _DtHelpCeStrrchr (path, Slash, MB_CUR_MAX, &ptr);
177 len = ptr - path + 1;
181 * malloc the room for the path and file name.
183 ptr = (char *) malloc (len + strlen(string) + 1);
188 * copy the name into the destination string.
192 strncat (ptr, path, len);
193 strcat (ptr, string);
199 /*****************************************************************************
200 * Function: GetTopicMap (_DtHelpVolume vol, char *target_id,
201 * int level, char ***ret_ids)
203 * Parameters: vol Specifies the loaded volume
204 * target_id The target location ID of a topic.
205 * level The levels progressed so far. It is
206 * used to calculate how much memory
207 * is required to hold all the ids.
208 * ret_ids Returns a null terminated list of the
209 * location IDs of the topics between the
210 * target and the parent.
211 * Memory own by caller:
214 * Returns: The number of ids put in the list so far,
217 * errno Values: CEErrorMalloc
220 * Purpose: Recursively build a list of id strings containing all of
221 * the target_id's ancestors.
223 *****************************************************************************/
235 if (_DtHelpCeGetCcdfTopicParent (vol, target_id, &idParent) == 0)
238 * still not at the top
242 result = GetTopicMap (vol, idParent, level + 1, ret_ids);
245 (*ret_ids)[result] = strdup (idParent);
251 *ret_ids = (char **) malloc (sizeof(char *) * (level + 2));
252 if ((*ret_ids) == NULL)
255 (*ret_ids)[level + 1] = NULL;
262 } /* End GetTopicMap */
264 /******************************************************************************
265 * Function: char *GetResourceString (XrmDatabase db, char *topic,
266 * char *resClass, char *resName)
268 * Parameters: db Specifies the handle to a resource database.
269 * topic Specifies the topic whose resource value is
270 * desired. If 'topic' is NULL, the
271 * desired resource is for the volume and
272 * not a specific topic.
273 * resClass Specifies the resource class name.
274 * resName Specifies the resource name.
276 * Return Value: Returns the desired resource as string.
277 * This string is NOT owned by the caller and
278 * should only be read or copied.
280 * Returns NULL if an error occurs.
282 * errno Values: CEErrorMalloc
283 * CEErrorIllegalResource If the resource is not in
284 * the database or if the
287 * Purpose: Get a resource value for a volume or topic.
289 ******************************************************************************/
307 topicLen = strlen(topic) + strlen(Period);
309 len = strlen(volumeStr) + topicLen + 1;
310 fullResName = (char *) malloc (len + strlen (resName));
311 fullResClass = (char *) malloc (len + strlen (resClass));
312 if (fullResName != NULL && fullResClass != NULL)
314 strcpy (fullResName, volumeStr);
315 strcpy (fullResClass, VolumeStr);
319 strcat (fullResName, topic);
320 strcat (fullResName, Period);
322 strcat (fullResClass, topic);
323 strcat (fullResClass, Period);
326 strcat (fullResName , resName);
327 strcat (fullResClass, resClass);
330 errno = CEErrorMalloc;
333 if (fullResClass != NULL && fullResName != NULL)
335 if (XrmGetResource (db, fullResClass, fullResName, &resType, &resValue)
336 && strlen ((char *) resValue.addr))
337 retVal = (char *) resValue.addr;
339 errno = CEErrorIllegalResource;
350 /******************************************************************************
351 * Function: char **GetResourceStringArray (XrmDatabase db, char *topic,
352 * char *resClass, char *resName)
354 * Parameters: db Specifies the handle to a resource database.
355 * topic Specifies the topic whose resource value is
356 * desired. If 'topic' is NULL, the
357 * desired resource is for the volume and
358 * not a specific topic.
359 * resClass Specifies the resource class name.
360 * resName Specifies the resource name.
362 * Return Value: Returns a NULL-terminated string array containing the
363 * value of the desired resource. The elements of the
364 * array are the strings of non-whitespace characters in
365 * the resource value. This array is owned by the caller
366 * and should be freed (using _DtHelpCeFreeStringArray) when
369 * Purpose: Get am array-valued resource for a volume or topic.
371 ******************************************************************************/
373 GetResourceStringArray (
380 char **valArray = NULL;
384 /* Get the resource value which is a single string where the elements are
385 separated by white space. */
386 val = GetResourceString (db, topic, resClass, resName);
390 while (nextC && *nextC != '\0')
392 nextC = _DtHelpGetNxtToken (nextC, &token);
396 _DtHelpCeFreeStringArray (valArray);
400 /* If the token is a '\0' then we are at the end and we can quit.
401 If the token is a '\n', then ignore it. Otherwise the token
402 is an element of the array we are building. */
408 valArray = (char **) _DtHelpCeAddPtrToArray (
409 (void **) valArray, (void *) token);
411 * If we malloc'ed ourselves out of existence...stop processing.
422 /******************************************************************************
423 * Function: char *GetNextKeyword (char *str, char *delimiter,
426 * Parameters: str Specifies the string which is being parsed.
427 * delimiter Specifies the delimiter string.
428 * ret_token Returns the string found between the current
429 * position of the input string and the delimiter
432 * Newline or Null strings are
433 * not owned by the caller.
435 * Otherwise, the memory for the returned
436 * token is owned by the caller.
438 * Return Value: Returns a pointer to the next unparsed character
439 * in the input string. A NULL value indicates an error.
441 * Purpose: Load the keywords associated with a volume.
443 ******************************************************************************/
455 /* Find the next token in the string. The parsing rules are:
457 - The deliminater (except for \n) separate a keyword from
458 its list of location IDs.
459 - \n is a token itself.
460 - The \0 at the end of the string is a token.
463 /* Skip all of the whitespace and \n. */
464 (void) _DtHelpCeStrspn (str, " \n", MB_CUR_MAX, &len);
467 /* Str is pointing at the start of the next keyword. Depending on the
468 type of token, malloc the memory and copy the token value. */
474 /* We have some non-whitespace characters. Find the end of */
475 /* them and copy them into new memory. */
480 _DtHelpCeStrchr (str, delimiter, MB_CUR_MAX, &str);
483 if (strncmp (str, delimiter, strlen(delimiter)) == 0)
488 else /* if (str == NULL) */
490 str = start + strlen (start);
495 token = (char *) malloc ((str - start + 1) * sizeof (char));
498 strncpy (token, start, str - start);
499 *(token + (str - start)) = '\0';
501 str += strlen (delimiter);
509 /******************************************************************************
510 * Function: int TopicFilename (_DtHelpVolume vol, char *topic,
513 * Parameters: vol Specifies the loaded volume
514 * topic Specifies locationID for the topic
515 * retFname Returns the name of the file where the topic
517 * Memory own by caller:
520 * Returns: 0 if successful, -1 if a failure occurs
522 * Purpose: Get the name of the file where a topic is stored.
524 ******************************************************************************/
531 CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
533 *retFname = GetFilenameResource (ccdfVol, topic);
534 if (*retFname == NULL && errno == CEErrorIllegalResource)
535 errno = CEErrorMissingFilenameRes;
537 *retFname = CreateFileName (vol->volFile, *retFname);
539 if (*retFname == NULL)
545 /******************************************************************************
546 * Function: int TopicFilepos (_DtHelpVolume vol, char *topic, int *retFpos);
548 * Parameters: vol Specifies the loaded volume
549 * topic The locationID for the topic
550 * retFpos Returns the byte offset of the start of the
551 * topic within the topic file.
553 * Return Value: 0 if successful, -1 if a failure occurs.
555 * Purpose: Determine the position of the topic within the topic file.
556 ******************************************************************************/
563 CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
565 if (GetResourceInt(ccdfVol->volDb, topic, "Filepos", "filepos", retFpos) == -1)
571 /******************************************************************************
572 * Function: int GetResourceInt (XrmDatabase db, char *topic,
573 * char *resClass, char *resName, ret_value)
575 * Parameters: db Specifies the handle to a resource database.
576 * topic Specifies the topic whose resource value is
577 * desired. If 'topic' is NULL, the
578 * desired resource is for the volume and
579 * not a specific topic.
580 * resClass Specifies the resource class name.
581 * resName Specifies the resource name.
582 * ret_value Returns an int containing the resource value.
584 * Return Value: 0 if successful, -1 if a failure occurs.
586 * Purpose: Get an integer-valued resource for a volume or topic.
587 ******************************************************************************/
598 retValue = GetResourceString (db, topic, resClass, resName);
601 *ret_value = atoi(retValue);
608 /******************************************************************************
609 * Function: static int LocationIDTopic (_DtHelpVolume vol, char *locId,
612 * Parameters: vol Specifies the loaded volume
613 * locId Specifies locationID desired.
614 * retTopic Returns the locationID of the topic with
615 * contains 'locId'. This string IS owned by
616 * the caller and must be freed when no longer
619 * Return Value: 0 if successful, -1 if a failure occurs
621 * Purpose: Find which topic contains a specified locationID.
622 ******************************************************************************/
631 char **locIdList = NULL;
634 CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
638 if (_DtHelpCeGetCcdfVolIdList (vol, &allTopics) != 0)
641 /* Check whether the locationID is a topic. */
642 for (nextTopic = allTopics;
643 nextTopic && *nextTopic != NULL && *retTopic == NULL; nextTopic++)
645 if (_DtHelpCeStrCaseCmpLatin1 (locId, *nextTopic) == 0)
646 *retTopic = strdup(*nextTopic);
649 /* For each topic in the volume, get its list of locationIDs and
650 check them. NOTE: This code should be separated out into a public
651 _DtTopicLocationIDs function. Then we would have a function
652 that returns all of the locationIDs in a topic, which might
653 prove useful someday. */
655 if (*retTopic == NULL)
657 for (nextTopic = allTopics;
658 nextTopic && *nextTopic != NULL && *retTopic == NULL;
662 * valid to get a NULL on this resource, but not good
665 locIdList = GetResourceStringArray (ccdfVol->volDb, *nextTopic,
666 "LocationIDs", "locationIDs");
667 if (locIdList == NULL && errno != CEErrorIllegalResource)
670 errno = CEErrorLocIdNotFound;
671 for (nextLocId = locIdList;
672 nextLocId != NULL && *nextLocId != NULL && *retTopic == NULL;
675 if (_DtHelpCeStrCaseCmpLatin1 (locId, *nextLocId) == 0)
676 *retTopic = strdup(*nextTopic);
679 if (NULL != locIdList)
680 _DtHelpCeFreeStringArray (locIdList);
684 if (*retTopic == NULL)
690 /******************************************************************************
691 * Semi-Public CCDF Access Functions
692 ******************************************************************************/
693 /*****************************************************************************
694 * Function: int _DtHelpCeGetCcdfIdPath (_DtHelpVolume vol, char *target_id,
697 * Parameters: vol Specifies the loaded volume
698 * target_id The target location ID of a topic.
699 * ret_ids Returns a null terminated list of the
700 * location IDs of the topics between the
701 * target and the parent.
702 * Memory own by caller:
705 * Returns: The number of ids in the list, -1 for failure. If successful,
706 * the list will always contain at least the target_id.
708 * Purpose: Get the list of ids between the top and the target id.
710 *****************************************************************************/
712 _DtHelpCeGetCcdfIdPath (
718 char *topicId = NULL;
720 if (LocationIDTopic (vol, target_id, &topicId) != 0)
723 idCount = GetTopicMap (vol, topicId, 0, ret_ids);
727 * include this entry in the count
729 (*ret_ids)[idCount] = topicId;
739 } /* End _DtHelpCeGetCcdfIdPath */
741 /******************************************************************************
742 * Function: int _DtHelpCeGetCcdfTopicChildren (_DtHelpVolume vol,
746 * Parameters: vol Specifies the loaded volume.
747 * topic_id Specifies the topic for which children
749 * retTopics Returns a NULL-terminated string array
750 * containing the list of children for a topic
751 * in the volume. This array is owned by the
752 * caller and should be freed (using
753 * _DtHelpCeFreeStringArray) when not needed.
755 * Memory own by caller:
758 * Return Value: > 0 if successful, -1 if a failure occurs
760 * Purpose: Get the list of children for a topic contained in a volume.
762 ******************************************************************************/
764 _DtHelpCeGetCcdfTopicChildren (
773 char *topicId = NULL;
776 if (LocationIDTopic (vol, topic_id, &topicId) != 0)
780 * initialize the return value
787 result = _DtHelpCeGetCcdfVolIdList (vol, &topicList);
790 while (*topicList && result == 0)
792 result = _DtHelpCeGetCcdfTopicParent (vol, *topicList, &parent_id);
796 * It's legal to get a NULL back - means the topic
797 * doesn't have a parent.
800 _DtHelpCeStrCaseCmpLatin1 (parent_id, topicId) == 0)
802 child_id = strdup (*topicList);
805 *retTopics = (char **) _DtHelpCeAddPtrToArray (
806 (void **) (*retTopics), child_id);
807 if (*retTopics == NULL)
814 * lost the previous data...stop processing.
817 _DtHelpCeFreeStringArray (*retTopics);
827 * problems processing TopicParent...stop processing
830 _DtHelpCeFreeStringArray (*retTopics);
839 * free the duplicate string
850 /******************************************************************************
851 * Function: int _DtHelpCeGetCcdfVolIdList (_DtHelpVolume vol, char ***topics);
853 * Parameters: vol Specifies the loaded volume.
854 * topics Returns a NULL-terminated string array
855 * containing the ordered list of topics in the
856 * volume. This array is NOT owned by the caller
857 * and should only be read or copied.
859 * Return Value: 0 if successful, -1 if a failure occurs
861 * Purpose: Get the list of topics contained in a volume.
863 ******************************************************************************/
865 _DtHelpCeGetCcdfVolIdList (
869 CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
871 if (ccdfVol->topicList == NULL)
872 ccdfVol->topicList = GetResourceStringArray (ccdfVol->volDb, NULL,
873 "TopicList", "topicList");
874 *retTopics = ccdfVol->topicList;
875 if (*retTopics == NULL)
877 if (errno == CEErrorIllegalResource)
878 errno = CEErrorMissingTopicList;
885 /*****************************************************************************
886 * Function: int _DtHelpCeFindCcdfId (_DtHelpVolume vol, char *target_id,
887 * char *ret_name, int *ret_offset)
889 * Parameters: vol Specifies the loaded volume
890 * target_id Specifies target location ID
891 * ret_name Returns a null terminated string
892 * containing a fully qualified path to
893 * the file that contains 'target_id'.
894 * ret_offset Returns the offset into 'ret_name'
895 * to the topic that contains 'target_id'.
897 * Memory own by caller:
900 * Returns: True if successful, False if a failure occurs
902 * Purpose: Find which topic contains a specified locationID.
903 *****************************************************************************/
905 _DtHelpCeFindCcdfId (
912 char *topicId = NULL;
915 snprintf(newTarget, sizeof(newTarget), "%s", target_id);
916 _DtHelpCeUpperCase(newTarget);
919 * find the location id for the topic that contains the
920 * target_id (they may be the same). Then find the filename
923 if (TopicFilename (vol, newTarget, ret_name) == -1)
926 * if the reason TopicFilename failed was because we couldn't
927 * find a resource, try looking for it in the LocationIDs.
929 if (errno == CEErrorMissingFilenameRes &&
930 LocationIDTopic (vol, newTarget, &topicId) == 0 &&
931 TopicFilename (vol, topicId, ret_name) == 0 &&
932 TopicFilepos (vol, topicId, ret_offset) == 0)
935 else if (TopicFilepos (vol, newTarget, ret_offset) != -1)
939 * free the excess strings
946 } /* End _DtHelpCeFindCcdfId */
948 /******************************************************************************
949 * Function: int _DtHelpCeGetCcdfTopicParent (_DtHelpVolume vol, char *topic,
952 * Parameters: vol Specifies the loaded volume
953 * topic Specifies locationID for the topic
954 * retParent Returns a string with the locationID for the
955 * topic which is the parent of the current
956 * topic. If the current topic is at the top of
957 * the hierarchy, a NULL string is returned.
958 * This string is NOT owned by the caller and
959 * should only be read or copied.
961 * Return Value: 0 if successful, -1 if a failure occurs
963 * Purpose: Find the parent for a topic.
964 ******************************************************************************/
966 _DtHelpCeGetCcdfTopicParent (
971 CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
973 /* Don't return an error if we are asked for the parent of NULL, or if
974 the topic has no parent. Both cases are valid (and used by
981 *retParent = GetResourceString(ccdfVol->volDb, topic,
983 if (*retParent == NULL && errno != CEErrorIllegalResource)
990 /*****************************************************************************
991 * Function: int _DtHelpCeGetCcdfKeywordList (_DtHelpVolume vol,
993 * Parameters: vol Specifies the volume whose keywords need to be
994 * loaded from disk. Once loaded, they can be
995 * accessed through the fields of the volume structure.
997 * Return Value: 0 if successful, -1 if a failure occurs
999 * Purpose: Load the keywords associated with a volume.
1000 *****************************************************************************/
1002 _DtHelpCeGetCcdfKeywordList (
1006 char *keywordString;
1012 CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
1014 /* Generate the name of the keyword file. Because volume files
1015 use the ".hv" suffix and keyword files use ".hvk", all we have
1016 to do is append a "k". */
1018 * If the keywordFile is non-null, we've already tried once.
1019 * We want to try again, because the problem may have been
1020 * fixed without restarting this process.
1022 * But don't malloc memory again, because we'll leak memory.
1023 * Just use what is given.
1025 if (ccdfVol->keywordFile == NULL)
1027 ccdfVol->keywordFile = (char *) malloc (strlen (vol->volFile) + 2);
1028 if (ccdfVol->keywordFile == NULL)
1031 strcpy (ccdfVol->keywordFile, vol->volFile);
1032 strcat (ccdfVol->keywordFile, "k");
1036 * check to see if it exists
1038 if (access (ccdfVol->keywordFile, R_OK) == -1)
1041 /* Load the keyword file and get the "keywords" resource. */
1042 kDb = XrmGetFileDatabase (ccdfVol->keywordFile);
1046 keywordString = GetResourceString (kDb, NULL, "Keywords", "keywords");
1047 if (keywordString == NULL)
1049 if (errno == CEErrorIllegalResource)
1050 errno = CEErrorMissingKeywordsRes;
1051 XrmDestroyDatabase (kDb);
1055 /* Now parse the string into the appropriate arrays. The string has the
1058 keyword1<\>topic topic topic ... \n
1059 keyword2<\>topic topic topic ... \n
1062 nextC = (char *) keywordString;
1064 while (nextC && *nextC)
1067 /* Get the next keyword. If we find newlines while looking for
1068 the keyword, throw them away. If the next token is the end-
1071 nextC = GetNextKeyword (nextC, "<\\>", &token);
1075 XrmDestroyDatabase (kDb);
1078 _DtHelpCeFreeStringArray (vol->keywords);
1079 vol->keywords = NULL;
1081 if (vol->keywordTopics)
1083 for (topicList = vol->keywordTopics;
1084 topicList; topicList++)
1085 _DtHelpCeFreeStringArray (*topicList);
1086 free (vol->keywordTopics);
1087 vol->keywordTopics = NULL;
1095 /* We have the next keyword. Hang onto it and add it to the list
1096 once we get the array of topics. We don't add it yet because if
1097 there are no topics we want to throw it away. (Silently ignoring
1098 keywords which specify no topics is an undocumented feature.) */
1100 currKeyword = token;
1102 /* Now get the list of topics. */
1106 nextC = _DtHelpGetNxtToken (nextC, &token);
1110 XrmDestroyDatabase (kDb);
1113 _DtHelpCeFreeStringArray (vol->keywords);
1114 vol->keywords = NULL;
1116 if (vol->keywordTopics)
1118 for (topicList = vol->keywordTopics;
1119 topicList; topicList++)
1120 _DtHelpCeFreeStringArray (*topicList);
1121 free (vol->keywordTopics);
1122 vol->keywordTopics = NULL;
1125 _DtHelpCeFreeStringArray (topics);
1131 /* If the next token is end-of-file (\0), then quit. Otherwise
1132 if the next token is a newline, then we have gotten all of
1133 the topics and we need to add them to the array of topic
1134 arrays. The final choice is that the token is a string so
1135 we add it to the current array of topics. */
1141 /* We have all of the topics. If the array of topics isn't
1142 empty, add everything to the data structures.
1146 vol->keywords = (char **) _DtHelpCeAddPtrToArray (
1147 (void **) vol->keywords,
1148 (void *) currKeyword);
1149 vol->keywordTopics = (char ***) _DtHelpCeAddPtrToArray (
1150 (void **) vol->keywordTopics,
1153 * If we just malloc'ed ourselves out of existence...
1156 if (vol->keywords == 0 || vol->keywordTopics == 0)
1158 XrmDestroyDatabase (kDb);
1162 _DtHelpCeFreeStringArray (vol->keywords);
1163 _DtHelpCeFreeStringArray (topics);
1164 vol->keywords = NULL;
1166 if (vol->keywordTopics)
1168 for (topicList = vol->keywordTopics;
1169 topicList; topicList++)
1170 _DtHelpCeFreeStringArray (*topicList);
1171 free (vol->keywordTopics);
1172 vol->keywordTopics = NULL;
1181 topics = (char **) _DtHelpCeAddPtrToArray ((void **) topics,
1184 * If we just malloc'ed ourselves out of existence
1190 XrmDestroyDatabase (kDb);
1193 _DtHelpCeFreeStringArray (vol->keywords);
1194 vol->keywords = NULL;
1196 if (vol->keywordTopics != NULL)
1198 for (topicList = vol->keywordTopics;
1199 topicList; topicList++)
1200 _DtHelpCeFreeStringArray (*topicList);
1201 free (vol->keywordTopics);
1202 vol->keywordTopics = NULL;
1209 } while (nextC && *nextC);
1215 XrmDestroyDatabase (kDb);
1219 } /* End _DtHelpCeGetCcdfKeywordList */
1221 /******************************************************************************
1222 * Function: int _DtHelpCeGetCcdfVolumeAbstract (_DtHelpVolume vol,
1225 * Parameters: vol Specifies the loaded volume.
1226 * abstract Returns the abstract of the volume. This string
1227 * is owned by the caller and should be freed.
1229 * Return Value: 0 if successful, -1 if a failure occurs
1231 * Purpose: Get the abstract of a volume.
1232 ******************************************************************************/
1234 _DtHelpCeGetCcdfVolumeAbstract (
1239 CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
1242 abstract = GetResourceString(ccdfVol->volDb, NULL, "Abstract", "abstract");
1243 if (abstract == NULL)
1245 if (errno == CEErrorIllegalResource)
1246 errno = CEErrorMissingAbstractRes;
1249 *retAbs = strdup(abstract);
1251 if (*retAbs == NULL)
1257 /*****************************************************************************
1258 * Function: int _DtHelpCeMapCcdfTargetToId (_DtHelpVolume vol,
1262 * Parameters: vol Specifies the loaded volume
1263 * target_id Specifies target location ID
1264 * ret_id Returns the id containing the target_id.
1265 * This memory *IS NOT* owned by the caller.
1266 * And *MAY* point to target_id.
1268 * Returns: 0 if successful, -1 if a failure occurs
1270 * Purpose: Find which topic contains a specified locationID.
1272 *****************************************************************************/
1274 _DtHelpCeMapCcdfTargetToId (
1276 const char *target_id,
1279 char newTarget[128];
1280 CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
1282 snprintf(newTarget, sizeof(newTarget), "%s", target_id);
1283 _DtHelpCeUpperCase(newTarget);
1286 * find the location id for the topic that contains the
1287 * target_id (they may be the same). Then find the filename
1290 *ret_id = (char *) target_id;
1291 if (GetFilenameResource (ccdfVol, newTarget) == NULL)
1294 * if the reason TopicFilename failed was because we couldn't
1295 * find a resource, try looking for it in the LocationIDs.
1297 if (errno == CEErrorIllegalResource &&
1298 LocationIDTopic (vol, newTarget, ret_id) == 0 &&
1299 GetFilenameResource(ccdfVol, *ret_id) != NULL)
1307 } /* End _DtHelpCeMapCcdfTargetToId */
1309 /*****************************************************************************
1310 * Function: char * _DtHelpCeGetCcdfVolLocale (_DtHelpVolume vol)
1312 * Parameters: vol Specifies the loaded volume
1314 * Returns: The pointer to the locale string if successful. Otherwise
1317 * Purpose: Get the locale of the specified volume.
1318 * Returns the locale in a unix specific format
1319 * - locale[_ter][.charset] - This memory is owned by
1322 *****************************************************************************/
1324 _DtHelpCeGetCcdfVolLocale (
1327 char *locale = NULL;
1329 CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
1332 locale = GetResourceString(ccdfVol->volDb, NULL, "CharSet", "charSet");
1333 if (_DtHelpCeStrchr(locale, ".", 1, &charSet) != 0)
1336 _DtHelpCeXlateOpToStdLocale(DtLCX_OPER_CCDF,charSet,&locale,NULL,NULL);
1337 /* charset is owned by the volume Xrm database; don't free */
1339 else if (NULL != locale)
1340 locale = strdup(locale);
1344 } /* End _DtHelpCeGetCcdfVolLocale */
1346 /*****************************************************************************
1347 * Function: int _DtHelpCeGetCcdfDocStamp (_DtHelpVolume vol, char **ret_doc,
1350 * Parameters: volume Specifies the loaded volume
1351 * ret_doc Returns the doc id.
1352 * ret_time Returns the time stamp.
1354 * Memory: Caller owns the string in ret_doc and ret_time.
1356 * Returns: 0 if successful, -2 if the volume does not contain
1357 * one or the other, -1 if any other failure.
1359 * Purpose: Get doc id and time stamp of a volume.
1361 *****************************************************************************/
1363 _DtHelpCeGetCcdfDocStamp (
1372 if (ret_doc != NULL)
1375 if (ret_time != NULL)
1379 if (stat(vol->volFile, &buf) == 0)
1381 *ret_time = (char *) malloc (sizeof(time_t) * 3 + 1);
1382 if (*ret_time != NULL)
1384 sprintf(*ret_time, "%u", (unsigned) buf.st_mtime);
1391 } /* End _DtHelpCeGetCcdfDocStamp */
1393 /******************************************************************************
1394 * Function: static int _DtHelpCeGetCcdfTopTopic (_DtHelpVolume vol,
1397 * Parameters: vol Specifies the loaded volume.
1398 * topic Returns the locationID for the top topic in
1399 * the volume hierarchy. This string is NOT
1400 * owned by the caller and should only be read or
1403 * Return Value: 0 if successful, -1 if a failure occurs
1405 * Purpose: Get the top topic of a volume.
1406 ******************************************************************************/
1408 _DtHelpCeGetCcdfTopTopic (
1412 CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
1414 *retTopic = GetResourceString(ccdfVol->volDb, NULL, "TopTopic", "topTopic");
1415 if (*retTopic == NULL)
1417 if (errno == CEErrorIllegalResource)
1418 errno = CEErrorMissingTopTopicRes;
1425 /******************************************************************************
1426 * Function: char *_DtHelpCeGetCcdfVolTitle (_DtHelpVolume vol);
1428 * Parameters: vol Specifies the loaded volume.
1430 * Return Value: The title if successful, NULL otherwise.
1431 * The caller *DOES NOT* own the memory returned
1432 * and *MUST NOT* modify the memory.
1434 * Purpose: Get the title of a volume.
1436 ******************************************************************************/
1438 _DtHelpCeGetCcdfVolTitle (
1441 CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
1443 return (GetResourceString (ccdfVol->volDb, NULL, "Title", "title"));
1446 /******************************************************************************
1447 * Function: int _DtHelpCeGetCcdfVolumeTitle (_DtHelpVolume vol);
1449 * Parameters: vol Specifies the loaded volume.
1451 * Return Value: The title if successful, NULL otherwise.
1452 * The caller *DOES NOT* own the memory returned
1453 * and *MUST NOT* modify the memory.
1455 * Purpose: Get the title of a volume.
1457 ******************************************************************************/
1459 _DtHelpCeGetCcdfVolumeTitle (
1463 *ret_title = _DtHelpCeGetCcdfVolTitle(vol);
1465 if (*ret_title == NULL)
1467 if (errno == CEErrorIllegalResource)
1468 errno = CEErrorMissingTitleRes;
1472 *ret_title = strdup(*ret_title);
1473 if (*ret_title == NULL)
1475 errno = CEErrorMalloc;
1481 /******************************************************************************
1482 * Function: int _DtHelpCeOpenCcdfVolume (_DtHelpVolume vol);
1484 * Parameters: vol Specifies the loaded volume.
1488 * Purpose: Open a CCDF help volume
1490 ******************************************************************************/
1492 _DtHelpCeOpenCcdfVolume (
1496 CcdfVolumePtr ccdfVol;
1498 ccdfVol = (struct _CcdfVolumeInfo *) malloc(sizeof(struct _CcdfVolumeInfo));
1499 if (ccdfVol != NULL)
1501 *ccdfVol = DefaultCcdfVol;
1502 ccdfVol->volDb = XrmGetFileDatabase(vol->volFile);
1503 if (ccdfVol->volDb != NULL)
1505 (void) stat(vol->volFile, &buf);
1506 vol->check_time = buf.st_mtime;
1507 vol->vols.ccdf_vol = (CcdfVolumeHandle) ccdfVol;
1516 /******************************************************************************
1517 * Function: void _DtHelpCeCloseCcdfVolume (_DtHelpVolume vol);
1519 * Parameters: vol Specifies the loaded volume.
1523 * Purpose: Open a CCDF help volume
1525 ******************************************************************************/
1527 _DtHelpCeCloseCcdfVolume (
1530 CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
1532 if (ccdfVol->volDb != NULL)
1533 XrmDestroyDatabase (ccdfVol->volDb);
1535 if (ccdfVol->topicList != NULL)
1536 _DtHelpCeFreeStringArray (ccdfVol->topicList);
1538 if (ccdfVol->keywordFile != NULL)
1539 free (ccdfVol->keywordFile);
1544 /******************************************************************************
1545 * Function: int _DtHelpCeRereadCcdfVolume (_DtHelpVolume vol);
1547 * Parameters: vol Specifies the loaded volume.
1551 * Purpose: Reread a CCDF volume.
1553 ******************************************************************************/
1555 _DtHelpCeRereadCcdfVolume (
1558 CcdfVolumePtr ccdfVol = GetCcdfVolumePtr(vol);
1560 if (ccdfVol->volDb != NULL)
1561 XrmDestroyDatabase (ccdfVol->volDb);
1563 if (ccdfVol->topicList != NULL)
1564 _DtHelpCeFreeStringArray (ccdfVol->topicList);
1566 if (ccdfVol->keywordFile != NULL)
1567 free (ccdfVol->keywordFile);
1569 ccdfVol->topicList = NULL;
1570 ccdfVol->keywordFile = NULL;
1571 ccdfVol->volDb = XrmGetFileDatabase(vol->volFile);
1573 if (ccdfVol->volDb != NULL)
1579 /******************************************************************************
1580 * Function: char *_DtHelpCeGetResourceString (XrmDatabase db, char *topic,
1581 * char *resClass, char *resName)
1583 * Parameters: db Specifies the handle to a resource database.
1584 * topic Specifies the topic whose resource value is
1585 * desired. If 'topic' is NULL, the
1586 * desired resource is for the volume and
1587 * not a specific topic.
1588 * resClass Specifies the resource class name.
1589 * resName Specifies the resource name.
1591 * Return Value: Returns the desired resource as string.
1592 * This string is NOT owned by the caller and
1593 * should only be read or copied.
1595 * Returns NULL if an error occurs.
1597 * errno Values: CEErrorMalloc
1598 * CEErrorIllegalResource If the resource is not in
1599 * the database or if the
1602 * Purpose: Get a resource value for a volume or topic.
1604 ******************************************************************************/
1606 _DtHelpCeGetResourceString (
1612 return (GetResourceString(db, topic, resClass, resName));
1615 /******************************************************************************
1616 * Function: char **_DtHelpCeGetResourceStringArray (XrmDatabase db,
1617 * char *topic, char *resClass, char *resName)
1619 * Parameters: db Specifies the handle to a resource database.
1620 * topic Specifies the topic whose resource value
1621 * is desired. If 'topic' is NULL, the
1622 * desired resource is for the volume and
1623 * not a specific topic.
1624 * resClass Specifies the resource class name.
1625 * resName Specifies the resource name.
1627 * Return Value: Returns a NULL-terminated string array
1628 * containing the value of the desired resource.
1629 * The elements of the array are the strings of
1630 * non-whitespace characters in the resource value.
1631 * This array is owned by the caller and should be
1632 * freed (using _DtHelpCeFreeStringArray) when not
1635 * Purpose: Get am array-valued resource for a volume or topic.
1637 ******************************************************************************/
1639 _DtHelpCeGetResourceStringArray (
1645 return (GetResourceStringArray(db, topic, resClass, resName));