1 /* $TOG: FormatCCDF.c /main/23 1999/10/14 15:06:28 mgreess $ */
2 /************************************<+>*************************************
3 ****************************************************************************
7 ** Project: Unix Desktop Help
9 ** Description: This code formats an file in CCDF (Cache Creek
10 ** Distribution Format) into internal format.
12 ** (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
14 ** (c) Copyright 1993, 1994 Hewlett-Packard Company
15 ** (c) Copyright 1993, 1994 International Business Machines Corp.
16 ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
17 ** (c) Copyright 1993, 1994 Novell, Inc.
21 ****************************************************************************
22 ************************************<+>*************************************/
31 #include <sys/utsname.h>
40 #include <X11/Xresource.h>
47 * Canvas Engine includes
50 #include "CanvasSegP.h"
60 #include "AccessCCDFI.h"
61 #include "CanvasError.h"
63 #include "CvStringI.h"
64 #include "CvtToArrayP.h"
65 #include "FontAttrI.h"
66 #include "FormatUtilI.h"
67 #include "FormatCCDFI.h"
68 #include "CCDFUtilI.h"
69 #include "HelpXlate.h"
70 #include "StringFuncsI.h"
72 extern char *_DtHelpGetLocale(void);
77 /******************************************************************************
78 * Private variables and defines.
79 *****************************************************************************/
80 #define BUFF_SIZE 1024
84 #define CCDF_LINK_JUMP_REUSE 0
85 #define CCDF_LINK_JUMP_NEW 1
86 #define CCDF_LINK_DEFINITION 2
87 #define CCDF_LINK_EXECUTE 3
88 #define CCDF_LINK_MAN_PAGE 4
89 #define CCDF_LINK_APP_DEFINE 5
91 #define IsTypeHyperText(x) (((x) & _DtCvHYPER_TEXT) ? 1 : 0)
92 #define IsTypeNewLine(x) (((x) & _DtCvNEW_LINE) ? 1 : 0)
93 #define NextAvailSeg(x) (NULL != x.list ? &(x.list[x.cnt]) : NULL)
95 /******************************************************************************
97 ******************************************************************************/
98 typedef struct _segList {
104 typedef struct _formatVariables {
116 char *topic_char_set;
131 _DtCvLinkDb my_links;
132 _FrmtUiInfo *ui_info;
142 typedef enum _processState ProcessState;
144 /******************************************************************************
145 * Private Function Declarations
146 ******************************************************************************/
147 static _DtCvSegment *AllocateSegments(
151 static int AppendCharToInfo(
152 FormatVariables *cur_vars,
154 static int AppendOctalToInfo(
155 FormatVariables *cur_vars,
157 static int AppendSpaceToInfo (
158 FormatVariables *cur_vars,
160 _DtCvFrmtOption type );
161 static int AppendToInfo (
162 FormatVariables *cur_vars,
164 const char *scan_string );
165 static int ChangeFont(
167 unsigned long seg_flags,
168 _DtCvFrmtOption frmt_type,
169 _DtHelpFontHints *font_attr,
171 FormatVariables *cur_vars,
172 ProcessState cur_state,
176 static int CheckIdString(
177 FormatVariables *cur_vars,
178 ProcessState cur_state,
179 unsigned long seg_flags,
180 _DtCvFrmtOption frmt_type,
181 _DtHelpFontHints *font_attr,
186 static int CheckSaveSegment (
187 unsigned long seg_flags,
188 _DtHelpFontHints *font_attr,
190 FormatVariables *cur_vars );
191 static int CreateSaveGraphic (
192 FormatVariables *cur_vars,
196 static int CheckSegList (
197 FormatVariables *cur_vars);
199 FormatVariables *cur_vars,
200 _FrmtUiInfo *ui_info,
202 _DtCvTopicPtr *ret_handle);
203 static int GetNextBuffer (
204 FormatVariables *cur_vars);
205 static int GetStringParameter(
206 FormatVariables *cur_vars,
208 _DtCvValue eat_escape,
209 _DtCvValue ignore_quotes,
210 _DtCvValue less_test,
212 static int GetValueParameter(
213 FormatVariables *cur_vars,
216 static int InitStructure(
217 FormatVariables *cur_vars,
218 _FrmtUiInfo *ui_info,
223 ProcessState cur_state,
224 FormatVariables *cur_vars,
225 unsigned long seg_flags,
226 _DtCvFrmtOption frmt_type,
227 _DtHelpFontHints *font_attr,
229 const char *scan_string,
233 static int ProcessFigureCmd(
234 FormatVariables *cur_vars,
235 ProcessState cur_state,
236 _DtCvFrmtOption frmt_type,
237 _DtHelpFontHints *font_attr,
240 static int ProcessHypertext(
241 FormatVariables *cur_vars,
242 ProcessState cur_state,
243 unsigned long seg_flags,
244 _DtCvFrmtOption frmt_type,
245 _DtHelpFontHints *font_attr,
249 static int ProcessInLine(
250 FormatVariables *cur_vars,
253 static int ProcessLabelCmd(
254 FormatVariables *cur_vars,
255 unsigned long seg_flags,
256 _DtCvFrmtOption frmt_type,
257 _DtHelpFontHints *font_attr,
262 _DtCvSegment **ret_list);
263 static int ProcessParagraph (
264 FormatVariables *cur_vars,
265 ProcessState cur_state,
267 static int SaveNewLine(
268 FormatVariables *cur_vars,
270 _DtHelpFontHints *font_attr,
272 static int SaveStringAsSegments (
273 FormatVariables *cur_vars,
274 unsigned long seg_flags,
275 _DtHelpFontHints *font_attr,
277 static int SkipToNextToken (
278 FormatVariables *cur_vars,
280 static void TerminateSegList (
283 static int SegmentSave(
284 FormatVariables *cur_vars,
285 unsigned long seg_type,
286 _DtHelpFontHints *font_attr,
292 /******** End Public Function Declarations ********/
294 /******************************************************************************
296 *****************************************************************************/
297 static const char *Specials = "<\n\\ ";
298 static const char *SpaceString = " ";
299 static const char *CString = "C";
300 static const char *Period = ".";
301 static const char *Slash = "/";
303 static const FormatVariables DefVars = {
304 True, /* int last_was_space; */
305 False, /* int last_was_mb; */
306 False, /* int last_was_nl; */
308 NULL, /* char *rd_buf; */
309 NULL, /* char *rd_ptr; */
310 NULL, /* char *fmt_buf; */
311 NULL, /* char *my_path; */
312 NULL, /* char *vol_name; */
313 NULL, /* char *topic_id; */
314 NULL, /* char *topic_char_set; */
315 NULL, /* char *topic_lang; */
317 0, /* int rd_size; */
318 0, /* int rd_flag; */
320 1, /* int topic_mb_max; */
321 1, /* int cur_mb_max; */
323 0, /* int fmt_buf_max; */
324 0, /* int fmt_size; */
325 0, /* int cell_cnt; */
327 NULL, /* BufFilePtr my_file; */
328 { /* SegList my_list; */
331 NULL, /* _DtCvSegment *list; */
332 }, /* SegList my_list; */
333 NULL, /* _DtCvLinkDb my_links; */
334 NULL, /* _FrmtUiInfo ui_info; */
337 static const SegList InitList =
341 NULL, /* _DtCvSegment *list; */
344 static const _DtCvContainer DefContainer =
346 NULL, /* char *id; */
347 NULL, /* char *justify_char; */
348 _DtCvDYNAMIC, /* _DtCvFrmtOption type; */
349 _DtCvBORDER_NONE, /* _DtCvFrmtOption border; */
350 _DtCvJUSTIFY_LEFT, /* _DtCvFrmtOption justify; */
351 _DtCvJUSTIFY_TOP, /* _DtCvFrmtOption vjustify; */
352 _DtCvJUSTIFY_LEFT_MARGIN,/* _DtCvFrmtOption orient; */
353 _DtCvJUSTIFY_TOP, /* _DtCvFrmtOption vorient; */
354 _DtCvWRAP_NONE, /* _DtCvFrmtOption flow; */
355 10000, /* int percent; */
356 0, /* _DtCvUnit leading; */
357 0, /* _DtCvUnit fmargin; */
358 0, /* _DtCvUnit lmargin; */
359 0, /* _DtCvUnit rmargin; */
360 0, /* _DtCvUnit tmargin; */
361 1, /* _DtCvUnit bmargin; */
362 {0, NULL}, /* _DtCvLine bdr_info; */
363 NULL, /* _DtCvSegment seg_list; */
366 static const FrmtPrivateInfo DefPrivInfo =
368 (char) False, /* char top_block; */
369 (char) False, /* char dup_flag; */
370 0, /* int sdl_type; */
371 NULL, /* void *match_info; */
372 NULL, /* void *id_info; */
373 NULL, /* void *tmp_info; */
376 /******************************************************************************
380 *****************************************************************************/
381 /******************************************************************************
382 * Function: int CreateMarker (
385 * cur_vars Specifies the current setting of
386 * formatting variables.
387 * id_string The id string for the marker.
389 * Returns: 0 if successful, -1 if failure.
391 * Purpose: To create a marker id.
393 *****************************************************************************/
396 FormatVariables *cur_vars,
402 * make sure there is room for the marker segment
404 result = CheckSegList(cur_vars);
407 int cnt = cur_vars->my_list.cnt;
408 _DtCvSegment *list = cur_vars->my_list.list;
411 * now make a mark segment here.
413 list[cnt].type = _DtCvSetTypeToMarker(list[cnt].type);
414 _DtCvIdOfMarkerSeg(&list[cnt]) = id_string;
415 cur_vars->my_list.cnt++;
421 /******************************************************************************
422 * Function: void GetMbLen (
425 * cur_vars Specifies the current setting of
426 * formatting variables.
427 * font_str Specifies the CCDF string for a
428 * CHARACTERSET change. The string is
429 * modified by this routine.
430 * lang_ptr Returns the language and territory
431 * value. The caller owns this memory.
432 * set_ptr Returns the code set of the language.
433 * The caller owns this memory.
437 * Purpose: 1) To decompose the font_string into a language and code set
439 * 2) To set the mb_cur_len variable in cur_vars.
441 *****************************************************************************/
444 FormatVariables *cur_vars,
451 char *langPart = NULL;
452 char *codePart = NULL;
457 while (*font_str == ' ')
460 for (i = strlen(font_str) - 1; i > -1 && font_str[i] == ' '; i--)
464 * check for locale.codeset
466 if (_DtHelpCeStrchr(font_str, ".", 1, &ptr) == 0)
469 * make font_str two seperate strings by replacing
470 * the dot with a end of line.
473 langPart = strdup(font_str);
474 codePart = strdup(ptr);
482 _DtHelpCeXlateOpToStdLocale(DtLCX_OPER_CCDF, font_str,
483 NULL, &langPart, &codePart);
485 * if the language is not specified for the code set,
486 * get the environment's.
488 if (strcmp(langPart, "?") == 0)
492 langPart = _DtHelpGetLocale();
493 if (langPart == NULL || *langPart == '\0')
494 langPart = strdup((char *) CString);
495 else if (_DtHelpCeStrrchr(langPart, "_", MB_CUR_MAX, &ptr) == 0)
497 else if (_DtHelpCeStrrchr(langPart, Period, MB_CUR_MAX, &ptr) == 0)
502 cur_vars->cur_mb_max = _DtHelpCeGetMbLen(langPart, codePart);
505 * now set the return variables
507 if (lang_ptr != NULL)
508 *lang_ptr = langPart;
518 /******************************************************************************
519 * Function: int ReturnLinkWinHint (int ccdf_type)
528 *****************************************************************************/
533 int winHint = _DtCvWindowHint_CurrentWindow;
535 if (ccdf_type == CCDF_LINK_JUMP_NEW)
536 winHint = _DtCvWindowHint_NewWindow;
538 else if (ccdf_type == CCDF_LINK_DEFINITION)
539 winHint = _DtCvWindowHint_PopupWindow;
544 /******************************************************************************
545 * Function: int ReturnLinkType (int ccdf_type, char *spec)
554 *****************************************************************************/
560 int trueType = _DtCvLinkType_SameVolume;
564 case CCDF_LINK_JUMP_NEW:
565 case CCDF_LINK_JUMP_REUSE:
566 case CCDF_LINK_DEFINITION:
567 if (strchr(spec, ' ') != NULL)
568 trueType = _DtCvLinkType_CrossLink;
571 case CCDF_LINK_EXECUTE:
572 trueType = _DtCvLinkType_Execute;
575 case CCDF_LINK_MAN_PAGE:
576 trueType = _DtCvLinkType_ManPage;
579 case CCDF_LINK_APP_DEFINE:
580 trueType = _DtCvLinkType_AppDefine;
588 /******************************************************************************
589 * Function: int CheckSegList (FormatVariables *cur_vars)
593 * Returns: 0 for success, -1 for errors.
598 * Purpose: Check the global variable 'SegCount' against 'SegMax' and
599 * realloc/malloc more memory for the global variable 'SegList'
600 * if necessary. If memory is realloc'ed/malloc'ed, the entry
601 * 'para_entry->seg_list' is set to 'SegList'.
603 *****************************************************************************/
606 FormatVariables *cur_vars )
608 if (cur_vars->my_list.cnt >= cur_vars->my_list.max)
610 cur_vars->my_list.list = AllocateSegments (cur_vars->my_list.list,
611 cur_vars->my_list.max,
612 (cur_vars->my_list.max + GROW_SIZE));
614 if (NULL == cur_vars->my_list.list)
617 cur_vars->my_list.max += GROW_SIZE;
623 /******************************************************************************
624 * Function: static _DtCvSegment *AllocateSegments (_DtCvSegment p_seg,
625 * int original_size, int new_size)
628 * p_seg Specifies a pointer to the old list
630 * original_size Specifies the current size of 'p_seg'.
631 * new_size Specifies the new size of 'p_seg'.
633 * Returns: A pointer to the new list of structures.
634 * A NULL indicates an error.
636 * Purpose: (Re)Allocates _DtCvSegment structures and initializes
637 * them to the default segment which is type _DtCvNOOP
638 * and the container values set to default values.
640 *****************************************************************************/
641 static _DtCvSegment *
647 FrmtPrivateInfo *priv = NULL;
654 * reallocate the segments.
656 p_seg = (_DtCvSegment *) realloc ((void *) p_seg,
657 (sizeof(_DtCvSegment) * new_size));
659 * reallocate the private formatting information.
661 priv = p_seg->client_use;
662 priv = (FrmtPrivateInfo *) realloc ((void *) priv,
663 sizeof(FrmtPrivateInfo) * new_size);
668 * reattach the private information with their segments.
670 while (count < original_size)
671 p_seg[count++].client_use = priv++;
674 p_seg = _DtHelpAllocateSegments (new_size);
679 * want to 'empty' the type.
681 while (original_size < new_size)
684 * if we went through _DtHelpAllocateSegments, then the
685 * priv pointer will be NULL. But that's okay since the
686 * _DtHelpAllocateSegments routine will initalized the
687 * variables for us. The only reason we have to do it
688 * is if we've reallocated the list.
694 p_seg[original_size ].client_use = priv++;
695 p_seg[original_size ].type = _DtCvNOOP;
696 p_seg[original_size ].link_idx = -1;
697 p_seg[original_size ].next_seg = NULL;
698 p_seg[original_size ].next_disp = NULL;
701 p_seg[original_size++].handle.container = DefContainer;
708 /******************************************************************************
709 * Function: static int CheckList (
710 * FormatVariables cur_vars, int count, int grow)
713 * cur_vars Specifies a structure containing the list
715 * count Specifies the amount needed.
716 * grow Specifies the amount to grow by.
718 * Returns: 0 if successful, -1 if failure.
720 * Purpose: Makes sure there is 'grow' size number of segments
721 * available. If not, it calls AllocateSegments to 'grow'
722 * the segment list. cur_vars->seg_list is set to the new
723 * pointer, cur_vars->seg_max indicates the maximum number
724 * of segments in the list.
726 *****************************************************************************/
734 * what's the new count?
736 count += seg_list->cnt;
739 * is it larger than the current max?
741 if (count > seg_list->max)
744 * grow the list by the indicated amount.
746 grow += seg_list->max;
749 * check to see if it is enough. If not, force the grow value
750 * to be the required count.
758 seg_list->list = AllocateSegments(seg_list->list, seg_list->max, grow);
761 * return an code if no list allocated.
763 if (NULL == seg_list->list)
769 seg_list->max = grow;
775 /******************************************************************************
776 * Function: int SegmentSave (int type,
777 * char **font_attr, char *string, int linkspec,
778 * _DtCvSegment *p_seg)
781 * type Specifies the segment type.
782 * font_attr Specifies the resource list of quarks for the
783 * font to associate with the segment.
784 * string Specifies the string segment.
785 * link_spec Specifies the link specification for the
787 * p_seg Specifies the _DtCvSegment structure to
788 * initialize with the data.
790 * Returns: 0 if successful, -1 if errors.
795 * Purpose: Creates a new segment with the given data.
797 *****************************************************************************/
800 FormatVariables *cur_vars,
801 unsigned long seg_type,
802 _DtHelpFontHints *font_attr,
809 _DtCvSegment *pSeg = NextAvailSeg(cur_vars->my_list);
811 pSeg->type = _DtCvSetTypeToNoop(seg_type);
812 pSeg->link_idx = linkspec;
815 * We use this routine for many things.
816 * If we want an newline in here, we may not have any data.
820 pSeg->type = _DtCvSetTypeToString(pSeg->type);
823 * if a wide character representation is required,
826 if (seg_type & _DtCvWIDE_CHAR)
831 * include the null byte in the multibyte to widechar
839 pwcs = (wchar_t *) malloc(sizeof(wchar_t) * num_chars);
843 str_size = mbstowcs(pwcs, string, ((size_t) num_chars));
845 /* check to see if it converted everything */
846 if (str_size + 1 == num_chars)
847 _DtCvStringOfStringSeg(pSeg) = (void *) pwcs;
853 _DtCvStringOfStringSeg(pSeg) = (void *) strdup(string);
855 if (NULL == _DtCvStringOfStringSeg(pSeg))
859 * set the default font. This should really be passed in via
860 * the format entry point (or the ui_info structure).
862 _DtCvFontOfStringSeg(pSeg) = 0;
867 if (NULL != cur_vars->ui_info->load_font)
868 (*(cur_vars->ui_info->load_font))(
869 cur_vars->ui_info->client_data,
870 _DtHelpFontHintsLang(*font_attr),
871 _DtHelpFontHintsCharSet(*font_attr),
873 &(_DtCvFontOfStringSeg(pSeg)));
879 /******************************************************************************
880 * Function: int SaveStringAsSegments (FormatVariables, int type, char **font_attr,
884 * type Specifies the segment type.
885 * font_attr Specifies the resource list of quarks for the
886 * font to associate with the segment.
887 * link_spec Specifies the link specification for the
890 * Returns: 0 if successful, -1 if errors.
894 * Purpose: Saves a segment into the global 'SegList'. This is
895 * a wrapper around SegmentSave that adds specific
896 * information relative to this module.
898 *****************************************************************************/
900 SaveStringAsSegments (
901 FormatVariables *cur_vars,
902 unsigned long seg_flags,
903 _DtHelpFontHints *font_attr,
913 seg_flags = _DtCvSetTypeToNoop(seg_flags);
914 if (cur_vars->cur_mb_max != 1 && cur_vars->fmt_size > 1)
916 if (IsTypeNewLine(seg_flags))
919 seg_flags = seg_flags & ~(_DtCvNEW_LINE);
922 ptr = cur_vars->fmt_buf;
926 * what type of character is this?
928 len = mblen (ptr, cur_vars->cur_mb_max);
931 * How many of the following characters are of the same size?
933 size = _DtHelpFmtFindBreak (ptr, len, &numChars);
936 * save off the character that doesn't match
941 * put in the null byte for the string.
942 * and set to wide char if not doing multi-byte sequence.
946 seg_flags = _DtCvSetTypeToWideChar (seg_flags);
949 * does this segment get the newline flag?
951 if (True == newLine && size >= cur_vars->fmt_size)
952 seg_flags = _DtCvSetTypeToNewLine(seg_flags);
957 if (CheckSegList(cur_vars) == -1 ||
958 SegmentSave (cur_vars, seg_flags, font_attr, ptr, size,
959 numChars, link_spec) == -1)
963 * remove the wide char flag
965 seg_flags &= ~(_DtCvWIDE_CHAR);
968 * Bump the segment list count.
970 cur_vars->my_list.cnt++;
973 * replace the character that didn't match.
974 * and bump the pointer to it.
978 cur_vars->fmt_size -= size;
979 } while (0 < cur_vars->fmt_size);
983 if (CheckSegList (cur_vars) == -1 ||
984 SegmentSave (cur_vars, seg_flags, font_attr,
985 cur_vars->fmt_buf, cur_vars->fmt_size,
989 cur_vars->my_list.cnt++;
992 cur_vars->fmt_size = 0;
993 if (cur_vars->fmt_buf)
994 cur_vars->fmt_buf[0] = '\0';
999 /******************************************************************************
1000 * Function: int CheckSaveSegment (int type, char **font_attr, int link_spec,
1001 * FormatVariables cur_vars)
1004 * type Specifies the segment type.
1005 * font_attr Specifies the resource list of quarks for the
1006 * font to associate with the segment.
1007 * link_spec Specifies the link specification for the
1010 * Returns: 0 if successful, -1 if errors.
1014 * Purpose: Checks 'cur_vars->fmt_size' for a non-zero value. If it is,
1015 * calls SaveSegment.
1017 *****************************************************************************/
1020 unsigned long seg_flags,
1021 _DtHelpFontHints *font_attr,
1023 FormatVariables *cur_vars)
1027 if (cur_vars->fmt_size)
1028 result = SaveStringAsSegments (cur_vars, seg_flags, font_attr, link_spec);
1033 /******************************************************************************
1034 * Function: void TerminateSegList (
1038 * Returns: 0 if successful, -1 if errors.
1040 * Purpose: Links the segments together.
1042 *****************************************************************************/
1049 _DtCvSegment *lastDisp = NULL;
1052 if (True == flag && 0 == seg_list->cnt && NULL != seg_list->list)
1054 free(seg_list->list);
1055 *seg_list = InitList;
1059 * set the next segment and display segment pointers.
1061 for (count = 1, pSeg = seg_list->list; count < seg_list->cnt;
1065 * link this segment to the next segment
1067 pSeg->next_seg = &(pSeg[1]);
1070 * is this a displayable segment?
1071 * If so, link it into the displayable list.
1073 if (_DtCvIsSegNoop(pSeg) || _DtCvIsSegRegion(pSeg)
1074 || _DtCvIsSegString(pSeg))
1077 * Is there a displayable segment yet?
1078 * If so, set its next displayable link to this segment.
1080 if (NULL != lastDisp)
1081 lastDisp->next_disp = pSeg;
1084 * this segment becomes the last displayable segment.
1092 if (NULL != pSeg && NULL != lastDisp
1093 && (_DtCvIsSegNoop(pSeg) || _DtCvIsSegRegion(pSeg)
1094 || _DtCvIsSegString(pSeg)))
1095 lastDisp->next_disp = pSeg;
1099 /******************************************************************************
1100 * Function: int InitStructure (FormatVariables *cur_vars,
1101 * char *rd_buf, int rd_size,
1104 * rd_buffer Specifies the buffer all reads use.
1105 * id_string Specifies the location ID to search for.
1107 * Returns: 0 if successful, -1 if errors.
1111 * Purpose: Attach formatting information to the structure that gets
1112 * passed around by, among other things, setting the global
1113 * variable 'cur_vars->rd_ptr' to 'rd_buffer', and
1114 * remembering the location id.
1116 *****************************************************************************/
1119 FormatVariables *cur_vars,
1120 _FrmtUiInfo *ui_info,
1124 cur_vars->ui_info = ui_info;
1125 cur_vars->rd_size = rd_size;
1126 cur_vars->rd_buf = rd_buf;
1127 cur_vars->rd_ptr = cur_vars->rd_buf;
1129 cur_vars->fmt_size = 0;
1130 if (cur_vars->fmt_buf)
1131 cur_vars->fmt_buf[0] = '\0';
1134 * allocate the link data base.
1136 cur_vars->my_links = _DtLinkDbCreate();
1137 if (NULL == cur_vars->my_links)
1143 /******************************************************************************
1144 * Function: int AppendToInfo (FormatVariables *cur_vars,
1145 * char **src, const char *scan_string)
1148 * src Specifies the source string to read.
1149 * Returns pointing at a special character,
1150 * an invalid character or the
1152 * scan_string Specifies the special characters to
1153 * look for in 'src'.
1155 * Returns: 0 if stopped on a special character.
1156 * 1 if found the end of string.
1157 * 2 if found an invalid character.
1162 * Purpose: Appends onto 'cur_vars->fmt_buf' the number of characters
1163 * found in 'src' that does not match any character in
1166 * Sets 'cur_vars->last_was_space' to false (assumes that one
1167 * of the special characters is a space).
1169 *****************************************************************************/
1172 FormatVariables *cur_vars,
1174 const char *scan_string )
1179 cur_vars->last_was_space = False;
1180 spnResult = _DtHelpCeStrcspn(*src, scan_string, cur_vars->cur_mb_max,
1184 if (_DtHelpCeAddStrToBuf(src,&(cur_vars->fmt_buf),&(cur_vars->fmt_size),
1185 &(cur_vars->fmt_buf_max),size,INFO_GROW) == -1)
1187 cur_vars->last_was_space = False;
1190 if (spnResult == -1)
1193 if (0 == size && 1 == spnResult)
1199 /******************************************************************************
1200 * Function: int AppendOctalToInfo (FormatVariables *cur_vars, char *src)
1203 * src Specifies the source string to read.
1205 * Returns: 0 if successful, -1 if errors.
1208 * CEErrorFormattingValue
1211 * Purpose: Convert the octal representation pointed to by 'src' and
1212 * change it into a character byte. The routine only allows
1213 * a number between the values 1-255.
1215 * Append the byte onto the global variable 'Info'.
1216 * Set 'cur_vars->last_was_space' to false.
1218 *****************************************************************************/
1221 FormatVariables *cur_vars,
1227 if (((int)strlen(src)) < 4 && cur_vars->my_file != NULL)
1229 if (GetNextBuffer (cur_vars) == -1)
1232 src = cur_vars->rd_ptr;
1235 if (_DtHelpCeAddOctalToBuf(src,&(cur_vars->fmt_buf),&(cur_vars->fmt_size),
1236 &(cur_vars->fmt_buf_max),INFO_GROW) == -1)
1239 cur_vars->last_was_space = False;
1244 /******************************************************************************
1245 * Function: int AppendCharToInfo (FormatVariables *cur_vars, char **src)
1248 * src Specifies the source string to read.
1249 * Returns pointing at the next character
1252 * Returns: 0 if successful, -1 if errors.
1256 * Purpose: Appends the character pointed to by 'src' onto the
1257 * global buffer 'Info', updating the pointers associated
1258 * with 'Info' accordingly.
1260 * Sets 'cur_vars->last_was_space' to False;
1262 *****************************************************************************/ static int
1264 FormatVariables *cur_vars,
1267 cur_vars->last_was_space = False;
1268 return (_DtHelpCeAddCharToBuf (src, &(cur_vars->fmt_buf),
1269 &(cur_vars->fmt_size),
1270 &(cur_vars->fmt_buf_max), INFO_GROW));
1273 /******************************************************************************
1274 * Function: int AppendSpaceToInfo (char **src, int type)
1277 * src Specifies the source string to read.
1278 * Returns pointing at the next character
1280 * type Specifies the type of the segment being
1283 * Returns: 0 if successful, -1 if errors.
1287 * Purpose: Appends a space onto the global buffer 'Info', if
1288 * the variable 'cur_vars->last_was_space' is false or the
1289 * static string flag is set in 'type'.
1291 * Sets 'cur_vars->last_was_space' to true.
1293 *****************************************************************************/
1296 FormatVariables *cur_vars,
1298 _DtCvFrmtOption type)
1301 char *space = (char *) SpaceString;
1303 if (!cur_vars->last_was_space || _DtCvLITERAL == type) {
1305 result = _DtHelpCeAddCharToBuf (&space, &(cur_vars->fmt_buf),
1306 &(cur_vars->fmt_size),
1307 &(cur_vars->fmt_buf_max), INFO_GROW);
1308 cur_vars->last_was_space = True;
1316 /******************************************************************************
1317 * Function: int FindEndMarker (FormatVariables *cur_vars)
1319 * Returns: 0 if successful, -1 if errors.
1323 * Purpose: Wrapper around __DtHelpFindEndMarker.
1324 * Find the '>' token.
1326 *****************************************************************************/
1329 FormatVariables *cur_vars)
1331 return (_DtHelpCeGetCcdfEndMark (cur_vars->my_file, cur_vars->rd_buf,
1332 &(cur_vars->rd_ptr),cur_vars->rd_size,1));
1335 /******************************************************************************
1336 * Function: int GetNextBuffer (FormatVariables *cur_vars)
1338 * Returns: 0 if successful, -1 if errors.
1342 * Purpose: Wrapper around __DtHelpGetNextBuffer.
1343 * Read the next buffer's worth of information.
1345 *****************************************************************************/
1348 FormatVariables *cur_vars)
1350 cur_vars->rd_flag = _DtHelpCeGetNxtBuf (cur_vars->my_file,
1352 &(cur_vars->rd_ptr),
1354 return (cur_vars->rd_flag);
1357 /******************************************************************************
1358 * Function: int SaveNewLine (FormatVariables *cur_vars, int cur_type,
1363 * cur_cmd Specifies the type of segment being processed.
1364 * font_attr Specifies the list of font quarks associated
1365 * with the current segment.
1366 * link_spec Specifies the hypertext link specification
1367 * associated with the current segment.
1369 * Returns: 0 if successful, -1 if errors.
1373 * Purpose: Sets the newline flag on a segment and saves it by calling
1374 * 'SaveStringAsSegments'.
1375 * If the current segment is non-null, save it with the
1377 * Otherwise if there are no segments saved, create one with the
1378 * a type of CE_old_NOOP.
1379 * Otherwise there are other segments, but the current segment is
1380 * empty. Look back at the previous segment.
1381 * If it doesn't have the newline set on it,
1382 * its newline flag is enabled.
1383 * Otherwise the previous segment had the newline set, so
1384 * create another segment just like it with a
1385 * null length and the newline flag set (if the
1386 * previous segment is a graphic, create it
1387 * with a type of CE_old_NOOP).
1389 *****************************************************************************/
1392 FormatVariables *cur_vars,
1394 _DtHelpFontHints *font_attr,
1401 * If there is information in the buffer, save it with the newline flag
1403 if (cur_vars->fmt_size)
1404 result = SaveStringAsSegments (cur_vars, _DtCvSetTypeToNewLine (cur_type),
1405 font_attr, link_spec);
1407 * check to see if there is any segments. If not create a new one
1408 * with the type NOOP.
1410 else if (0 == cur_vars->my_list.cnt)
1411 result = SaveStringAsSegments (cur_vars, _DtCvSetTypeToNewLine(_DtCvNOOP),
1412 font_attr, link_spec);
1414 * There was not any information in the buffer and we have one or
1415 * more segments. Try placing the flag on the previous segment.
1419 pSeg = NextAvailSeg(cur_vars->my_list);
1423 * Does the previous segment already have a newline flag?
1424 * If so, create a new NOOP segment with the newline set.
1426 if (_DtCvIsSegNewLine (pSeg))
1427 result = SaveStringAsSegments (cur_vars, _DtCvSetTypeToNewLine (_DtCvNOOP),
1428 font_attr, link_spec);
1430 pSeg->type = _DtCvSetTypeToNewLine (pSeg->type);
1433 cur_vars->last_was_space = True;
1437 /******************************************************************************
1438 * Function: int CreateSaveGraphic (FormatVariables cur_vars,
1440 * char *file_name, int link_spec )
1443 * type Specifies the type of graphic segment
1445 * file_name Specifies the file name of the graphic.
1446 * link_spec Specifies the hypertext link specification
1447 * associated with the graphic.
1449 * Returns: 0 if successful, -1 if errors.
1451 * Purpose: Save a graphic segment.
1452 * If 'file_name' is not an absolute path, resolve it to
1453 * a full path by using the path to the volume.
1455 *****************************************************************************/
1458 FormatVariables *cur_vars,
1464 _DtCvSegment *cvRegion;
1466 if (CheckList (&(cur_vars->my_list), 1, 1) == -1)
1470 * create the path to the file name
1472 if (*file_name == '/')
1473 fullName = strdup (file_name);
1476 fullName = (char *) malloc (strlen (cur_vars->my_path) +
1477 strlen (file_name) + 2);
1478 if (fullName == NULL)
1481 strcpy (fullName, cur_vars->my_path);
1482 strcat (fullName, "/");
1483 strcat (fullName, file_name);
1487 * load the graphic into the current segment
1489 cvRegion = NextAvailSeg(cur_vars->my_list);
1490 if (NULL != cur_vars->ui_info->load_graphic &&
1491 (*(cur_vars->ui_info->load_graphic))(
1492 cur_vars->ui_info->client_data,
1498 &(_DtCvWidthOfRegionSeg(cvRegion)),
1499 &(_DtCvHeightOfRegionSeg(cvRegion)),
1500 &(_DtCvInfoOfRegionSeg(cvRegion))) == 0)
1503 * set the type and index.
1504 * and indicate that this segment has been used.
1506 _DtCvAscentOfRegionSeg(cvRegion) = -1;
1507 cvRegion->type = _DtCvSetTypeToRegion(type);
1508 cvRegion->link_idx = link_spec;
1509 cur_vars->my_list.cnt++;
1513 * free the file name path
1520 /******************************************************************************
1521 * Function: int ChangeFont (int whichOne, int segType,
1522 * char **font_attr, int linkspec,
1523 * FormatVariables *cur_vars, int flags)
1526 * whichOne Specifies the index into 'font_attr' to
1528 * segType Specifies the type of segment currently
1530 * font_attr Specifies the list of font quarks associated
1531 * with the current segment.
1532 * linkspec Specifies the hypertext link specification
1533 * associated with the segment.
1534 * flags Specifies the routines flags.
1536 * Returns: The value returned from 'routine' if successful, -1 if errors.
1540 * Purpose: Saves any segment with the current font type and
1541 * process the next segment using the new font type.
1543 *****************************************************************************/
1547 unsigned long seg_flags,
1548 _DtCvFrmtOption frmt_type,
1549 _DtHelpFontHints *font_attr,
1551 FormatVariables *cur_vars,
1552 ProcessState cur_state,
1558 int oldMb_Len = cur_vars->cur_mb_max;
1560 _DtHelpFontHints oldFontStruct;
1562 if (CheckSaveSegment (seg_flags, font_attr, linkspec, cur_vars) == -1)
1565 oldFontStruct = *font_attr;
1567 if (GetStringParameter(cur_vars, _DtCvTRUE, _DtCvTRUE, _DtCvFALSE,
1568 _DtCvFALSE, &fontString) == -1)
1572 * Is this font change allowed to go through?
1574 if (!(fnt_flag & (1 << whichOne)))
1578 case _CEFONT_SPACING:
1579 font_attr->spacing = _DtHelpFontSpacingProp;
1580 if (fontString[0] == 'm')
1581 font_attr->spacing = _DtHelpFontSpacingMono;
1584 font_attr->pointsz = atoi(fontString);
1587 font_attr->slant = _DtHelpFontSlantRoman;
1588 if (fontString[0] == 'i')
1589 font_attr->slant = _DtHelpFontSlantItalic;
1591 case _CEFONT_WEIGHT:
1592 font_attr->weight = _DtHelpFontWeightMedium;
1593 if (fontString[0] == 'b')
1594 font_attr->weight = _DtHelpFontWeightBold;
1597 font_attr->style = _DtHelpFontStyleSanSerif;
1598 if (*fontString == 's')
1600 if (fontString[1] == 'e')
1601 font_attr->style = _DtHelpFontStyleSerif;
1602 else if (fontString[1] == 'y')
1603 font_attr->style = _DtHelpFontStyleSymbol;
1606 case _CEFONT_CHAR_SET:
1608 * Change to the correct mb_len.
1610 GetMbLen(cur_vars, fontString,
1611 &(_DtHelpFontHintsLang(*font_attr)),
1612 &(_DtHelpFontHintsCharSet(*font_attr)));
1617 result = FindEndMarker (cur_vars);
1619 result = Parse (CCDF_FONT_CMD, cur_state, cur_vars,
1620 seg_flags, frmt_type,
1621 font_attr, linkspec,
1622 Specials, flags, ret_on_nl, fnt_flag);
1624 * free the lanugage and code sets strings.
1626 if (!(fnt_flag & (1 << whichOne)) && whichOne == _CEFONT_CHAR_SET)
1628 free(_DtHelpFontHintsLang(*font_attr));
1629 free(_DtHelpFontHintsCharSet(*font_attr));
1633 * reset the old quark
1634 * if necessary, reset the MB_LEN
1636 *font_attr = oldFontStruct;
1637 cur_vars->cur_mb_max = oldMb_Len;
1651 /******************************************************************************
1652 * Function: int SkipToNextToken (FormatVariables *cur_vars, int flag)
1655 * flag Specifies whether the routine returns a -1
1656 * if '>' is the next token.
1658 * Returns: The value from __DtHelpSkipToNextToken:
1659 * -1 If problems encountered finding the next token.
1660 * 0 If no problems encountered finding the next token.
1661 * 1 If flag is true and the next token is a > character.
1665 * Purpose: Wrapper around __DtHelpSkipToNextToken.
1666 * Skip the current string and any spaces or newline
1667 * characters after it.
1669 *****************************************************************************/
1672 FormatVariables *cur_vars,
1675 return (_DtHelpCeSkipToNextCcdfToken (cur_vars->my_file, cur_vars->rd_buf,
1676 cur_vars->rd_size, 1, &(cur_vars->rd_ptr), flag));
1679 /******************************************************************************
1680 * Function: int GetStringParameter (FormatVariables *cur_vars,
1681 * int flag, int eat_escape,
1682 * int ignore_quotes, int less_test,
1683 * char **ret_string)
1686 * flag Specifies whether the routine returns
1687 * a -1 if '>' is the next token.
1688 * eat_secape Specifies whether the backslash is not
1689 * placed in the returned string.
1690 * True - it is skipped.
1691 * False - it is saved in 'ret_string'.
1692 * ignore_quotes Specifies whether quotes are to be included
1693 * in the returned string.
1694 * less_test Specifies whether the routine should
1695 * stop when it finds a '<' character.
1696 * ret_string Returns the string found.
1697 * If NULL, throws the information away.
1699 * Returns: The value from __DtHelpFormatGetStringParameter:
1700 * -1 If problems encountered.
1701 * 0 If no problems encountered getting the string.
1702 * 1 If flag is false and the no string was found.
1706 * Purpose: Wrapper around __DtHelpFormatGetStringParameter.
1707 * Skip the current string and any spaces or newline
1708 * characters after it. Get the next quoted/unquoted
1709 * string after that.
1711 *****************************************************************************/
1714 FormatVariables *cur_vars,
1716 _DtCvValue eat_escape,
1717 _DtCvValue ignore_quotes,
1718 _DtCvValue less_test,
1721 return (_DtHelpCeGetCcdfStrParam (cur_vars->my_file,
1722 cur_vars->rd_buf, cur_vars->rd_size, cur_vars->cur_mb_max,
1723 &(cur_vars->rd_ptr),
1724 flag, eat_escape, ignore_quotes, less_test, ret_string));
1727 /******************************************************************************
1728 * Function: int GetValueParameter (FormatVariables *cur_vars,
1729 * int flag, int *ret_value)
1732 * flag Specifies whether the routine returns
1733 * a -2 if '>' is the next token.
1734 * ret_value Returns the atoi conversion
1735 * of the string found.
1737 * Returns: The value from __DtHelpFormatGetValueParameter:
1738 * -1 If problems encountered.
1739 * 0 If no problems encountered getting the string.
1740 * -2 If flag is true and the next token is a >
1745 * Purpose: Wrapper around __DtHelpFormatGetValueParameter.
1746 * Skip the current string and any spaces or newline
1747 * characters after it. Process the next string as
1750 *****************************************************************************/
1753 FormatVariables *cur_vars,
1757 return (_DtHelpCeGetCcdfValueParam (cur_vars->my_file, cur_vars->rd_buf,
1759 &(cur_vars->rd_ptr), flag, cur_vars->cur_mb_max,
1763 /******************************************************************************
1764 * Function: int GetParagraphParameters (FormatVariables *cur_vars,
1765 * int seg_type, int graphic_type,
1766 * char **label, char **file_name,
1767 * char **link_string, int *link_type,
1768 * char **description)
1771 * seg_type Specifies the default type for the segment.
1772 * Returns the new type for the segment.
1773 * graphic_type Specifies the default type for a graphic
1774 * if a justified graphic is
1775 * encountered in the paragraph options.
1776 * Returns the new type for a graphic
1777 * if a justified graphic was
1778 * encountered in the paragraph options.
1779 * label Returns the label if one is specified
1780 * in the paragraph options.
1781 * file_name Returns the file name of a graphic if
1782 * one is specified in the paragraph
1784 * link_string Returns the hypertext specification if one
1785 * is specified in the paragraph options.
1786 * link_type Returns the hypertext link type if one is
1788 * description Returns the hypertext description if one
1791 * Returns: 0 if successfult, -1 if errors.
1795 * Purpose: Wrapper around __DtHelpParagraphGetOptions.
1796 * Process the options found in <PARAGRAPH> syntax.
1797 * Test to see if the id specified in the <PARAGRAPH>
1798 * is the one we are looking at.
1800 *****************************************************************************/
1802 GetParagraphParameters(
1803 FormatVariables *cur_vars,
1805 _DtCvFrmtOption *frmt_type,
1806 _DtCvFrmtOption *gpos,
1816 int optionCount = 0;
1818 char *tmpString = NULL;
1821 * initialize string variables if valid addresses
1826 *description = NULL;
1828 *gpos = _DtCvJUSTIFY_LEFT;
1832 while (False == done && result != -1)
1834 if (SkipToNextToken (cur_vars, _DtCvFALSE) == -1)
1837 switch (_DtCvToLower(*(cur_vars->rd_ptr)))
1840 * end of paragraph spec
1843 (cur_vars->rd_ptr)++;
1851 if (GetValueParameter (cur_vars, _DtCvFALSE, &value) == -1)
1854 _DtCvContainerBMarginOfSeg(para) = 0;
1855 if (value > 0 && 0 < cur_vars->ui_info->line_height)
1856 _DtCvContainerBMarginOfSeg(para) = value *
1857 (cur_vars->ui_info->line_height / 2);
1864 if (GetValueParameter (cur_vars, _DtCvFALSE, &value) == -1)
1867 _DtCvContainerTMarginOfSeg(para) = 0;
1868 if (value > 0 && 0 < cur_vars->ui_info->line_height)
1869 _DtCvContainerTMarginOfSeg(para) = value *
1870 (cur_vars->ui_info->line_height / 2);
1874 * description [string | "string" | 'string']
1877 result = GetStringParameter(cur_vars, _DtCvTRUE, _DtCvTRUE,
1878 _DtCvFALSE, _DtCvFALSE, description);
1885 if (GetValueParameter (cur_vars, _DtCvFALSE, &value) == -1)
1888 _DtCvContainerFMarginOfSeg(para) =
1889 value * cur_vars->ui_info->avg_char;
1893 * glink [string | "string" | 'string']
1901 * to determine what token this is we must look at the
1904 (cur_vars->rd_ptr)++;
1907 * do we need to read more?
1909 if (*(cur_vars->rd_ptr) == '\0'
1910 && GetNextBuffer(cur_vars) == -1)
1914 * check for the next permutation
1916 switch (_DtCvToLower(*(cur_vars->rd_ptr)))
1919 * glink [string | "string" | 'string']
1922 result = GetStringParameter(cur_vars, _DtCvTRUE,
1923 _DtCvTRUE, _DtCvFALSE, _DtCvFALSE, glink);
1930 result = GetStringParameter(cur_vars, _DtCvTRUE,
1931 _DtCvTRUE, _DtCvFALSE, _DtCvFALSE, &tmpString);
1933 if (-1 != result && _DtCvToLower (*tmpString) == 'r')
1934 *gpos = _DtCvJUSTIFY_RIGHT;
1944 result = GetStringParameter(cur_vars, _DtCvTRUE,
1945 _DtCvTRUE, _DtCvFALSE, _DtCvFALSE, file_name);
1952 if (GetValueParameter(cur_vars,_DtCvFALSE,&value) == -1
1956 *gspace = value * cur_vars->ui_info->avg_char;
1963 if (GetValueParameter(cur_vars,_DtCvFALSE,glinktype) == -1
1978 if (GetStringParameter(cur_vars, _DtCvTRUE, _DtCvTRUE,
1979 _DtCvFALSE, _DtCvFALSE, &tmpString) == -1)
1982 _DtCvContainerIdOfSeg(para) = tmpString;
1986 * label [string | "string" | 'string']
1991 * to determine what token this is we must look at the
1992 * second and possibly the third characters.
1994 (cur_vars->rd_ptr)++;
1997 * do we need to read more?
1999 if (*(cur_vars->rd_ptr) == '\0'
2000 && GetNextBuffer(cur_vars) == -1)
2004 * check for the next permutation
2006 if (_DtCvToLower(*(cur_vars->rd_ptr)) == 'a')
2011 if (GetStringParameter(cur_vars, _DtCvTRUE, _DtCvFALSE,
2012 _DtCvFALSE, _DtCvFALSE, &tmpString) == -1)
2016 * If we got a label process it.
2018 if (ret_label == NULL || *ret_label)
2021 * we've already processed a label!
2028 *ret_label = tmpString;
2030 else if (_DtCvToLower(*(cur_vars->rd_ptr)) == 'e')
2035 if (GetValueParameter (cur_vars, _DtCvFALSE, &value) == -1)
2038 _DtCvContainerLMarginOfSeg(para) =
2039 value * cur_vars->ui_info->avg_char;
2049 _DtCvContainerTypeOfSeg(para) = _DtCvLITERAL;
2050 *frmt_type = _DtCvLITERAL;
2057 if (GetValueParameter (cur_vars, _DtCvFALSE, &value) == -1)
2060 _DtCvContainerRMarginOfSeg(para) =
2061 value * cur_vars->ui_info->avg_char;
2068 _DtCvContainerTypeOfSeg(para) = _DtCvDYNAMIC;
2069 *frmt_type = _DtCvDYNAMIC;
2073 * Found an option we don't understand.
2082 * adjust the first margin to correctly indicate the offset from the
2083 * left margin. In the old CCDF, the first margin indicated left plus
2084 * and additional indent. For the new Canvas Engine, it is suppose
2085 * to be an addition on top of the left margin.
2087 _DtCvContainerFMarginOfSeg(para) = _DtCvContainerLMarginOfSeg(para) -
2088 _DtCvContainerFMarginOfSeg(para);
2092 return (optionCount - 1);
2094 } /* End GetParagraphParameters */
2096 /******************************************************************************
2097 * Function: int FlowingParagraph (
2105 * Purpose: Process the <PARAGRAPH> specification.
2107 *****************************************************************************/
2110 FormatVariables *cur_vars,
2111 ProcessState cur_state,
2112 _DtCvFrmtOption frmt_flags,
2117 _DtCvFrmtOption gpos,
2120 _DtHelpFontHints *font_attr)
2124 _DtCvSegment *graphSeg;
2125 _DtCvSegment *bodySeg;
2126 SegList flowList = InitList;
2129 * reset current list
2131 cur_vars->my_list = InitList;
2134 * create two containers.
2136 if (0 == CheckList(&(flowList), 2, 2))
2139 * point to the containers for the graphic and body.
2141 graphSeg = flowList.list;
2142 bodySeg = flowList.list;
2146 * set the bottom margins to zero.
2148 graphSeg->type = _DtCvSetTypeToContainer(graphSeg->type);
2149 bodySeg->type = _DtCvSetTypeToContainer(bodySeg->type);
2150 _DtCvContainerBMarginOfSeg(graphSeg) = 0;
2151 _DtCvContainerBMarginOfSeg(bodySeg) = 0;
2154 * so the first segment is the container for the graphic.
2155 * set the controller flag and values.
2157 graphSeg->type = _DtCvSetTypeToController(graphSeg->type);
2158 _DtCvContainerFlowOfSeg(graphSeg) = _DtCvWRAP;
2159 _DtCvContainerPercentOfSeg(graphSeg) = 0;
2160 _DtCvContainerOrientOfSeg(graphSeg) = gpos;
2161 if (_DtCvJUSTIFY_LEFT == gpos)
2163 _DtCvContainerJustifyOfSeg(graphSeg) = gpos;
2164 _DtCvContainerRMarginOfSeg(graphSeg) = gspace;
2168 _DtCvContainerJustifyOfSeg(graphSeg) = gpos;
2169 _DtCvContainerLMarginOfSeg(graphSeg) = gspace;
2173 * mark the first segment as used.
2178 * check for hypertext link.
2181 type = _DtCvHYPER_TEXT;
2184 * re-set the segment list and create the graphic.
2186 if (0 == CreateSaveGraphic(cur_vars, type, file_name, link_idx))
2189 * so the first segment in cur_vars is a region.
2190 * attach it to the graphic container.
2192 _DtCvContainerListOfSeg(graphSeg) = cur_vars->my_list.list;
2195 * now process the following information as the body of
2196 * the paragraph as the list for the non-controller
2199 cur_vars->my_list = InitList;
2200 if (-1 != Parse (CCDF_PARAGRAPH_CMD, cur_state, cur_vars,
2204 ret_on_nl, fnt_flag))
2207 * establish the links between the segments
2209 TerminateSegList(&(cur_vars->my_list), True);
2212 * if there was a segment list generated,
2213 * attach the it to the non-controller
2214 * container and mark it as used.
2216 if (NULL != cur_vars->my_list.list)
2218 _DtCvContainerListOfSeg(bodySeg) = cur_vars->my_list.list;
2226 cur_vars->my_list = flowList;
2227 TerminateSegList(&(cur_vars->my_list), True);
2231 /******************************************************************************
2232 * Function: int ProcessParagraph (
2240 * Purpose: Process the <PARAGRAPH> specification.
2242 *****************************************************************************/
2245 FormatVariables *cur_vars,
2246 ProcessState cur_state,
2250 int labelFnd = False;
2251 int allowed = ~(CCDF_TOPIC_CMD | CCDF_TITLE_CMD | CCDF_ABBREV_CMD);
2252 int oldMbLenMax = cur_vars->cur_mb_max;
2255 _DtCvUnit gspace = 0;
2256 char *glinkSpec = NULL;
2258 char *fileName = NULL;
2259 char *description = NULL;
2262 ProcessState myState = NormalState;
2263 _DtCvFrmtOption gpos;
2264 _DtCvFrmtOption frmtType = _DtCvDYNAMIC;
2265 _DtCvSegment *paraSeg;
2266 _DtCvSegment *labelSeg = NULL;
2267 _DtCvSegment *col1 = NULL;
2268 _DtCvSegment *col2 = NULL;
2269 _DtCvSegment **childList;
2271 SegList tableList = InitList;
2272 _DtHelpFontHints fontAttrs;
2275 * remember the old font list.
2276 * initialize the font quark list
2277 * and use the char set specified for this topic.
2279 _DtHelpCeCopyDefFontAttrList (&fontAttrs);
2280 cur_vars->cur_mb_max = cur_vars->topic_mb_max;
2281 _DtHelpFontHintsLang(fontAttrs) = cur_vars->topic_lang;
2282 _DtHelpFontHintsCharSet(fontAttrs) = cur_vars->topic_char_set;
2285 * Make next segment in my parent's list for a container for this
2288 if (-1 == CheckSegList(cur_vars))
2292 * remember the parent list
2293 * make sure the defaults are set
2295 oldList = cur_vars->my_list;
2296 paraSeg = NextAvailSeg(cur_vars->my_list);
2297 paraSeg->handle.container = DefContainer;
2298 paraSeg->type = _DtCvSetTypeToContainer(paraSeg->type);
2299 _DtCvContainerLeadingOfSeg(paraSeg) = cur_vars->ui_info->leading;
2300 cur_vars->my_list = InitList;
2303 * get the parameters on the paragraph
2304 * and set the default for the bottom.
2306 result = GetParagraphParameters (cur_vars, paraSeg, &frmtType,
2307 &gpos, &glinkSpec, &glinktype, &gspace,
2308 &label, &fileName, &description);
2311 * for lists, we will inherit our parent's bottom margin
2312 * when we return to the loop processing the list. Therefore,
2313 * set our bottom margin to zero if we are part of a label body.
2315 if (0 == result && LabelBody == cur_state)
2316 _DtCvContainerBMarginOfSeg(paraSeg) = 0;
2317 else if (result > 0)
2321 * check for a label specification. Either as a 'label' parameter
2322 * or a the <LABEL> command.
2327 * check for the parameter
2331 FormatVariables oldVars = *cur_vars;
2333 cur_vars->rd_buf = label;
2334 cur_vars->rd_flag = 0;
2335 cur_vars->rd_ptr = label;
2336 cur_vars->my_file = NULL;
2338 result = Parse (CCDF_LABEL_CMD, NormalState, cur_vars,
2342 (CCDF_FONT_CMD | CCDF_OCTAL_CMD),
2346 result = CheckSaveSegment (_DtCvSTRING, &fontAttrs,
2349 TerminateSegList(&(cur_vars->my_list), True);
2350 cur_vars->rd_buf = oldVars.rd_buf;
2351 cur_vars->rd_flag = oldVars.rd_flag;
2352 cur_vars->rd_ptr = oldVars.rd_ptr;
2353 cur_vars->my_file = oldVars.my_file;
2354 cur_vars->last_was_space = True;
2356 labelSeg = cur_vars->my_list.list;
2357 cur_vars->my_list = InitList;
2361 * check for the command.
2363 else if (0 == _DtHelpCeCheckNextCcdfCmd("lab", cur_vars->my_file,
2365 cur_vars->rd_size, 1,
2366 &(cur_vars->rd_ptr)))
2368 result = ProcessLabelCmd(cur_vars, 0, frmtType,
2370 allowed, False, fnt_flag,
2376 * if a label was processed, create the containers for it.
2378 if (-1 != result && True == labelFnd)
2381 * set the correct state.
2383 myState = LabelBody;
2386 * create containers for the label and it's body
2388 result = CheckList(&tableList, 2, 2);
2392 * set the top and bottom margins on both the child
2393 * containers (so they are the same) to reflect
2394 * the list's before/after values.
2397 * set the pointer to the first column
2398 * overwrite the left and right margin values.
2400 col1 = NextAvailSeg(tableList);
2401 col1->type = _DtCvSetTypeToContainer(col1->type);
2402 _DtCvContainerTMarginOfSeg(col1) =
2403 _DtCvContainerTMarginOfSeg(paraSeg);
2404 _DtCvContainerBMarginOfSeg(col1) =
2405 _DtCvContainerBMarginOfSeg(paraSeg);
2406 _DtCvContainerLMarginOfSeg(col1) = 0;
2407 _DtCvContainerRMarginOfSeg(col1) = cur_vars->ui_info->avg_char;
2411 * set the pointer for the second column
2412 * and set the top/bottom values.
2414 col2 = NextAvailSeg(tableList);
2415 col2->type = _DtCvSetTypeToContainer(col2->type);
2416 _DtCvContainerTMarginOfSeg(col2) =
2417 _DtCvContainerTMarginOfSeg(paraSeg);
2418 _DtCvContainerBMarginOfSeg(col2) =
2419 _DtCvContainerBMarginOfSeg(paraSeg);
2423 * create an id for this label
2425 sprintf(numChar, "%d", cur_vars->cell_cnt++);
2426 _DtCvContainerIdOfSeg(col1) = (char *) malloc (
2427 strlen("&CCDF_RES_") + strlen(numChar) + 1);
2428 if (NULL != _DtCvContainerIdOfSeg(col1))
2431 * copy over the id and attach the list.
2433 strcpy(_DtCvContainerIdOfSeg(col1), "&CCDF_RES_");
2434 strcat(_DtCvContainerIdOfSeg(col1), numChar);
2435 _DtCvContainerListOfSeg(col1) = labelSeg;
2438 * set the id for the second column.
2440 sprintf(numChar, "%d", cur_vars->cell_cnt++);
2441 _DtCvContainerIdOfSeg(col2) = (char *) malloc (
2442 strlen("&CCDF_RES_") + strlen(numChar) + 1);
2443 if (NULL != _DtCvContainerIdOfSeg(col2))
2445 strcpy(_DtCvContainerIdOfSeg(col2), "&CCDF_RES_");
2446 strcat(_DtCvContainerIdOfSeg(col2), numChar);
2458 * disallow labels from here on out. Either one was found and processed
2461 allowed &= (~(CCDF_LABEL_CMD));
2464 * Now check and process the graphic specification.
2469 * initialize the segment list for the children of the paragraph.
2471 cur_vars->my_list = InitList;
2474 * check for a graphic in the specification.
2475 * If so, then we need to create, as the list for the
2476 * paragraph container, two containers; one container
2477 * that is a controller and has the graphic and the
2478 * other contains the rest of the content of the
2481 * First, create the link index for the graphic.
2483 if (NULL != glinkSpec)
2486 * but if there isn't a graphic, throw away the link
2487 * specifications since they are useless!
2489 if (NULL != fileName && strlen (glinkSpec))
2491 linkIndex = _DtLinkDbAddLink (cur_vars->my_links,
2494 ReturnLinkType(glinktype, glinkSpec),
2495 ReturnLinkWinHint(glinktype),
2499 * had problems creating the link index, bail
2501 if (linkIndex == -1)
2507 * now create the graphic and process the graphic body..
2508 * or just process the rest of the paragraph....
2512 if (NULL != fileName)
2513 result = FlowingParagraph(cur_vars,
2518 gpos, gspace, fileName,
2522 result = Parse (CCDF_PARAGRAPH_CMD, myState, cur_vars,
2530 * establish the links
2532 TerminateSegList (&(cur_vars->my_list), True);
2540 _DtCvFrmtOption *colJ;
2542 if (True == labelFnd)
2544 char *colW1 = "1"; /* default bulletted list */
2545 char *colW2 = "99,0,98"; /* default bulletted list */
2549 * set the body of the label in it's container.
2551 _DtCvContainerListOfSeg(col2) = cur_vars->my_list.list;
2554 * figure out which column widths should be used.
2556 if (14 * cur_vars->ui_info->avg_char
2557 == _DtCvContainerLMarginOfSeg(paraSeg))
2563 else if (3 * cur_vars->ui_info->avg_char
2564 == _DtCvContainerLMarginOfSeg(paraSeg))
2567 else if (0 == _DtCvContainerLMarginOfSeg(paraSeg))
2572 * create the column width strings.
2575 colW = (char **) _DtCvAddPtrToArray((void **) colW,
2576 ((void *) strdup(colW1)));
2578 colW = (char **) _DtCvAddPtrToArray((void **) colW,
2579 ((void *) strdup (colW2)));
2582 * create the array for column justification.
2584 colJ = (_DtCvFrmtOption *) malloc (sizeof(_DtCvFrmtOption) * 2);
2587 colJ[0] = _DtCvJUSTIFY_LEFT;
2588 colJ[1] = _DtCvJUSTIFY_LEFT;
2592 * set this segment's type to a table and fill in all
2593 * the relevant information.
2595 paraSeg->type = _DtCvTABLE;
2596 _DtCvNumColsOfTableSeg(paraSeg) = 2;
2597 _DtCvColWOfTableSeg(paraSeg) = colW;
2598 _DtCvColJustifyOfTableSeg(paraSeg) = colJ;
2599 _DtCvJustifyCharsOfTableSeg(paraSeg) = NULL;
2602 * now create the list of ids in this table.
2604 ids = (char *) malloc (
2605 strlen(_DtCvContainerIdOfSeg(col1)) +
2606 strlen(_DtCvContainerIdOfSeg(col2)) + 2);
2609 strcpy(ids, _DtCvContainerIdOfSeg(col1));
2611 strcat(ids, _DtCvContainerIdOfSeg(col2));
2613 _DtCvCellIdsOfTableSeg(paraSeg) = NULL;
2614 _DtCvCellIdsOfTableSeg(paraSeg) = (char **)
2616 (void **) _DtCvCellIdsOfTableSeg(paraSeg),
2620 * now create the list of cells in the table.
2622 _DtCvCellsOfTableSeg(paraSeg) = NULL;
2623 _DtCvCellsOfTableSeg(paraSeg) = (_DtCvSegment **)
2625 (void **) _DtCvCellsOfTableSeg(paraSeg),
2627 if (NULL != _DtCvCellsOfTableSeg(paraSeg))
2628 _DtCvCellsOfTableSeg(paraSeg) = (_DtCvSegment **)
2630 (void **) _DtCvCellsOfTableSeg(paraSeg),
2633 if (NULL == colW || NULL == colJ || NULL == ids
2634 || NULL == _DtCvCellIdsOfTableSeg(paraSeg)
2635 || NULL == _DtCvCellsOfTableSeg(paraSeg))
2643 * attach the list to my container.
2645 _DtCvContainerListOfSeg(paraSeg) = cur_vars->my_list.list;
2648 * consolidate any table children I have.
2650 for (pSeg = cur_vars->my_list.list, labelSeg = NULL;
2651 -1 != result && NULL != pSeg;
2652 pSeg = pSeg->next_seg)
2654 if (_DtCvIsSegTable(pSeg))
2656 if (NULL != labelSeg)
2659 * bypass this segment since it will no
2660 * longer be 'used' by consolidating it
2661 * with another label set.
2663 labelSeg->next_seg = pSeg->next_seg;
2666 * free the other justification and width info.
2668 free((void *) _DtCvColJustifyOfTableSeg(pSeg));
2669 colW = _DtCvColWOfTableSeg(pSeg);
2672 free(_DtCvColWOfTableSeg(pSeg));
2675 * add the segments to the list
2677 childList = _DtCvCellsOfTableSeg(pSeg);
2678 _DtCvCellsOfTableSeg(labelSeg) = (_DtCvSegment **)
2680 (void **) _DtCvCellsOfTableSeg(labelSeg),
2683 if (NULL != _DtCvCellsOfTableSeg(labelSeg))
2684 _DtCvCellsOfTableSeg(labelSeg) = (_DtCvSegment **)
2686 (void **)_DtCvCellsOfTableSeg(labelSeg),
2688 free((void *) _DtCvCellsOfTableSeg(pSeg));
2691 * add the ids to the list
2693 _DtCvCellIdsOfTableSeg(labelSeg) = (char **)
2695 (void **)_DtCvCellIdsOfTableSeg(labelSeg),
2696 (void *)(*(_DtCvCellIdsOfTableSeg(pSeg))));
2698 free((void *) _DtCvCellIdsOfTableSeg(pSeg));
2700 if (NULL == _DtCvCellIdsOfTableSeg(labelSeg)
2701 || NULL == _DtCvCellsOfTableSeg(labelSeg))
2707 * this segment becomes the segment holding
2708 * the consolidated table.
2721 * restore the font MB_CUR_MAX
2723 cur_vars->cur_mb_max = oldMbLenMax;
2726 * free all the strings
2730 if (fileName != NULL)
2734 * free the linkSpec and description,
2736 if (NULL != description)
2738 if (NULL != glinkSpec)
2745 cur_vars->my_list = oldList;
2746 cur_vars->last_was_space = True;
2749 } /* End ProcessParagraph */
2751 /******************************************************************************
2752 * Function: int ProcessHypertext (
2753 * FormatVariables *cur_vars, int segType,
2754 * char **font_attr, int flags )
2757 * segType Specifies the type of segment currently
2759 * font_attr Specifies the list of font quarks to
2760 * associate with the string.
2761 * flags Specifies the formatting commands allowed.
2763 * Returns: 0 if successful, -1 if errors.
2767 * Purpose: Process the <LINK> specification.
2769 *****************************************************************************/
2772 FormatVariables *cur_vars,
2773 ProcessState cur_state,
2774 unsigned long seg_flags,
2775 _DtCvFrmtOption frmt_type,
2776 _DtHelpFontHints *font_attr,
2784 char *description = NULL;
2785 char *hyperlink = NULL;
2788 * is a <LINK> command allowed here?
2790 if (CCDF_NOT_ALLOW_CMD(flags, CCDF_LINK_CMD))
2794 * get the hypertext type
2796 if (GetValueParameter (cur_vars, _DtCvTRUE, &hyperType) < 0)
2801 errno = CEErrorHyperType;
2806 * get the hypertext link spec.
2808 result = GetStringParameter(cur_vars, _DtCvTRUE, _DtCvTRUE, _DtCvFALSE,
2809 _DtCvFALSE, &hyperlink);
2813 * See if we have the optional description string
2815 result = GetStringParameter (cur_vars, _DtCvFALSE, _DtCvTRUE,
2816 _DtCvFALSE, _DtCvFALSE, &description);
2820 result = _DtLinkDbAddLink (cur_vars->my_links,
2823 ReturnLinkType(hyperType, hyperlink),
2824 ReturnLinkWinHint(hyperType),
2826 if (NULL != description)
2833 * if no problems encountered, start parsing with this
2838 hyperIndex = result;
2839 result = FindEndMarker (cur_vars);
2843 * set the hypertext flag and type.
2845 seg_flags = _DtCvSetTypeToHyperText(seg_flags);
2847 result = Parse (CCDF_LINK_CMD, cur_state, cur_vars,
2848 seg_flags, frmt_type,
2852 ret_on_nl, fnt_flag);
2857 * Don't free the hypertext string or description.
2858 * It is now owned by the Link List.
2866 } /* End ProcessHypertext */
2868 /******************************************************************************
2869 * Function: int ProcessLabelCmd (
2870 * FormatVariables *cur_vars, int seg_type,
2871 * char **font_attr, int link_spec,
2875 * font_attr Specifies the list of font quarks to
2876 * associate with the string.
2877 * link_spec Specifies the hypertext link to associate
2879 * flags Specifies the formatting commands allowed.
2881 * Returns: 0 if successful, -1 if errors.
2885 * Purpose: Process the <LABEL> specification.
2887 *****************************************************************************/
2890 FormatVariables *cur_vars,
2891 unsigned long seg_flags,
2892 _DtCvFrmtOption frmt_type,
2893 _DtHelpFontHints *font_attr,
2898 _DtCvSegment **ret_list)
2900 SegList oldList = cur_vars->my_list;
2903 * is a <LABEL> command allowed?
2905 if (CCDF_NOT_ALLOW_CMD(flags, CCDF_LABEL_CMD))
2909 * can't have another <LABEL> command inside this one
2911 flags &= (~(CCDF_LABEL_CMD));
2914 * Find the end marker
2916 if (FindEndMarker (cur_vars) != 0)
2919 cur_vars->my_list = InitList;
2920 if (Parse (CCDF_LABEL_CMD, NormalState, cur_vars,
2926 ret_on_nl, fnt_flag) == -1)
2930 * set the links, return the segment list and restore the old list.
2932 TerminateSegList(&(cur_vars->my_list), True);
2933 *ret_list = cur_vars->my_list.list;
2934 cur_vars->my_list = oldList;
2937 * Indicate that preceding space on the next text should be ignored
2939 cur_vars->last_was_space = True;
2943 } /* End ProcessLabelCmd */
2945 /******************************************************************************
2946 * Function: int ProcessFigureCmd (
2947 * FormatVariables *cur_vars,
2951 * font_attr Specifies the list of font quarks to
2952 * associate with the string.
2954 * Returns: 0 if successful, -1 if errors.
2958 * Purpose: Process the <FIGURE> specification.
2960 *****************************************************************************/
2963 FormatVariables *cur_vars,
2964 ProcessState cur_state,
2965 _DtCvFrmtOption frmt_type,
2966 _DtHelpFontHints *font_attr,
2973 int linkType = CCDF_LINK_JUMP_REUSE;
2975 int segType = _DtCvREGION;
2976 char *description = NULL;
2977 char *idString = NULL;
2978 char *filename = NULL;
2979 char *linkspec = NULL;
2980 _DtCvFrmtOption vertOrientCap = _DtCvJUSTIFY_BOTTOM;
2981 _DtCvFrmtOption horzOrientCap = _DtCvJUSTIFY_CENTER;
2982 _DtCvFrmtOption justifyCap = _DtCvJUSTIFY_CENTER;
2983 _DtCvFrmtOption justifyGraphic = _DtCvJUSTIFY_CENTER;
2984 _DtCvSegment *figContainer;
2987 SegList figList = InitList;
2990 * create a container for this figure (and possibly a caption)
2992 if (-1 == CheckSegList(cur_vars))
2995 figContainer = NextAvailSeg(cur_vars->my_list);
2996 figContainer->handle.container = DefContainer;
2997 figContainer->type = _DtCvSetTypeToContainer(figContainer->type);
2998 _DtCvContainerLeadingOfSeg(figContainer) = cur_vars->ui_info->leading;
3001 * remember the old list and initialize for the figure.
3003 oldList = cur_vars->my_list;
3004 cur_vars->my_list = InitList;
3007 * process the parameters of the figure cmd.
3009 while (!done && result != -1)
3011 if (SkipToNextToken (cur_vars, _DtCvFALSE) == -1)
3017 switch (_DtCvToLower(*(cur_vars->rd_ptr)))
3020 * end of figure spec
3024 * move past the end of token marker
3025 * and skip the leading blanks in the caption.
3027 (cur_vars->rd_ptr)++;
3028 while (result != -1 && !done)
3030 if (*(cur_vars->rd_ptr) == '\0')
3031 result = GetNextBuffer (cur_vars);
3032 else if ((cur_vars->cur_mb_max == 1 ||
3033 mblen(cur_vars->rd_ptr, cur_vars->cur_mb_max) == 1)
3034 && *(cur_vars->rd_ptr) == ' ')
3035 (cur_vars->rd_ptr)++;
3051 * Go to the next character.
3053 (cur_vars->rd_ptr)++;
3056 * Do we need to read more information?
3058 if (*(cur_vars->rd_ptr) == '\0' && GetNextBuffer (cur_vars) == -1)
3064 * look at the next charager to determine the token.
3066 switch (_DtCvToLower(*(cur_vars->rd_ptr)))
3068 case 'c': /* caption center */
3069 justifyCap = _DtCvJUSTIFY_CENTER;
3070 horzOrientCap = _DtCvJUSTIFY_CENTER;
3073 case 'e': /* graphic centered */
3074 justifyGraphic = _DtCvJUSTIFY_CENTER;
3077 case 'b': /* caption below graphic */
3078 vertOrientCap = _DtCvJUSTIFY_BOTTOM;
3081 case 'l': /* caption justified left */
3082 justifyCap = _DtCvJUSTIFY_LEFT;
3083 horzOrientCap = _DtCvJUSTIFY_LEFT_MARGIN;
3086 case 'r': /* caption right justified */
3087 justifyCap = _DtCvJUSTIFY_RIGHT;
3088 horzOrientCap = _DtCvJUSTIFY_RIGHT_MARGIN;
3091 case 't': /* caption at top */
3092 vertOrientCap = _DtCvJUSTIFY_TOP;
3099 * description [string | "string" | 'string']
3102 result = GetStringParameter (cur_vars, _DtCvTRUE, _DtCvTRUE,
3103 _DtCvFALSE, _DtCvFALSE, &description);
3110 result = GetStringParameter (cur_vars, _DtCvTRUE, _DtCvTRUE,
3111 _DtCvFALSE, _DtCvFALSE, &filename);
3121 result = GetStringParameter (cur_vars, _DtCvTRUE, _DtCvTRUE,
3122 _DtCvFALSE, _DtCvFALSE, &idString);
3124 * if this figure had an id associated with it, create
3125 * marker segment for it.
3127 if (-1 != result && NULL != idString && '\0' != *idString)
3130 * create the marker. If there is an error, free the
3133 result = CreateMarker(cur_vars, idString);
3141 * link [string | "string" | 'string']
3145 * Go to the next character.
3147 (cur_vars->rd_ptr)++;
3150 * Do we need to read more information?
3152 if (*(cur_vars->rd_ptr) == '\0' && GetNextBuffer (cur_vars) == -1)
3158 * look at the next charager to determine the token.
3160 switch (_DtCvToLower(*(cur_vars->rd_ptr)))
3163 justifyGraphic = _DtCvJUSTIFY_LEFT;
3167 segType = _DtCvSetTypeToHyperText (segType);
3168 result = GetStringParameter (cur_vars, _DtCvTRUE,
3169 _DtCvTRUE, _DtCvFALSE, _DtCvFALSE,
3183 justifyGraphic = _DtCvJUSTIFY_RIGHT;
3190 if (GetValueParameter (cur_vars, _DtCvTRUE, &linkType) == -1)
3192 else if (linkType < 0)
3194 errno = CEErrorHyperType;
3204 if (result != -1 && (filename == NULL || strlen(filename) == 0))
3210 * check to see if the hypertext flag is set but we don't
3211 * have a link specification.
3213 if (IsTypeHyperText(segType) && !linkspec)
3215 segType = segType & ~(_DtCvHYPER_TEXT);
3217 if (NULL != description)
3223 * do we still have a good hypertext?
3224 * if so, create a link index for it.
3226 if (IsTypeHyperText(segType))
3228 linkIndex = _DtLinkDbAddLink (cur_vars->my_links,
3231 ReturnLinkType(linkType, linkspec),
3232 ReturnLinkWinHint(linkType),
3234 if (linkIndex == -1)
3242 * parse the caption. If there is a caption, we will need to
3243 * wrap it and the figure in containers with the appropriate
3244 * controller flags set to get the correct layout.
3246 result = Parse (CCDF_FIGURE_CMD, cur_state, cur_vars,
3250 (CCDF_NEWLINE_CMD | CCDF_LINK_CMD |
3251 CCDF_FONT_CMD | CCDF_ID_CMD),
3252 ret_on_nl, fnt_flag);
3255 * save the caption List.
3257 TerminateSegList(&(cur_vars->my_list), True);
3258 capList = cur_vars->my_list;
3261 * is there a caption? If so, create two segments instead
3265 if (-1 != result && 0 != capList.cnt)
3269 * allocate room for the figure (and caption)
3272 result = CheckList(&figList, cnt, cnt);
3277 * process any caption that was specified
3279 if (0 != capList.cnt)
3281 _DtCvSegment *pSeg = figList.list;
3284 * create a controller for the caption.
3286 pSeg->type = _DtCvSetTypeToController(
3287 _DtCvSetTypeToContainer(pSeg->type));
3290 * set its orientation and justification.
3292 _DtCvContainerOrientOfSeg(pSeg) = horzOrientCap;
3293 _DtCvContainerVOrientOfSeg(pSeg) = vertOrientCap;
3294 _DtCvContainerJustifyOfSeg(pSeg) = justifyCap;
3295 _DtCvContainerBMarginOfSeg(pSeg) = 0;
3298 * attach the caption to the container.
3300 _DtCvContainerListOfSeg(pSeg) = capList.list;
3303 * indicate this segment has been used.
3309 * now load the graphic into the next available segment
3310 * allocated for the figure.
3312 cur_vars->my_list = figList;
3313 result = CreateSaveGraphic (cur_vars, segType, filename, linkIndex);
3316 * if no problems, attach the figure (and caption) to the
3324 TerminateSegList(&(cur_vars->my_list), True);
3327 * attach the figure (and caption) to the wrapper
3329 _DtCvContainerListOfSeg(figContainer) = cur_vars->my_list.list;
3332 * set the justify to the correct value to act on the
3335 _DtCvContainerJustifyOfSeg(figContainer) = justifyGraphic;
3338 * indicate that this segment has been used
3346 * restore the segment list.
3349 cur_vars->my_list = oldList;
3353 * don't free the link string or description,
3354 * the link list owns them now.
3359 } /* End ProcessFigureCmd */
3361 /******************************************************************************
3362 * Function: int ProcessInLine (FormatVariables cur_vars,
3363 * int seg_type, int link_spec )
3366 * seg_type Specifes the type of segment currently
3368 * link_spec Specifies the hypertext link associated
3369 * with this segment.
3371 * Returns: 0 if successful, -1 if errors.
3375 * Purpose: Process a <GRAPHIC> specification.
3377 *****************************************************************************/
3380 FormatVariables *cur_vars,
3386 char *idString = NULL;
3387 char *filename = NULL;
3390 * process the graphic parameters
3392 while (!done && result != -1)
3394 if (SkipToNextToken (cur_vars, _DtCvFALSE) == -1)
3397 switch (_DtCvToLower(*(cur_vars->rd_ptr)))
3400 * end of in line spec
3404 * move past the end of token marker
3406 (cur_vars->rd_ptr)++;
3414 result = GetStringParameter (cur_vars, _DtCvTRUE, _DtCvTRUE,
3415 _DtCvFALSE, _DtCvFALSE, &filename);
3425 result = GetStringParameter (cur_vars, _DtCvTRUE, _DtCvTRUE,
3426 _DtCvFALSE, _DtCvFALSE, &idString);
3428 * if this graphic had an id associated with it, create
3429 * marker segment for it.
3431 if (-1 != result && NULL != idString && '\0' != *idString)
3434 * create the marker. If there is an error, free the
3437 result = CreateMarker(cur_vars, idString);
3449 if (result != -1 && (filename == NULL || strlen(filename) == 0))
3455 * create the graphic.
3457 result = CreateSaveGraphic (cur_vars,
3458 _DtCvSetTypeToInLine(seg_type),
3459 filename, link_spec);
3460 cur_vars->last_was_space = False;
3467 } /* End ProcessInLine */
3469 /******************************************************************************
3470 * Function: int CheckIdString (
3471 * FormatVariables *cur_vars, int segType,
3472 * char **font_attr, int linkspec,
3476 * segType Specifies the type of segment currently
3478 * font_attr Specifies the list of font quarks to
3479 * associate with the string.
3480 * linkspec Specifies the hypertext link associated
3482 * flags Specifies the formatting commands allowed.
3484 * Returns: 0 if successful, -1 if errors.
3488 * Purpose: Create a marker at this location.
3490 *****************************************************************************/
3493 FormatVariables *cur_vars,
3494 ProcessState cur_state,
3495 unsigned long seg_flags,
3496 _DtCvFrmtOption frmt_type,
3497 _DtHelpFontHints *font_attr,
3507 * is it legal to have a <ID> command at this point?
3509 if (CCDF_NOT_ALLOW_CMD (flags, CCDF_ID_CMD))
3514 * clear out any current information in the buffer
3515 * and make sure there is a segment available.
3517 if (-1 != GetStringParameter (cur_vars, _DtCvTRUE, _DtCvTRUE,
3518 _DtCvFALSE, _DtCvFALSE, &ptr)
3520 -1 != CheckSaveSegment (seg_flags, font_attr, linkspec, cur_vars))
3523 * create the marker. If there is an error, free the
3526 result = CreateMarker(cur_vars, ptr);
3531 * find the end of the <ID> syntax
3532 * and parse the data between the begin <ID> and </ID>.
3534 if (0 == result && -1 != FindEndMarker (cur_vars) &&
3535 -1 != Parse (CCDF_ID_CMD, cur_state, cur_vars,
3536 seg_flags, frmt_type,
3540 ret_on_nl, fnt_flag))
3545 * return an error code if necessary
3549 } /* End CheckIdString */
3551 /******************************************************************************
3552 * Function: int Parse (int cur_cmd,
3553 * FormatVariables *cur_vars, int segType,
3555 * int linkspec, int allowed)
3558 * cur_cmd Specifies the current formatting command
3560 * parent Specifies the parent paragraph.
3561 * segType Specifies the type of segment currently
3563 * font_attr Specifies the list of font quarks to
3564 * associate with the string.
3565 * linkspec Specifies the hypertext link associated
3567 * allowed Specifies the formatting commands allowed.
3570 * 1 if ran into a </> specification.
3575 * Purpose: Parse the data.
3577 *****************************************************************************/
3581 ProcessState cur_state,
3582 FormatVariables *cur_vars,
3583 unsigned long seg_flags,
3584 _DtCvFrmtOption frmt_type,
3585 _DtHelpFontHints *font_attr,
3587 const char *scan_string,
3595 int fontType = False;
3596 int cmdType = False;
3601 if (cur_vars->cur_mb_max != 1)
3602 charSize = mblen(cur_vars->rd_ptr, cur_vars->cur_mb_max);
3607 * check to see if a newline was the previous character.
3608 * If so, it may need to be replaced with a space.
3610 if (cur_vars->last_was_nl == True &&
3611 AppendSpaceToInfo(cur_vars, NULL, frmt_type) == -1)
3614 cur_vars->last_was_nl = False;
3615 cur_vars->last_was_mb = False;
3617 switch (*(cur_vars->rd_ptr))
3621 * Go to the next character.
3623 (cur_vars->rd_ptr)++;
3628 cmdType = _DtHelpCeGetCcdfCmd (cur_cmd, cur_vars->rd_buf,
3629 &(cur_vars->rd_ptr),
3638 case CCDF_FIGURE_CMD:
3639 if (CheckSaveSegment(seg_flags, font_attr,
3640 linkspec, cur_vars) == -1
3642 ProcessFigureCmd(cur_vars,
3646 ret_on_nl, fnt_flag) == -1)
3659 fontType = _DtHelpCeGetCcdfFontType (cur_vars->rd_ptr);
3660 done = ChangeFont(fontType, seg_flags,
3662 font_attr , linkspec,
3674 case CCDF_FORMAT_END:
3675 if (CheckSaveSegment(seg_flags, font_attr,
3676 linkspec, cur_vars) == -1 ||
3677 FindEndMarker (cur_vars) == -1)
3685 case CCDF_GRAPHIC_CMD:
3687 * clear out any information
3688 * in the buffer and then
3689 * process the figure.
3691 if (CheckSaveSegment (seg_flags, font_attr,
3692 linkspec, cur_vars) == -1
3694 ProcessInLine (cur_vars, seg_flags,
3703 done = CheckIdString (cur_vars,
3710 ret_on_nl, fnt_flag);
3717 if (CheckSaveSegment (seg_flags, font_attr,
3718 linkspec, cur_vars) == -1
3720 ProcessHypertext(cur_vars, cur_state,
3721 seg_flags, frmt_type,
3723 ret_on_nl, fnt_flag) == -1)
3730 case CCDF_NEWLINE_CMD:
3731 if (SaveNewLine (cur_vars, seg_flags, font_attr,
3734 FindEndMarker (cur_vars) == -1)
3738 case CCDF_OCTAL_CMD:
3739 if (AppendOctalToInfo(cur_vars,
3740 cur_vars->rd_ptr) == -1
3741 || FindEndMarker (cur_vars) == -1)
3748 case CCDF_PARAGRAPH_CMD:
3749 if (CheckSaveSegment (seg_flags, font_attr,
3750 linkspec, cur_vars) == -1
3752 ProcessParagraph(cur_vars, cur_state,
3759 * this should never be hit if the markup is
3760 * correct. Processing labels is through the
3761 * the paragraph processor now.
3763 case CCDF_LABEL_CMD:
3775 * Go to the next character
3777 (cur_vars->rd_ptr)++;
3780 * If processing a static segment, we want to
3781 * keep the author defined end-of-lines.
3783 * Otherwise, we throw them away.
3785 if (_DtCvLITERAL == frmt_type || True == ret_on_nl)
3787 done = SaveStringAsSegments (cur_vars,
3788 _DtCvSetTypeToNewLine(seg_flags),
3789 font_attr, linkspec);
3794 else if (cur_vars->last_was_space == False)
3795 cur_vars->last_was_nl = True;
3801 * go past this character.
3803 (cur_vars->rd_ptr)++;
3806 * append 1-8 characters on the end of the buffer.
3808 _DtHelpCeCountChars(cur_vars->fmt_buf, MB_CUR_MAX,
3810 leftOver = leftOver % 8;
3811 ptr = ((char *) SpaceString) + leftOver;
3812 done = _DtHelpCeAddStrToBuf (&ptr,
3813 &(cur_vars->fmt_buf),
3814 &(cur_vars->fmt_size),
3815 &(cur_vars->fmt_buf_max),
3822 * The author has escaped a character.
3823 * Increment to the escaped character.
3825 (cur_vars->rd_ptr)++;
3828 * Do we need to read more information?
3830 if (*(cur_vars->rd_ptr) == '\0' &&
3831 GetNextBuffer (cur_vars) == -1)
3834 * If we didn't read more information or
3835 * was successful on the read, save the
3836 * escaped character.
3838 done = AppendCharToInfo (cur_vars, &(cur_vars->rd_ptr));
3843 * Put a space in the segment.
3845 done = AppendSpaceToInfo (cur_vars,
3846 &(cur_vars->rd_ptr), frmt_type);
3851 * put the information in the buffer
3853 if (AppendToInfo (cur_vars, &(cur_vars->rd_ptr),
3859 else if (charSize > 1)
3861 if ((cur_vars->ui_info->nl_to_space == 1 ||
3862 (cur_vars->last_was_mb == False
3863 && cur_vars->last_was_nl == True))
3864 && AppendSpaceToInfo(cur_vars, NULL, frmt_type) == -1)
3867 cur_vars->last_was_nl = False;
3868 cur_vars->last_was_mb = True;
3869 if (AppendToInfo (cur_vars, &(cur_vars->rd_ptr), scan_string) == -1)
3872 else if (charSize < 0)
3875 * we have either invalid characters or part of a multi-byte
3876 * character. Read the next buffer for more info.
3878 leftOver = strlen (cur_vars->rd_ptr);
3879 if (leftOver < ((int) MB_CUR_MAX))
3881 if (GetNextBuffer (cur_vars) == -1)
3887 * In trouble brothers and sisters. We have garbage in the
3888 * buffer - BAIL OUT!
3893 if (!done && *(cur_vars->rd_ptr) == '\0')
3896 * We're at the end of the buffer, can we read more?
3898 if (cur_vars->rd_flag > 0 && GetNextBuffer (cur_vars) == -1)
3901 if (cur_vars->rd_flag == 0)
3907 * DO NOT MODIFY 'done' HERE
3908 * If you do, the caller is unable to test for return value == 1!!!!
3911 CheckSaveSegment (seg_flags, font_attr, linkspec, cur_vars) == -1)
3917 /*****************************************************************************
3918 * Function: int ParseTitle (FormatVariables cur_vars)
3921 * cur_vars Specifies the current values for formatting.
3923 * Returns: 0 if successful, -1 if failure.
3927 * Purpose: ParseTitle gets the data between a <TITLE> and </TITLE>
3928 * pair; putting it in a controlling container.
3930 *****************************************************************************/
3933 FormatVariables *cur_vars,
3937 _DtHelpFontHints *fontAttrs)
3940 SegList oldList = cur_vars->my_list;
3943 * rest the current segment list
3945 cur_vars->my_list = InitList;
3948 * check for the <TITLE> directive.
3950 if (_DtHelpCeCheckNextCcdfCmd ("ti", cur_vars->my_file, cur_vars->rd_buf,
3951 cur_vars->rd_size, 1, &(cur_vars->rd_ptr)) != 0
3952 || FindEndMarker (cur_vars) != 0)
3957 * 1 when a </> is found,
3958 * 0 if the data runs out before we finish parsing,
3961 * A return of 1 is required from Parse
3963 if (1 == Parse (CCDF_TITLE_CMD, NormalState, cur_vars,
3965 fontAttrs, -1, Specials,
3966 ~(CCDF_TOPIC_CMD | CCDF_TITLE_CMD | CCDF_ABBREV_CMD |
3967 CCDF_PARAGRAPH_CMD | CCDF_FIGURE_CMD | CCDF_LABEL_CMD),
3971 * skip the any abbreviation that might be there
3975 result = _DtHelpCeSkipCcdfAbbrev (cur_vars->my_file,
3977 &(cur_vars->rd_ptr), cur_vars->rd_size,
3978 cur_vars->cur_mb_max);
3981 * if we successfully skipped the abbreviation and there is
3982 * a title - then attach the title body to the controlling
3983 * container (and make the container a controller).
3985 if (result != -1 && cur_vars->my_list.list)
3987 _DtCvSegment *list = oldList.list;
3988 int cnt = oldList.cnt;
3990 TerminateSegList (&(cur_vars->my_list), True);
3993 * when this segment was allocated, it was initialized
3994 * to the correct vertical and horizontal orientation
3995 * for a CCDF title. Simply set the type to container
3996 * and controller to get it to act properly.
4000 list[cnt].type = _DtCvSetTypeToContainer(list[cnt].type);
4001 if (True == cont_flag)
4002 list[cnt].type = _DtCvSetTypeToController(list[cnt].type);
4005 * attach the title body to the controller container.
4007 _DtCvContainerListOfSeg(&list[cnt]) = cur_vars->my_list.list;
4010 * and count this segment as used.
4015 * otherwise, a container hasn't been created for this list.
4016 * but we don't want to loose the information.
4019 oldList.list = cur_vars->my_list.list;
4024 * restore segment usage information.
4026 cur_vars->my_list = oldList;
4031 /*****************************************************************************
4032 * Function: int Format (FormatVariables cur_vars, char *id_string,
4040 * Purpose: Format is the top entry point for formating Help Files with
4041 * formatting information into a form understood by a display area.
4042 * It will keep calling Parse, until the entire topic is read
4043 * or an error occurs.
4045 *****************************************************************************/
4048 FormatVariables *cur_vars,
4049 _FrmtUiInfo *ui_info,
4051 _DtCvTopicPtr *ret_topic )
4056 char *charSet = NULL;
4057 char readBuf[BUFF_SIZE];
4058 _DtHelpFontHints fontAttrs;
4059 _DtCvTopicInfo *topicHandle;
4060 SegList myList = InitList;
4063 * malloc space for the topic handle.
4065 topicHandle = (_DtCvTopicInfo *) malloc (sizeof(_DtCvTopicInfo));
4066 if (topicHandle == NULL)
4070 * initialize the font attributes to the default hints
4072 _DtHelpCeCopyDefFontAttrList (&fontAttrs);
4075 * set up the formatting variable structure
4077 if (InitStructure (cur_vars, ui_info, readBuf, BUFF_SIZE) == -1)
4081 * read the first buffer's worth of the topic.
4083 cur_vars->rd_flag = _DtHelpCeReadBuf (cur_vars->my_file, cur_vars->rd_buf,
4085 if (cur_vars->rd_flag == -1)
4089 * The first command in the buffer MUST be the <TOPIC> command.
4090 * It is in a one byte charset.
4092 if (_DtHelpCeGetCcdfTopicCmd (((void *) NULL), cur_vars->my_file,
4093 cur_vars->rd_buf, &(cur_vars->rd_ptr),
4094 cur_vars->rd_size, 1, &charSet) == -1)
4098 * change the character set to the returned character set
4099 * Assume that the charset is 'iso8859' if not specified.
4101 cur_vars->cur_mb_max = 1;
4102 if (NULL != charSet)
4103 GetMbLen(cur_vars, charSet, &(_DtHelpFontHintsLang(fontAttrs)),
4104 &(_DtHelpFontHintsCharSet(fontAttrs)));
4107 * Remember the topic code set and MB_CUR_MAX.
4109 cur_vars->topic_char_set = _DtHelpFontHintsCharSet(fontAttrs);
4110 cur_vars->topic_lang = _DtHelpFontHintsLang(fontAttrs);
4111 cur_vars->topic_mb_max = cur_vars->cur_mb_max;
4114 * allocate two segments for the topic - one for the <title>
4115 * and one for the body of the topic.
4117 if (0 != CheckList(&(cur_vars->my_list), 2, 2))
4119 if (NULL != charSet)
4121 free(_DtHelpFontHintsLang(fontAttrs));
4122 free(_DtHelpFontHintsCharSet(fontAttrs));
4129 * get the title and skip the abbreviation.
4131 if (0 != ParseTitle(cur_vars, True, True, 0, &fontAttrs))
4133 if (NULL != charSet)
4135 free(_DtHelpFontHintsLang(fontAttrs));
4136 free(_DtHelpFontHintsCharSet(fontAttrs));
4143 * remember this current list since we will be attaching any more
4144 * information as a child of these segments.
4146 myList = cur_vars->my_list;
4149 * process the rest of the information
4151 while (0 == result && !done)
4154 * reset the segment count before processing the information
4155 * for this paragraph
4157 cur_vars->my_list = InitList;
4160 * make sure we've got a container for this paragraph
4162 done = CheckList(&myList, 1, GROW_SIZE);
4165 * now process the information while finding paragraphs.
4169 done = Parse (CCDF_PARAGRAPH_CMD, NormalState, cur_vars,
4171 &fontAttrs, -1, Specials,
4172 ~(CCDF_TOPIC_CMD | CCDF_TITLE_CMD | CCDF_ABBREV_CMD),
4174 } while (0 == done);
4177 * if no errors, attach the resulting child information to the
4178 * paragraph container.
4183 * clean up the last segment.
4185 if (cur_vars->my_list.list)
4187 _DtCvSegment *list = NextAvailSeg(myList);
4189 TerminateSegList (&(cur_vars->my_list), True);
4192 * make it a container.
4194 list->type = _DtCvSetTypeToContainer(list->type);
4197 * attach the information to the container
4199 _DtCvContainerListOfSeg(list) = cur_vars->my_list.list;
4202 * and count this container as used.
4212 * If we had errors, deallocate the memory.
4215 _DtHelpFreeSegments(myList.list, _DtCvFALSE, ui_info->destroy_region,
4216 ui_info->client_data);
4220 * Tighten up the paragraph structures if too many allocated.
4222 if (0 != myList.cnt)
4223 TerminateSegList (&(myList), True);
4226 free ((char *) myList.list);
4232 * return the values, even if they are null and zero.
4235 if (id_string == NULL)
4236 topicHandle->id_str = id_string;
4238 topicHandle->id_str = strdup(id_string);
4240 topicHandle->seg_list = myList.list;
4241 topicHandle->mark_list = NULL;
4242 topicHandle->link_data = cur_vars->my_links;
4244 *ret_topic = (void *) topicHandle;
4249 if (NULL != charSet)
4251 free(_DtHelpFontHintsLang(fontAttrs));
4252 free(_DtHelpFontHintsCharSet(fontAttrs));
4262 /*****************************************************************************
4263 * Function: int FormatCCDFTitle (FormatVariables cur_vars
4266 * cur_vars Specifies the current values for formatting.
4267 * id_string Specifies the id to look for or NULL.
4268 * ret_para Returns a pointer to a list of _DtCvSegment
4270 * ret_num Specifies the number of structures in
4272 * ret_seg Specifies the segment containing 'id_string'
4279 * Purpose: Format is the top entry point for formating Help Files with
4280 * formatting information into a form understood by a display area.
4281 * It will keep calling Parse, until the entire topic is read
4282 * or an error occurs.
4284 *****************************************************************************/
4287 FormatVariables *cur_vars,
4288 _DtHelpFontHints fontAttrs,
4296 char *charSet = NULL;
4298 int origCnt = cur_vars->my_list.cnt;
4300 _DtCvSegment *titleSeg;
4303 cur_vars->rd_buf[0] = '\0';
4304 cur_vars->rd_ptr = cur_vars->rd_buf;
4306 if (_DtHelpCeFileOpenAndSeek(filename, offset, -1,
4307 &(cur_vars->my_file), NULL) != 0)
4310 cur_vars->rd_flag = _DtHelpCeReadBuf (cur_vars->my_file, cur_vars->rd_buf,
4313 if (cur_vars->rd_flag == -1)
4315 _DtHelpCeBufFileClose (cur_vars->my_file, True);
4320 * The first command in the buffer MUST be the <TOPIC> command.
4321 * It is in a one byte charset.
4323 if (_DtHelpCeGetCcdfTopicCmd (((void *) NULL), cur_vars->my_file,
4324 cur_vars->rd_buf, &(cur_vars->rd_ptr),
4325 cur_vars->rd_size, 1, &charSet) == -1)
4327 _DtHelpCeBufFileClose (cur_vars->my_file, True);
4332 * change the character set to the returned character set
4333 * Assume that the charset is 'iso8859' if not specified.
4335 cur_vars->cur_mb_max = 1;
4336 if (NULL != charSet)
4337 GetMbLen(cur_vars, charSet, &(_DtHelpFontHintsLang(fontAttrs)),
4338 &(_DtHelpFontHintsCharSet(fontAttrs)));
4341 * Remember the topic code set and MB_CUR_MAX.
4343 cur_vars->topic_char_set = _DtHelpFontHintsCharSet(fontAttrs);
4344 cur_vars->topic_lang = _DtHelpFontHintsLang(fontAttrs);
4345 cur_vars->topic_mb_max = cur_vars->cur_mb_max;
4348 * allocate another segment for this title.
4350 if (0 != CheckSegList(cur_vars))
4352 if (NULL != charSet)
4354 free(_DtHelpFontHintsLang(fontAttrs));
4355 free(_DtHelpFontHintsCharSet(fontAttrs));
4358 _DtHelpCeBufFileClose(cur_vars->my_file, True);
4363 * set the left margin correctly.
4365 titleSeg = NextAvailSeg(cur_vars->my_list);
4366 titleSeg->handle.container = DefContainer;
4367 titleSeg->type = _DtCvSetTypeToContainer(titleSeg->type);
4368 _DtCvContainerLMarginOfSeg(titleSeg) = level*2*cur_vars->ui_info->avg_char;
4369 _DtCvContainerBMarginOfSeg(titleSeg) = 0;
4370 _DtCvContainerTypeOfSeg(titleSeg) = _DtCvLITERAL;
4371 _DtCvContainerLeadingOfSeg(titleSeg) = cur_vars->ui_info->leading;
4376 if (-1 == ParseTitle(cur_vars, False, False, fnt_flags, &fontAttrs))
4378 if (NULL != charSet)
4380 free(_DtHelpFontHintsLang(fontAttrs));
4381 free(_DtHelpFontHintsCharSet(fontAttrs));
4384 _DtHelpCeBufFileClose(cur_vars->my_file, True);
4389 * We've parsed the title. see if we want the abbrev.
4392 * if the title is null or we want the abbrev,
4393 * process the abbreviation.
4395 if (NULL == _DtCvContainerListOfSeg(titleSeg) || want_abbrev)
4397 SegList titleList = cur_vars->my_list;
4400 * reset the buffer to get the abbreviation
4402 if (cur_vars->fmt_buf != NULL)
4404 free(cur_vars->fmt_buf);
4405 cur_vars->fmt_buf = NULL;
4406 cur_vars->fmt_size = 0;
4407 cur_vars->fmt_buf_max = 0;
4410 result = _DtHelpCeGetCcdfAbbrevCmd (cur_vars->my_file, cur_vars->rd_buf,
4411 cur_vars->rd_size, cur_vars->cur_mb_max,
4412 &(cur_vars->rd_ptr), &(cur_vars->fmt_buf));
4415 * If no errors getting the abbreviation, save it
4420 * save the abbreviation
4422 if (cur_vars->fmt_buf != NULL)
4425 * If there was a title, free it
4427 if (NULL != _DtCvContainerListOfSeg(titleSeg))
4428 _DtHelpFreeSegments(_DtCvContainerListOfSeg(titleSeg),
4430 cur_vars->ui_info->destroy_region,
4431 cur_vars->ui_info->client_data);
4434 * save the abbreviation
4436 cur_vars->my_list = InitList;
4437 cur_vars->fmt_size = strlen (cur_vars->fmt_buf);
4438 cur_vars->fmt_buf_max = cur_vars->fmt_size + 1;
4439 if (cur_vars->fmt_size > 0)
4440 result = SaveStringAsSegments (cur_vars, 0, &fontAttrs, -1);
4443 TerminateSegList(&(cur_vars->my_list), True);
4445 titleSeg->type = _DtCvSetTypeToContainer(titleSeg->type);
4446 _DtCvContainerListOfSeg(titleSeg) = cur_vars->my_list.list;
4452 * eliminate this segment if no title or abbrev was found.
4454 if (NULL == _DtCvContainerListOfSeg(titleSeg))
4456 titleList.cnt = origCnt;
4457 _DtCvContainerTypeOfSeg(titleSeg) = _DtCvDYNAMIC;
4461 * reset the title list
4463 cur_vars->my_list = titleList;
4466 result = _DtHelpCeSkipCcdfAbbrev (cur_vars->my_file, cur_vars->rd_buf,
4467 &(cur_vars->rd_ptr), cur_vars->rd_size,
4468 cur_vars->cur_mb_max);
4470 if (cur_vars->fmt_buf != NULL)
4471 cur_vars->fmt_buf[0] = '\0';
4472 cur_vars->fmt_size = 0;
4475 * remove the newline from the lists and
4476 * change all the newlines on the segments into a space.
4478 for (list = _DtCvContainerListOfSeg(titleSeg);
4479 NULL != list; list = list->next_seg)
4481 if (_DtCvIsSegNewLine(list))
4484 * clear the newline flag.
4486 list->type &= ~(_DtCvNEW_LINE);
4489 * check to see if the last character of this segment or
4490 * the first character of the next segment is a space.
4493 if (NULL != list->next_disp && _DtCvIsSegString(list)
4494 && _DtCvIsSegRegChar(list))
4497 * is the last character of the string a space?
4500 len = strlen((char *) _DtCvStringOfStringSeg(list)) - 1;
4501 if (' ' != ((char *) _DtCvStringOfStringSeg(list))[len])
4504 * is the next segment a one byte string?
4505 * and if so, is the first character a space?
4506 * if so, do nothing.
4508 if (_DtCvIsSegString(list->next_disp)
4509 && _DtCvIsSegRegChar(list->next_disp)
4510 && ' ' != *((char *)_DtCvStringOfStringSeg(list->next_disp)))
4513 * need to add a space to one of these strings.
4516 _DtCvStringOfStringSeg(list) = (char *) realloc(
4517 (void *) _DtCvStringOfStringSeg(list),
4518 sizeof(char *) * len);
4519 if (NULL == _DtCvStringOfStringSeg(list))
4522 strPtr = (char *) _DtCvStrPtr(
4523 _DtCvStringOfStringSeg(list),
4534 _DtHelpCeBufFileClose (cur_vars->my_file, True);
4539 if (NULL != charSet)
4541 free(_DtHelpFontHintsLang(fontAttrs));
4542 free(_DtHelpFontHintsCharSet(fontAttrs));
4552 /******************************************************************************
4553 * Function: int FormatEntryInToc (
4557 * Returns: 0 if successful, -1 if errors
4563 ******************************************************************************/
4566 _DtHelpVolumeHdl volume,
4568 FormatVariables *cur_vars,
4569 _DtHelpFontHints font_attrs,
4576 char *strPtr = NULL;
4578 _DtCvSegment *titleSeg;
4582 * check to see that there is a segment for this title.
4584 if (0 != CheckSegList(cur_vars))
4588 * The next segment in the list will become the next title.
4589 * Get a pointer to it for later use.
4591 titleList = cur_vars->my_list;
4592 titleSeg = NextAvailSeg(titleList);
4593 titleSeg->handle.container = DefContainer;
4594 titleSeg->type = _DtCvSetTypeToContainer(titleSeg->type);
4595 _DtCvContainerBMarginOfSeg(titleSeg) = 0;
4596 _DtCvContainerLeadingOfSeg(titleSeg) = cur_vars->ui_info->leading;
4599 * Get the file and offset for the topic.
4600 * and process the topic's title, ignoring most font changes.
4602 if (True == _DtHelpCeFindId(volume, loc_id, -1, &strPtr, &offset) &&
4603 -1 != FormatCCDFTitle(cur_vars, font_attrs, strPtr, offset, level,
4604 ((1<<_CEFONT_SIZE)|(1<<_CEFONT_WEIGHT)|(1<<_CEFONT_ANGLE)|(1<<_CEFONT_TYPE)),
4608 * now create the hypertext link index for the ghostlink.
4610 num = _DtLinkDbAddLink(cur_vars->my_links, NULL, loc_id,
4611 _DtCvLinkType_SameVolume,
4612 _DtCvWindowHint_CurrentWindow,
4615 * if a link index was successfully created, process the item.
4622 * check to see if this title had any segments.
4624 pSeg = _DtCvContainerListOfSeg(titleSeg);
4627 while (NULL != pSeg)
4630 * If this segment has a hypertext link, remove it.
4632 if (pSeg->link_idx != -1)
4633 _DtLinkDbRemoveLink(cur_vars->my_links, pSeg->link_idx);
4636 * change the link index and flag to the ghost link.
4638 pSeg->link_idx = num;
4639 pSeg->type &= ~(_DtCvHYPER_TEXT);
4640 pSeg->type = _DtCvSetTypeToGhostLink(pSeg->type);
4643 * go to the next segment.
4645 pSeg = pSeg->next_seg;
4651 * no title or abbreviation, so use the location id.
4652 * allocate room for it and put it between parens.
4654 tocLen = strlen (loc_id) + 9;
4655 if (tocLen > cur_vars->fmt_buf_max)
4657 if (NULL == cur_vars->fmt_buf)
4658 cur_vars->fmt_buf = (char *) malloc (tocLen);
4660 cur_vars->fmt_buf = (char *) realloc(
4663 cur_vars->fmt_buf_max = tocLen;
4666 cur_vars->fmt_size = tocLen - 1;
4667 strcpy (cur_vars->fmt_buf, "...(");
4668 strcat (cur_vars->fmt_buf, loc_id);
4669 strcat (cur_vars->fmt_buf, ")...");
4672 * don't overwrite the title's
4674 cur_vars->my_list = InitList;
4677 * save the string off and then attach to the title
4680 result = SaveStringAsSegments(cur_vars, _DtCvGHOST_LINK,
4683 _DtCvContainerListOfSeg(titleSeg) = cur_vars->my_list.list;
4686 * restore the title list.
4688 cur_vars->my_list = titleList;
4698 } /* End FormatEntryInToc */
4700 /******************************************************************************
4701 * Function: int FormatExpandToc (
4702 * _DtHelpVolumeHdl volume,
4705 ******************************************************************************/
4708 _DtHelpVolumeHdl volume,
4711 FormatVariables *cur_vars,
4712 _DtHelpFontHints font_attrs,
4717 if (*path_lst != NULL)
4719 font_attrs.weight = _DtHelpFontWeightMedium;
4720 if (_DtCvStrCaseCmpLatin1(*path_lst, cur_id) == 0)
4721 font_attrs.weight = _DtHelpFontWeightBold;
4723 result = FormatEntryInToc(volume, *path_lst, cur_vars,
4730 int count = _DtHelpCeGetCcdfTopicChildren(volume,
4731 *path_lst, &children);
4734 * if there are children, format them
4738 childLst = children;
4739 font_attrs.weight = _DtHelpFontWeightMedium;
4740 while (result != -1 && count > 0)
4743 * found the next item in the list
4745 if (*path_lst != NULL &&
4746 _DtCvStrCaseCmpLatin1(*path_lst, *childLst) == 0)
4747 result = FormatExpandedToc(volume,
4749 cur_vars, font_attrs, level);
4751 result = FormatEntryInToc(volume, *childLst,
4752 cur_vars, font_attrs, level);
4758 if (children != NULL)
4759 _DtCvFreeArray((void **) children);
4766 /******************************************************************************
4768 * Semi-Public Functions
4770 *****************************************************************************/
4771 /******************************************************************************
4772 * Function: VarHandle *__DtHelpCeSetUpVars (char *rd_buf, grow_size)
4776 * Returns: NULL if unsuccessful.
4782 ******************************************************************************/
4784 __DtHelpCeSetUpVars(
4787 _FrmtUiInfo *ui_info)
4789 FormatVariables *newVars;
4791 newVars = (FormatVariables *) malloc (sizeof(FormatVariables));
4793 newVars->ui_info = ui_info;
4795 newVars->topic_mb_max = _DtHelpCeGetMbLen(lang, code_set);
4796 newVars->cur_mb_max = newVars->topic_mb_max;
4798 return ((VarHandle) newVars);
4800 } /* End __DtHelpCeSetUpVars */
4802 /******************************************************************************
4803 * Function: int __DtHelpCeProcessString (char *in_string, int seg_type,
4808 * Returns: 0 if successful, -1 if errors.
4814 ******************************************************************************/
4816 __DtHelpCeProcessString(
4817 VarHandle var_handle,
4819 _DtCvFrmtOption frmt_type,
4825 _DtHelpFontHints *font_attr )
4828 FormatVariables *myVars = (FormatVariables *) var_handle;
4829 SegList oldList = myVars->my_list;
4831 myVars->rd_buf = in_string;
4832 myVars->rd_size = in_size;
4833 myVars->rd_ptr = in_string;
4834 myVars->my_file = my_file;
4836 if (my_file == NULL)
4837 myVars->rd_flag = 0;
4839 myVars->rd_flag = strlen(in_string);
4843 if (True == ret_on_nl)
4844 myVars->my_list = InitList;
4846 done = Parse (CCDF_FONT_CMD, NormalState, myVars,
4849 -1, scan_string, (CCDF_FONT_CMD | CCDF_OCTAL_CMD), ret_on_nl,
4852 if (done != -1 && True == ret_on_nl)
4854 TerminateSegList (&(myVars->my_list), True);
4855 if (NULL != myVars->my_list.list)
4857 done = CheckList (&oldList, 1, GROW_SIZE);
4860 _DtCvSegment *newSeg = NextAvailSeg(oldList);
4862 newSeg->type = _DtCvSetTypeToContainer(newSeg->type);
4863 _DtCvContainerListOfSeg(newSeg) = myVars->my_list.list;
4864 _DtCvContainerTypeOfSeg(newSeg) = _DtCvDYNAMIC;
4868 TerminateSegList(&oldList, False);
4874 if (False == ret_on_nl)
4875 oldList = myVars->my_list;
4877 myVars->my_list = oldList;
4880 } /* End __DtHelpCeProcessString */
4882 /*****************************************************************************
4883 * Function: int __DtHelpCeGetParagraphList (
4887 * Returns: 0 if successful, -1 if errors.
4891 * Purpose: _DtHelpFormatGetParagraphList places a terminator on the
4892 * last segment in the current paragraph and returns the
4893 * segment list included in the topic information structure.
4895 * If make_cont is true, the segment list is first included
4896 * in a container with the specified type.
4898 *****************************************************************************/
4900 __DtHelpCeGetParagraphList (
4901 VarHandle var_handle,
4903 _DtCvFrmtOption type,
4904 _DtCvTopicPtr *ret_handle)
4907 FormatVariables *myVars = (FormatVariables *) var_handle;
4908 _DtCvTopicInfo *topicHandle;
4911 * check the parameters.
4913 if (ret_handle == NULL || myVars == NULL)
4919 TerminateSegList(&(myVars->my_list), True);
4921 topicHandle = (_DtCvTopicInfo *) malloc (sizeof(_DtCvTopicInfo));
4922 if (topicHandle != NULL)
4926 if (True == make_cont)
4928 _DtCvSegment *myCont = AllocateSegments(NULL, 0, 1);
4932 myCont->type = _DtCvSetTypeToContainer(myCont->type);
4933 _DtCvContainerTypeOfSeg(myCont) = type;
4934 _DtCvContainerListOfSeg(myCont) = myVars->my_list.list;
4936 myVars->my_list.list = myCont;
4937 myVars->my_list.cnt = 1;
4938 myVars->my_list.max = 1;
4944 topicHandle->id_str = NULL;
4945 topicHandle->seg_list = myVars->my_list.list;
4946 topicHandle->mark_list = NULL;
4947 topicHandle->link_data = myVars->my_links;
4949 *ret_handle = (_DtCvTopicPtr) topicHandle;
4952 if (myVars->fmt_buf != NULL)
4953 free(myVars->fmt_buf);
4958 /******************************************************************************
4959 * Function: int _DtHelpCeFrmtCcdfTopic (_DtHelpVolumeHdl volume, char *filename,
4960 * int offset, char *id_string,
4961 * _DtCvTopicPtr *ret_handle)
4964 * volume Specifies the Help Volume the information
4965 * is associated with.
4966 * filename Specifies the file containing the Help Topic
4968 * offset Specifies the offset into 'filename' to
4969 * the Help Topic desired.
4970 * id_string Specifies the location id to look for or NULL.
4971 * ret_handle Returns a handle to the topic information
4972 * including the number of paragraphs and the
4975 * Returns: 0 if successful, -1 if errors
4979 * Purpose: _DtHelpCeFrmtCcdfTopic formats Help Files with formatting
4980 * information into a Canvas Engine structure.
4982 ******************************************************************************/
4984 _DtHelpCeFrmtCcdfTopic(
4985 _DtHelpVolumeHdl volume,
4989 _FrmtUiInfo *ui_info,
4990 _DtCvTopicPtr *ret_handle )
4994 FormatVariables variables;
4997 * Check the parameters
4999 if (volume == NULL || filename == NULL || offset < 0 || ret_handle == NULL)
5006 * get the current file path.
5008 variables = DefVars;
5009 variables.topic_id = id_string;
5012 variables.vol_name = _DtHelpCeGetVolumeName(volume);
5013 variables.my_path = strdup (variables.vol_name);
5014 if (variables.my_path == NULL)
5017 result = _DtHelpCeStrrchr (variables.my_path, Slash, MB_CUR_MAX, &ptr);
5019 ptr = strrchr (variables.my_path, '/');
5026 * open the file and seek to the correct place.
5028 result = _DtHelpCeFileOpenAndSeek (filename, offset, -1,
5029 &(variables.my_file), NULL);
5033 * Initialize the X variables.
5035 result = Format (&variables, ui_info, id_string, ret_handle);
5037 _DtHelpCeBufFileClose (variables.my_file, True);
5040 if (variables.fmt_buf != NULL)
5041 free (variables.fmt_buf);
5043 if (variables.my_path != NULL)
5044 free (variables.my_path);
5048 } /* End _DtHelpCeFrmtCcdfTopic */
5050 /******************************************************************************
5051 * Function: int _DtHelpCeFrmtCcdfPathAndChildren (
5052 * _DtHelpVolumeHdl volume,
5053 * _DtCvTopicPtr *ret_handle)
5056 * ret_handle Returns a handle to the topic information
5057 * including the number of paragraphs and the
5060 * Returns: 0 if successful, -1 if errors, 1 if there the path is empty.
5064 * Purpose: _DtHelpCeFormatCcdfToc formats Table of Contents for
5067 ******************************************************************************/
5069 _DtHelpCeFrmtCcdfPathAndChildren(
5070 _DtHelpVolumeHdl volume,
5072 _FrmtUiInfo *ui_info,
5073 _DtCvTopicPtr *ret_handle )
5079 char readBuf[BUFF_SIZE];
5080 FormatVariables myVars;
5081 _DtHelpFontHints fontAttrs;
5083 _DtHelpCeCopyDefFontAttrList (&fontAttrs);
5084 fontAttrs.pointsz = 10;
5085 fontAttrs.weight = _DtHelpFontWeightMedium;
5086 fontAttrs.style = _DtHelpFontStyleSanSerif;
5089 * Check the parameters
5091 if (volume == NULL || ret_handle == NULL)
5099 if (InitStructure (&myVars, ui_info, readBuf, BUFF_SIZE) == -1)
5103 * get the list of topics in the volume.
5105 pathCnt = _DtHelpCeGetCcdfIdPath(volume, loc_id, &pathHead);
5110 * Check to see if this topic is in the topic list.
5111 * I.e. if a count of 1 is returned this should match the
5112 * top topic, otherwise this is an hidden topic.
5116 if (_DtHelpCeGetCcdfTopTopic(volume, &ptr) == -1)
5118 else if (_DtCvStrCaseCmpLatin1(ptr, *pathHead) != 0)
5123 * if result is non-zero, we had problems or this is a hidden topic
5127 fontAttrs.slant = _DtHelpFontSlantRoman;
5129 myVars.topic_id = loc_id;
5130 myVars.vol_name = _DtHelpCeGetVolumeName(volume);
5131 myVars.my_path = strdup (myVars.vol_name);
5132 if (myVars.my_path == NULL)
5135 if (-1 == _DtHelpCeStrrchr (myVars.my_path, Slash, MB_CUR_MAX, &ptr))
5136 ptr = strrchr (myVars.my_path, '/');
5141 result = FormatExpandedToc(volume, loc_id, pathHead,
5142 &myVars, fontAttrs, 0);
5143 _DtCvFreeArray((void **) pathHead);
5147 result = __DtHelpCeGetParagraphList (&myVars, False, _DtCvDYNAMIC,
5151 * check for an empty path.
5153 if (-1 != result && NULL == ((_DtCvTopicInfo *) *ret_handle)->seg_list)
5156 if (myVars.my_path != NULL)
5157 free(myVars.my_path);
5161 } /* End _DtHelpCeFrmtCcdfPathAndChildren */
5163 /******************************************************************************
5164 * Function: int _DtHelpCeGetCcdfTitleChunks (
5165 * _DtHelpVolumeHdl volume,
5166 * _DtCvTopicPtr *ret_handle)
5169 * ret_handle Returns a handle to the topic information
5170 * including the number of paragraphs and the
5173 * Returns: 0 if successful, -1 if errors
5177 * Purpose: _DtHelpCeFormatCcdfToc formats Table of Contents for
5180 ******************************************************************************/
5182 _DtHelpCeGetCcdfTitleChunks(
5183 _DtHelpVolumeHdl volume,
5185 _FrmtUiInfo *ui_info,
5193 char readBuf[BUFF_SIZE];
5194 _DtCvSegment *titleSeg;
5195 _DtCvSegment *list = NULL;
5196 FormatVariables myVars;
5197 _DtHelpFontHints fontAttrs;
5198 _DtHelpCeLockInfo lockInfo;
5201 * Check the parameters
5203 if (volume == NULL || ret_chunks == NULL)
5210 * init the return value
5215 * get the topic in the volume.
5217 if (_DtHelpCeLockVolume(volume, &lockInfo) != 0)
5220 if (_DtHelpCeFindId(volume, loc_id, -1, &fileName, &offset) == False)
5222 _DtHelpCeUnlockVolume(lockInfo);
5226 _DtHelpCeCopyDefFontAttrList (&fontAttrs);
5228 if (InitStructure (&myVars, ui_info, readBuf, BUFF_SIZE) == -1)
5230 _DtHelpCeUnlockVolume(lockInfo);
5235 * initialize my variables.
5237 myVars.topic_id = loc_id;
5238 myVars.vol_name = _DtHelpCeGetVolumeName(volume);
5239 myVars.my_path = strdup (myVars.vol_name);
5240 if (myVars.my_path == NULL)
5242 _DtHelpCeUnlockVolume(lockInfo);
5246 if (-1 == _DtHelpCeStrrchr (myVars.my_path, Slash, MB_CUR_MAX, &ptr))
5247 ptr = strrchr (myVars.my_path, '/');
5252 result = FormatCCDFTitle(&myVars, fontAttrs, fileName,
5253 offset, 0, (1 << _CEFONT_SIZE), True);
5256 if (-1 != result && 0 < myVars.my_list.cnt)
5258 titleSeg = &(myVars.my_list.list[myVars.my_list.cnt - 1]);
5259 list = _DtCvContainerListOfSeg(titleSeg);
5262 if (result != -1 && NULL != list)
5264 _DtCvSegment *pSeg = list;
5266 while (-1 != result && NULL != pSeg)
5269 * create the types and add the informatio to the array.
5271 type = DT_HELP_CE_FONT_PTR | DT_HELP_CE_STRING;
5272 if (_DtCvIsSegNewLine(pSeg))
5273 type |= DT_HELP_CE_NEWLINE;
5275 if (_DtCvIsSegString(pSeg))
5277 *ret_chunks = (void **) _DtCvAddPtrToArray(*ret_chunks,
5279 if (NULL != *ret_chunks)
5280 *ret_chunks = (void **) _DtCvAddPtrToArray(*ret_chunks,
5281 (void *) _DtCvFontOfStringSeg(pSeg));
5283 if (NULL != *ret_chunks)
5285 if (_DtCvIsSegWideChar(pSeg))
5287 offset = _DtCvStrLen(_DtCvStringOfStringSeg(pSeg), 1)
5289 ptr = (char *) malloc (sizeof(char) * offset);
5292 (wchar_t *)_DtCvStringOfStringSeg(pSeg),
5296 ptr = strdup((char *) _DtCvStringOfStringSeg(pSeg));
5299 *ret_chunks = (void **)_DtCvAddPtrToArray(
5300 *ret_chunks, (void *) ptr);
5303 if (NULL == *ret_chunks || NULL == ptr)
5308 * go to the next segment
5310 pSeg = pSeg->next_seg;
5317 int idLen = strlen (loc_id) + 9;
5320 * create the location id string.
5322 idStr = (char *) malloc (idLen);
5326 * format the location id
5328 strcpy (idStr, "...(");
5329 strcat (idStr, loc_id);
5330 strcat (idStr, ")...");
5333 * format the language and codeset
5335 strcpy(buf, _DtHelpFontHintsLang(fontAttrs));
5337 strcpy(buf, _DtHelpFontHintsCharSet(fontAttrs));
5340 * creat a chunk table
5342 *ret_chunks = (void **) _DtCvAddPtrToArray(*ret_chunks,
5343 (void *) (DT_HELP_CE_CHARSET | DT_HELP_CE_STRING));
5344 if (NULL != *ret_chunks)
5345 *ret_chunks = (void **) _DtCvAddPtrToArray(*ret_chunks,
5346 (void *) strdup(buf));
5347 if (NULL != *ret_chunks)
5348 *ret_chunks = (void **) _DtCvAddPtrToArray(*ret_chunks,
5353 if (NULL != *ret_chunks)
5354 *ret_chunks = (void **) _DtCvAddPtrToArray(*ret_chunks,
5355 (void *) DT_HELP_CE_END);
5360 if (0 < myVars.my_list.cnt)
5361 _DtHelpFreeSegments(myVars.my_list.list, _DtCvFALSE,
5362 ui_info->destroy_region,
5363 ui_info->client_data);
5366 * free the link database
5368 _DtLinkDbDestroy(myVars.my_links);
5373 if (myVars.my_path != NULL)
5374 free(myVars.my_path);
5375 if (myVars.fmt_buf != NULL)
5376 free(myVars.fmt_buf);
5378 _DtHelpCeUnlockVolume(lockInfo);
5381 * indicate an error if problems.
5384 if (NULL == *ret_chunks)
5389 } /* End _DtHelpCeGetCcdfTitleChunks */
5391 /******************************************************************************
5392 * Function: int _DtHelpCeGetCcdfVolTitleChunks (
5393 * _DtHelpVolumeHdl volume,
5394 * void ***ret_chunks)
5397 * ret_chunks Returns a ptr to the title information chunks
5398 * The title chunks are stored in allocated memory
5399 * that is owned by the caller and should be
5400 * freed when no longer needed.
5403 * Returns: 0 if successful, -1 if errors
5407 * Purpose: _DtHelpCeFormatCcdfVolTitleChunks formats volume title for
5410 ******************************************************************************/
5412 _DtHelpCeGetCcdfVolTitleChunks(
5413 _DtHelpVolumeHdl volume,
5414 _FrmtUiInfo *ui_info,
5421 * get the title of the volume (we own the memory).
5423 charSet = _DtHelpCeGetCcdfVolLocale(volume);
5424 if (charSet == NULL)
5425 charSet = strdup("C.ISO-8859-1");
5427 titleStr = _DtHelpCeGetCcdfVolTitle(volume);
5428 if (titleStr != NULL)
5430 *ret_chunks = (void **) malloc(sizeof(void *) * 4);
5431 if (*ret_chunks == NULL)
5434 (*ret_chunks)[0] = (void *) (DT_HELP_CE_CHARSET | DT_HELP_CE_STRING);
5435 (*ret_chunks)[1] = (void *) strdup(charSet);
5436 (*ret_chunks)[2] = (void *) strdup(titleStr);
5437 (*ret_chunks)[3] = (void *) DT_HELP_CE_END;
5442 if (_DtHelpCeGetCcdfTitleChunks(volume, "_title",
5443 ui_info, ret_chunks) != 0
5445 _DtHelpCeGetCcdfTitleChunks(volume, "_hometopic",
5446 ui_info, ret_chunks) != 0)
5452 } /* End _DtHelpCeGetCcdfVolTitleChunks */