/* * CDE - Common Desktop Environment * * Copyright (c) 1993-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these libraries and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ /* $TOG: FormatCCDF.c /main/23 1999/10/14 15:06:28 mgreess $ */ /************************************<+>************************************* **************************************************************************** ** ** File: FormatCCDF.c ** ** Project: Unix Desktop Help ** ** Description: This code formats an file in CCDF (Cache Creek ** Distribution Format) into internal format. ** ** (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company ** ** (c) Copyright 1993, 1994 Hewlett-Packard Company ** (c) Copyright 1993, 1994 International Business Machines Corp. ** (c) Copyright 1993, 1994 Sun Microsystems, Inc. ** (c) Copyright 1993, 1994 Novell, Inc. ** ** ** **************************************************************************** ************************************<+>*************************************/ /* * system includes */ #include #include #include #if defined(sun) #include #endif #include #include #include #include #include #include #include #ifdef X_NOT_STDC_ENV extern int errno; #endif /* * Canvas Engine includes */ #include "CanvasP.h" #include "CanvasSegP.h" #include "LinkMgrP.h" /* * private includes */ #include "bufioI.h" #include "Access.h" #include "AccessI.h" #include "AccessP.h" #include "AccessCCDFI.h" #include "CanvasError.h" #include "CleanUpI.h" #include "CvStringI.h" #include "CvtToArrayP.h" #include "FontAttrI.h" #include "FormatUtilI.h" #include "FormatCCDFI.h" #include "CCDFUtilI.h" #include "HelpXlate.h" #include "StringFuncsI.h" extern char *_DtHelpGetLocale(void); #ifdef NLS16 #endif /****************************************************************************** * Private variables and defines. *****************************************************************************/ #define BUFF_SIZE 1024 #define GROW_SIZE 10 #define INFO_GROW 256 #define CCDF_LINK_JUMP_REUSE 0 #define CCDF_LINK_JUMP_NEW 1 #define CCDF_LINK_DEFINITION 2 #define CCDF_LINK_EXECUTE 3 #define CCDF_LINK_MAN_PAGE 4 #define CCDF_LINK_APP_DEFINE 5 #define IsTypeHyperText(x) (((x) & _DtCvHYPER_TEXT) ? 1 : 0) #define IsTypeNewLine(x) (((x) & _DtCvNEW_LINE) ? 1 : 0) #define NextAvailSeg(x) (NULL != x.list ? &(x.list[x.cnt]) : NULL) /****************************************************************************** * Private structures ******************************************************************************/ typedef struct _segList { int cnt; int max; _DtCvSegment *list; } SegList; typedef struct _formatVariables { int last_was_space; int last_was_mb; int last_was_nl; char *rd_buf; char *rd_ptr; char *fmt_buf; char *my_path; char *vol_name; char *topic_id; char *topic_char_set; char *topic_lang; int rd_size; int rd_flag; int topic_mb_max; int cur_mb_max; int fmt_buf_max; int fmt_size; int cell_cnt; BufFilePtr my_file; SegList my_list; _DtCvLinkDb my_links; _FrmtUiInfo *ui_info; } FormatVariables; enum _processState { NormalState, LabelBody }; typedef enum _processState ProcessState; /****************************************************************************** * Private Function Declarations ******************************************************************************/ static _DtCvSegment *AllocateSegments( _DtCvSegment *p_seg, int original_size, int new_size ); static int AppendCharToInfo( FormatVariables *cur_vars, char **src ); static int AppendOctalToInfo( FormatVariables *cur_vars, char *src ); static int AppendSpaceToInfo ( FormatVariables *cur_vars, char **src, _DtCvFrmtOption type ); static int AppendToInfo ( FormatVariables *cur_vars, char **src, const char *scan_string ); static int ChangeFont( int whichOne, unsigned long seg_flags, _DtCvFrmtOption frmt_type, _DtHelpFontHints *font_attr, int linkspec, FormatVariables *cur_vars, ProcessState cur_state, int flags, int ret_on_nl, int fnt_flag); static int CheckIdString( FormatVariables *cur_vars, ProcessState cur_state, unsigned long seg_flags, _DtCvFrmtOption frmt_type, _DtHelpFontHints *font_attr, int linkspec, int flags, int ret_on_nl, int fnt_flag); static int CheckSaveSegment ( unsigned long seg_flags, _DtHelpFontHints *font_attr, int link_spec, FormatVariables *cur_vars ); static int CreateSaveGraphic ( FormatVariables *cur_vars, int type, char *file_name, int link_spec ); static int CheckSegList ( FormatVariables *cur_vars); static int Format( FormatVariables *cur_vars, _FrmtUiInfo *ui_info, char *id_string, _DtCvTopicPtr *ret_handle); static int GetNextBuffer ( FormatVariables *cur_vars); static int GetStringParameter( FormatVariables *cur_vars, _DtCvValue flag, _DtCvValue eat_escape, _DtCvValue ignore_quotes, _DtCvValue less_test, char **ret_string ); static int GetValueParameter( FormatVariables *cur_vars, _DtCvValue flag, int *ret_value ); static int InitStructure( FormatVariables *cur_vars, _FrmtUiInfo *ui_info, char *rd_buf, int rd_size); static int Parse( int cur_cmd, ProcessState cur_state, FormatVariables *cur_vars, unsigned long seg_flags, _DtCvFrmtOption frmt_type, _DtHelpFontHints *font_attr, int linkspec, const char *scan_string, int allowed, int ret_on_nl, int fnt_flag); static int ProcessFigureCmd( FormatVariables *cur_vars, ProcessState cur_state, _DtCvFrmtOption frmt_type, _DtHelpFontHints *font_attr, int ret_on_nl, int fnt_flag); static int ProcessHypertext( FormatVariables *cur_vars, ProcessState cur_state, unsigned long seg_flags, _DtCvFrmtOption frmt_type, _DtHelpFontHints *font_attr, int flags, int ret_on_nl, int fnt_flag); static int ProcessInLine( FormatVariables *cur_vars, int seg_type, int link_spec ); static int ProcessLabelCmd( FormatVariables *cur_vars, unsigned long seg_flags, _DtCvFrmtOption frmt_type, _DtHelpFontHints *font_attr, int link_spec, int flags, int ret_on_nl, int fnt_flag, _DtCvSegment **ret_list); static int ProcessParagraph ( FormatVariables *cur_vars, ProcessState cur_state, int fnt_flag); static int SaveNewLine( FormatVariables *cur_vars, int cur_cmd, _DtHelpFontHints *font_attr, int link_spec ); static int SaveStringAsSegments ( FormatVariables *cur_vars, unsigned long seg_flags, _DtHelpFontHints *font_attr, int link_spec); static int SkipToNextToken ( FormatVariables *cur_vars, _DtCvValue flag ); static void TerminateSegList ( SegList *list, int flag); static int SegmentSave( FormatVariables *cur_vars, unsigned long seg_type, _DtHelpFontHints *font_attr, char *string, int str_size, int num_chars, int link_spec); /******** End Public Function Declarations ********/ /****************************************************************************** * Private variables *****************************************************************************/ static const char *Specials = "<\n\\ "; static const char *SpaceString = " "; static const char *Period = "."; static const char *Slash = "/"; static const FormatVariables DefVars = { True, /* int last_was_space; */ False, /* int last_was_mb; */ False, /* int last_was_nl; */ NULL, /* char *rd_buf; */ NULL, /* char *rd_ptr; */ NULL, /* char *fmt_buf; */ NULL, /* char *my_path; */ NULL, /* char *vol_name; */ NULL, /* char *topic_id; */ NULL, /* char *topic_char_set; */ NULL, /* char *topic_lang; */ 0, /* int rd_size; */ 0, /* int rd_flag; */ 1, /* int topic_mb_max; */ 1, /* int cur_mb_max; */ 0, /* int fmt_buf_max; */ 0, /* int fmt_size; */ 0, /* int cell_cnt; */ NULL, /* BufFilePtr my_file; */ { /* SegList my_list; */ 0, /* int cnt; */ 0, /* int max; */ NULL, /* _DtCvSegment *list; */ }, /* SegList my_list; */ NULL, /* _DtCvLinkDb my_links; */ NULL, /* _FrmtUiInfo ui_info; */ }; static const SegList InitList = { 0, /* int cnt; */ 0, /* int max; */ NULL, /* _DtCvSegment *list; */ }; static const _DtCvContainer DefContainer = { NULL, /* char *id; */ NULL, /* char *justify_char; */ _DtCvDYNAMIC, /* _DtCvFrmtOption type; */ _DtCvBORDER_NONE, /* _DtCvFrmtOption border; */ _DtCvJUSTIFY_LEFT, /* _DtCvFrmtOption justify; */ _DtCvJUSTIFY_TOP, /* _DtCvFrmtOption vjustify; */ _DtCvJUSTIFY_LEFT_MARGIN,/* _DtCvFrmtOption orient; */ _DtCvJUSTIFY_TOP, /* _DtCvFrmtOption vorient; */ _DtCvWRAP_NONE, /* _DtCvFrmtOption flow; */ 10000, /* int percent; */ 0, /* _DtCvUnit leading; */ 0, /* _DtCvUnit fmargin; */ 0, /* _DtCvUnit lmargin; */ 0, /* _DtCvUnit rmargin; */ 0, /* _DtCvUnit tmargin; */ 1, /* _DtCvUnit bmargin; */ {0, NULL}, /* _DtCvLine bdr_info; */ NULL, /* _DtCvSegment seg_list; */ }; static const FrmtPrivateInfo DefPrivInfo = { (char) False, /* char top_block; */ (char) False, /* char dup_flag; */ 0, /* int sdl_type; */ 0, /* void *match_info; */ NULL, /* void *id_info; */ NULL, /* void *tmp_info; */ }; /****************************************************************************** * * Private Functions * *****************************************************************************/ /****************************************************************************** * Function: int CreateMarker ( * * Parameters: * cur_vars Specifies the current setting of * formatting variables. * id_string The id string for the marker. * * Returns: 0 if successful, -1 if failure. * * Purpose: To create a marker id. * *****************************************************************************/ static int CreateMarker ( FormatVariables *cur_vars, char *id_string) { int result; /* * make sure there is room for the marker segment */ result = CheckSegList(cur_vars); if (-1 != result) { int cnt = cur_vars->my_list.cnt; _DtCvSegment *list = cur_vars->my_list.list; /* * now make a mark segment here. */ list[cnt].type = _DtCvSetTypeToMarker(list[cnt].type); _DtCvIdOfMarkerSeg(&list[cnt]) = id_string; cur_vars->my_list.cnt++; } return result; } /****************************************************************************** * Function: void GetMbLen ( * * Parameters: * cur_vars Specifies the current setting of * formatting variables. * font_str Specifies the CCDF string for a * CHARACTERSET change. The string is * modified by this routine. * lang_ptr Returns the language and territory * value. The caller owns this memory. * set_ptr Returns the code set of the language. * The caller owns this memory. * * Returns: Nothing * * Purpose: 1) To decompose the font_string into a language and code set * portions. * 2) To set the mb_cur_len variable in cur_vars. * *****************************************************************************/ static void GetMbLen ( FormatVariables *cur_vars, char *font_str, char **lang_ptr, char **set_ptr) { int i; char *ptr; char *langPart = NULL; char *codePart = NULL; char *mLang = NULL; /* * strip spaces */ while (*font_str == ' ') font_str++; for (i = strlen(font_str) - 1; i > -1 && font_str[i] == ' '; i--) font_str[i] = '\0'; /* * check for locale.codeset */ if (_DtHelpCeStrchr(font_str, ".", 1, &ptr) == 0) { /* * make font_str two separate strings by replacing * the dot with a end of line. */ *ptr++ = '\0'; langPart = strdup(font_str); codePart = strdup(ptr); goto done; } /* * old CCDF volume */ if (font_str == NULL || *font_str == '\0') codePart = strdup("UTF-8"); else codePart = strdup(font_str); mLang = _DtHelpGetLocale(); if (_DtHelpCeStrrchr(mLang, Period, MB_CUR_MAX, &ptr) == 0) { *ptr = '\0'; if (mLang != NULL && *mLang != '\0') { langPart = strdup(mLang); goto done; } } langPart = strdup("C"); done: cur_vars->cur_mb_max = MB_CUR_MAX; /* * now set the return variables */ if (lang_ptr != NULL) *lang_ptr = langPart; else free(langPart); if (set_ptr != NULL) *set_ptr = codePart; else free(codePart); free(mLang); } /****************************************************************************** * Function: int ReturnLinkWinHint (int ccdf_type) * * Parameters: * * Returns: * * errno Values: * * Purpose: *****************************************************************************/ static int ReturnLinkWinHint ( int ccdf_type) { int winHint = _DtCvWindowHint_CurrentWindow; if (ccdf_type == CCDF_LINK_JUMP_NEW) winHint = _DtCvWindowHint_NewWindow; else if (ccdf_type == CCDF_LINK_DEFINITION) winHint = _DtCvWindowHint_PopupWindow; return winHint; } /****************************************************************************** * Function: int ReturnLinkType (int ccdf_type, char *spec) * * Parameters: * * Returns: * * errno Values: * * Purpose: *****************************************************************************/ static int ReturnLinkType ( int ccdf_type, char *spec) { int trueType = _DtCvLinkType_SameVolume; switch(ccdf_type) { case CCDF_LINK_JUMP_NEW: case CCDF_LINK_JUMP_REUSE: case CCDF_LINK_DEFINITION: if (strchr(spec, ' ') != NULL) trueType = _DtCvLinkType_CrossLink; break; case CCDF_LINK_EXECUTE: trueType = _DtCvLinkType_Execute; break; case CCDF_LINK_MAN_PAGE: trueType = _DtCvLinkType_ManPage; break; case CCDF_LINK_APP_DEFINE: trueType = _DtCvLinkType_AppDefine; break; } return trueType; } /****************************************************************************** * Function: int CheckSegList (FormatVariables *cur_vars) * * Parameters: * * Returns: 0 for success, -1 for errors. * * errno Values: * CEErrorReported * * Purpose: Check the global variable 'SegCount' against 'SegMax' and * realloc/malloc more memory for the global variable 'SegList' * if necessary. If memory is realloc'ed/malloc'ed, the entry * 'para_entry->seg_list' is set to 'SegList'. * *****************************************************************************/ static int CheckSegList ( FormatVariables *cur_vars ) { if (cur_vars->my_list.cnt >= cur_vars->my_list.max) { cur_vars->my_list.list = AllocateSegments (cur_vars->my_list.list, cur_vars->my_list.max, (cur_vars->my_list.max + GROW_SIZE)); if (NULL == cur_vars->my_list.list) return -1; cur_vars->my_list.max += GROW_SIZE; } return 0; } /****************************************************************************** * Function: static _DtCvSegment *AllocateSegments (_DtCvSegment p_seg, * int original_size, int new_size) * * Parameters: * p_seg Specifies a pointer to the old list * of _DtCvSegments. * original_size Specifies the current size of 'p_seg'. * new_size Specifies the new size of 'p_seg'. * * Returns: A pointer to the new list of structures. * A NULL indicates an error. * * Purpose: (Re)Allocates _DtCvSegment structures and initializes * them to the default segment which is type _DtCvNOOP * and the container values set to default values. * *****************************************************************************/ static _DtCvSegment * AllocateSegments ( _DtCvSegment *p_seg, int original_size, int new_size ) { FrmtPrivateInfo *priv = NULL; if (NULL != p_seg) { int count = 0; /* * reallocate the segments. */ p_seg = (_DtCvSegment *) realloc ((void *) p_seg, (sizeof(_DtCvSegment) * new_size)); /* * reallocate the private formatting information. */ priv = p_seg->client_use; priv = (FrmtPrivateInfo *) realloc ((void *) priv, sizeof(FrmtPrivateInfo) * new_size); if (NULL == priv) { free(p_seg); p_seg = NULL; return NULL; } /* * reattach the private information with their segments. */ while (count < original_size) p_seg[count++].client_use = priv++; } else p_seg = _DtHelpAllocateSegments (new_size); if (NULL != p_seg) { /* * want to 'empty' the type. */ while (original_size < new_size) { /* * if we went through _DtHelpAllocateSegments, then the * priv pointer will be NULL. But that's okay since the * _DtHelpAllocateSegments routine will initalized the * variables for us. The only reason we have to do it * is if we've reallocated the list. */ if (NULL != priv) { *priv = DefPrivInfo; p_seg[original_size ].client_use = priv++; p_seg[original_size ].type = _DtCvNOOP; p_seg[original_size ].link_idx = -1; p_seg[original_size ].next_seg = NULL; p_seg[original_size ].next_disp = NULL; } p_seg[original_size++].handle.container = DefContainer; } } return p_seg; } /****************************************************************************** * Function: static int CheckList ( * FormatVariables cur_vars, int count, int grow) * * Parameters: * cur_vars Specifies a structure containing the list * of _DtCvSegments. * count Specifies the amount needed. * grow Specifies the amount to grow by. * * Returns: 0 if successful, -1 if failure. * * Purpose: Makes sure there is 'grow' size number of segments * available. If not, it calls AllocateSegments to 'grow' * the segment list. cur_vars->seg_list is set to the new * pointer, cur_vars->seg_max indicates the maximum number * of segments in the list. * *****************************************************************************/ static int CheckList ( SegList *seg_list, int count, int grow ) { /* * what's the new count? */ count += seg_list->cnt; /* * is it larger than the current max? */ if (count > seg_list->max) { /* * grow the list by the indicated amount. */ grow += seg_list->max; /* * check to see if it is enough. If not, force the grow value * to be the required count. */ if (count > grow) grow = count; /* * (re)allocate */ seg_list->list = AllocateSegments(seg_list->list, seg_list->max, grow); /* * return an code if no list allocated. */ if (NULL == seg_list->list) return -1; /* * set the max count */ seg_list->max = grow; } return 0; } /****************************************************************************** * Function: int SegmentSave (int type, * char **font_attr, char *string, int linkspec, * _DtCvSegment *p_seg) * * Parameters: * type Specifies the segment type. * font_attr Specifies the resource list of quarks for the * font to associate with the segment. * string Specifies the string segment. * link_spec Specifies the link specification for the * segment. * p_seg Specifies the _DtCvSegment structure to * initialize with the data. * * Returns: 0 if successful, -1 if errors. * * errno Values: * CEErrorReported * * Purpose: Creates a new segment with the given data. * *****************************************************************************/ static int SegmentSave ( FormatVariables *cur_vars, unsigned long seg_type, _DtHelpFontHints *font_attr, char *string, int str_size, int num_chars, int linkspec) { int result = 0; _DtCvSegment *pSeg = NextAvailSeg(cur_vars->my_list); pSeg->type = _DtCvSetTypeToNoop(seg_type); pSeg->link_idx = linkspec; /* * We use this routine for many things. * If we want an newline in here, we may not have any data. */ if (str_size) { pSeg->type = _DtCvSetTypeToString(pSeg->type); /* * if a wide character representation is required, * convert to wchar_t */ if (seg_type & _DtCvWIDE_CHAR) { wchar_t *pwcs; /* * include the null byte in the multibyte to widechar * conversion. */ num_chars++; /* * malloc the memory */ pwcs = (wchar_t *) malloc(sizeof(wchar_t) * num_chars); if (NULL != pwcs) { /* convert */ str_size = mbstowcs(pwcs, string, ((size_t) num_chars)); /* check to see if it converted everything */ if (str_size + 1 == num_chars) _DtCvStringOfStringSeg(pSeg) = (void *) pwcs; else free(pwcs); } } else _DtCvStringOfStringSeg(pSeg) = (void *) strdup(string); if (NULL == _DtCvStringOfStringSeg(pSeg)) return -1; /* * set the default font. This should really be passed in via * the format entry point (or the ui_info structure). */ _DtCvFontOfStringSeg(pSeg) = 0; /* * load the font */ if (NULL != cur_vars->ui_info->load_font) (*(cur_vars->ui_info->load_font))( cur_vars->ui_info->client_data, _DtHelpFontHintsLang(*font_attr), _DtHelpFontHintsCharSet(*font_attr), *font_attr, &(_DtCvFontOfStringSeg(pSeg))); } return result; } /****************************************************************************** * Function: int SaveStringAsSegments (FormatVariables, int type, char **font_attr, * int link_spec) * * Parameters: * type Specifies the segment type. * font_attr Specifies the resource list of quarks for the * font to associate with the segment. * link_spec Specifies the link specification for the * segment. * * Returns: 0 if successful, -1 if errors. * * errno Values: * * Purpose: Saves a segment into the global 'SegList'. This is * a wrapper around SegmentSave that adds specific * information relative to this module. * *****************************************************************************/ static int SaveStringAsSegments ( FormatVariables *cur_vars, unsigned long seg_flags, _DtHelpFontHints *font_attr, int link_spec) { int len; int size; int numChars; int newLine = False; char tmpChar; char *ptr; seg_flags = _DtCvSetTypeToNoop(seg_flags); if (cur_vars->cur_mb_max != 1 && cur_vars->fmt_size > 1) { if (IsTypeNewLine(seg_flags)) { newLine = True; seg_flags = seg_flags & ~(_DtCvNEW_LINE); } ptr = cur_vars->fmt_buf; do { /* * what type of character is this? */ len = mblen (ptr, cur_vars->cur_mb_max); /* * How many of the following characters are of the same size? */ size = _DtHelpFmtFindBreak (ptr, len, &numChars); /* * save off the character that doesn't match */ tmpChar = ptr[size]; /* * put in the null byte for the string. * and set to wide char if not doing multi-byte sequence. */ ptr[size] = '\0'; if (1 != len) seg_flags = _DtCvSetTypeToWideChar (seg_flags); /* * does this segment get the newline flag? */ if (True == newLine && size >= cur_vars->fmt_size) seg_flags = _DtCvSetTypeToNewLine(seg_flags); /* * save the segment. */ if (CheckSegList(cur_vars) == -1 || SegmentSave (cur_vars, seg_flags, font_attr, ptr, size, numChars, link_spec) == -1) return -1; /* * remove the wide char flag */ seg_flags &= ~(_DtCvWIDE_CHAR); /* * Bump the segment list count. */ cur_vars->my_list.cnt++; /* * replace the character that didn't match. * and bump the pointer to it. */ ptr[size] = tmpChar; ptr += size; cur_vars->fmt_size -= size; } while (0 < cur_vars->fmt_size); } else { if (CheckSegList (cur_vars) == -1 || SegmentSave (cur_vars, seg_flags, font_attr, cur_vars->fmt_buf, cur_vars->fmt_size, cur_vars->fmt_size, link_spec) == -1) return -1; cur_vars->my_list.cnt++; } cur_vars->fmt_size = 0; if (cur_vars->fmt_buf) cur_vars->fmt_buf[0] = '\0'; return 0; } /****************************************************************************** * Function: int CheckSaveSegment (int type, char **font_attr, int link_spec, * FormatVariables cur_vars) * * Parameters: * type Specifies the segment type. * font_attr Specifies the resource list of quarks for the * font to associate with the segment. * link_spec Specifies the link specification for the * segment. * * Returns: 0 if successful, -1 if errors. * * errno Values: * * Purpose: Checks 'cur_vars->fmt_size' for a non-zero value. If it is, * calls SaveSegment. * *****************************************************************************/ static int CheckSaveSegment ( unsigned long seg_flags, _DtHelpFontHints *font_attr, int link_spec, FormatVariables *cur_vars) { int result = 0; if (cur_vars->fmt_size) result = SaveStringAsSegments (cur_vars, seg_flags, font_attr, link_spec); return result; } /****************************************************************************** * Function: void TerminateSegList ( * * Parameters: * * Returns: 0 if successful, -1 if errors. * * Purpose: Links the segments together. * *****************************************************************************/ static void TerminateSegList ( SegList *seg_list, int flag) { int count; _DtCvSegment *lastDisp = NULL; _DtCvSegment *pSeg; if (True == flag && 0 == seg_list->cnt && NULL != seg_list->list) { free(seg_list->list); *seg_list = InitList; } /* * set the next segment and display segment pointers. */ for (count = 1, pSeg = seg_list->list; count < seg_list->cnt; count++, pSeg++) { /* * link this segment to the next segment */ pSeg->next_seg = &(pSeg[1]); /* * is this a displayable segment? * If so, link it into the displayable list. */ if (_DtCvIsSegNoop(pSeg) || _DtCvIsSegRegion(pSeg) || _DtCvIsSegString(pSeg)) { /* * Is there a displayable segment yet? * If so, set its next displayable link to this segment. */ if (NULL != lastDisp) lastDisp->next_disp = pSeg; /* * this segment becomes the last displayable segment. */ lastDisp = pSeg; } else lastDisp = NULL; } if (NULL != pSeg && NULL != lastDisp && (_DtCvIsSegNoop(pSeg) || _DtCvIsSegRegion(pSeg) || _DtCvIsSegString(pSeg))) lastDisp->next_disp = pSeg; } /****************************************************************************** * Function: int InitStructure (FormatVariables *cur_vars, * char *rd_buf, int rd_size, * * Parameters: * rd_buffer Specifies the buffer all reads use. * id_string Specifies the location ID to search for. * * Returns: 0 if successful, -1 if errors. * * errno Values: * * Purpose: Attach formatting information to the structure that gets * passed around by, among other things, setting the global * variable 'cur_vars->rd_ptr' to 'rd_buffer', and * remembering the location id. * *****************************************************************************/ static int InitStructure( FormatVariables *cur_vars, _FrmtUiInfo *ui_info, char *rd_buf, int rd_size) { cur_vars->ui_info = ui_info; cur_vars->rd_size = rd_size; cur_vars->rd_buf = rd_buf; cur_vars->rd_ptr = cur_vars->rd_buf; cur_vars->fmt_size = 0; if (cur_vars->fmt_buf) cur_vars->fmt_buf[0] = '\0'; /* * allocate the link data base. */ cur_vars->my_links = _DtLinkDbCreate(); if (NULL == cur_vars->my_links) return -1; return 0; } /****************************************************************************** * Function: int AppendToInfo (FormatVariables *cur_vars, * char **src, const char *scan_string) * * Parameters: * src Specifies the source string to read. * Returns pointing at a special character, * an invalid character or the * end of string. * scan_string Specifies the special characters to * look for in 'src'. * * Returns: 0 if stopped on a special character. * 1 if found the end of string. * 2 if found an invalid character. * -1 if errors. * * errno Values: * * Purpose: Appends onto 'cur_vars->fmt_buf' the number of characters * found in 'src' that does not match any character in * 'scan_string'. * * Sets 'cur_vars->last_was_space' to false (assumes that one * of the special characters is a space). * *****************************************************************************/ static int AppendToInfo ( FormatVariables *cur_vars, char **src, const char *scan_string ) { int spnResult; int size; cur_vars->last_was_space = False; spnResult = _DtHelpCeStrcspn(*src, scan_string, cur_vars->cur_mb_max, &size); if (0 < size) { if (_DtHelpCeAddStrToBuf(src,&(cur_vars->fmt_buf),&(cur_vars->fmt_size), &(cur_vars->fmt_buf_max),size,INFO_GROW) == -1) return -1; cur_vars->last_was_space = False; } if (spnResult == -1) spnResult = 2; if (0 == size && 1 == spnResult) spnResult = 0; return spnResult; } /****************************************************************************** * Function: int AppendOctalToInfo (FormatVariables *cur_vars, char *src) * * Parameters: * src Specifies the source string to read. * * Returns: 0 if successful, -1 if errors. * * errno Values: * CEErrorFormattingValue * CEErrorMalloc * * Purpose: Convert the octal representation pointed to by 'src' and * change it into a character byte. The routine only allows * a number between the values 1-255. * * Append the byte onto the global variable 'Info'. * Set 'cur_vars->last_was_space' to false. * *****************************************************************************/ static int AppendOctalToInfo( FormatVariables *cur_vars, char *src) { /* * must have 0xXX */ if (((int)strlen(src)) < 4 && cur_vars->my_file != NULL) { if (GetNextBuffer (cur_vars) == -1) return -1; src = cur_vars->rd_ptr; } if (_DtHelpCeAddOctalToBuf(src,&(cur_vars->fmt_buf),&(cur_vars->fmt_size), &(cur_vars->fmt_buf_max),INFO_GROW) == -1) return -1; cur_vars->last_was_space = False; return 0; } /****************************************************************************** * Function: int AppendCharToInfo (FormatVariables *cur_vars, char **src) * * Parameters: * src Specifies the source string to read. * Returns pointing at the next character * the string. * * Returns: 0 if successful, -1 if errors. * * errno Values: * * Purpose: Appends the character pointed to by 'src' onto the * global buffer 'Info', updating the pointers associated * with 'Info' accordingly. * * Sets 'cur_vars->last_was_space' to False; * *****************************************************************************/ static int AppendCharToInfo( FormatVariables *cur_vars, char **src) { cur_vars->last_was_space = False; return (_DtHelpCeAddCharToBuf (src, &(cur_vars->fmt_buf), &(cur_vars->fmt_size), &(cur_vars->fmt_buf_max), INFO_GROW)); } /****************************************************************************** * Function: int AppendSpaceToInfo (char **src, int type) * * Parameters: * src Specifies the source string to read. * Returns pointing at the next character * the string. * type Specifies the type of the segment being * processed. * * Returns: 0 if successful, -1 if errors. * * errno Values: * * Purpose: Appends a space onto the global buffer 'Info', if * the variable 'cur_vars->last_was_space' is false or the * static string flag is set in 'type'. * * Sets 'cur_vars->last_was_space' to true. * *****************************************************************************/ static int AppendSpaceToInfo ( FormatVariables *cur_vars, char **src, _DtCvFrmtOption type) { int result = 0; char *space = (char *) SpaceString; if (!cur_vars->last_was_space || _DtCvLITERAL == type) { result = _DtHelpCeAddCharToBuf (&space, &(cur_vars->fmt_buf), &(cur_vars->fmt_size), &(cur_vars->fmt_buf_max), INFO_GROW); cur_vars->last_was_space = True; } if (src != NULL) *src = *src + 1; return result; } /****************************************************************************** * Function: int FindEndMarker (FormatVariables *cur_vars) * * Returns: 0 if successful, -1 if errors. * * errno Values: * * Purpose: Wrapper around __DtHelpFindEndMarker. * Find the '>' token. * *****************************************************************************/ static int FindEndMarker( FormatVariables *cur_vars) { return (_DtHelpCeGetCcdfEndMark (cur_vars->my_file, cur_vars->rd_buf, &(cur_vars->rd_ptr),cur_vars->rd_size,1)); } /****************************************************************************** * Function: int GetNextBuffer (FormatVariables *cur_vars) * * Returns: 0 if successful, -1 if errors. * * errno Values: * * Purpose: Wrapper around __DtHelpGetNextBuffer. * Read the next buffer's worth of information. * *****************************************************************************/ static int GetNextBuffer ( FormatVariables *cur_vars) { cur_vars->rd_flag = _DtHelpCeGetNxtBuf (cur_vars->my_file, cur_vars->rd_buf, &(cur_vars->rd_ptr), cur_vars->rd_size); return (cur_vars->rd_flag); } /****************************************************************************** * Function: int SaveNewLine (FormatVariables *cur_vars, int cur_type, * char **font_attr, * int link_spec) * * Parameters: * cur_cmd Specifies the type of segment being processed. * font_attr Specifies the list of font quarks associated * with the current segment. * link_spec Specifies the hypertext link specification * associated with the current segment. * * Returns: 0 if successful, -1 if errors. * * errno Values: * * Purpose: Sets the newline flag on a segment and saves it by calling * 'SaveStringAsSegments'. * If the current segment is non-null, save it with the * newline flag set. * Otherwise if there are no segments saved, create one with the * a type of CE_old_NOOP. * Otherwise there are other segments, but the current segment is * empty. Look back at the previous segment. * If it doesn't have the newline set on it, * its newline flag is enabled. * Otherwise the previous segment had the newline set, so * create another segment just like it with a * null length and the newline flag set (if the * previous segment is a graphic, create it * with a type of CE_old_NOOP). * *****************************************************************************/ static int SaveNewLine( FormatVariables *cur_vars, int cur_type, _DtHelpFontHints *font_attr, int link_spec ) { int result = 0; _DtCvSegment *pSeg; /* * If there is information in the buffer, save it with the newline flag */ if (cur_vars->fmt_size) result = SaveStringAsSegments (cur_vars, _DtCvSetTypeToNewLine (cur_type), font_attr, link_spec); /* * check to see if there is any segments. If not create a new one * with the type NOOP. */ else if (0 == cur_vars->my_list.cnt) result = SaveStringAsSegments (cur_vars, _DtCvSetTypeToNewLine(_DtCvNOOP), font_attr, link_spec); /* * There was not any information in the buffer and we have one or * more segments. Try placing the flag on the previous segment. */ else { pSeg = NextAvailSeg(cur_vars->my_list); pSeg--; /* * Does the previous segment already have a newline flag? * If so, create a new NOOP segment with the newline set. */ if (_DtCvIsSegNewLine (pSeg)) result = SaveStringAsSegments (cur_vars, _DtCvSetTypeToNewLine (_DtCvNOOP), font_attr, link_spec); else pSeg->type = _DtCvSetTypeToNewLine (pSeg->type); } cur_vars->last_was_space = True; return result; } /****************************************************************************** * Function: int CreateSaveGraphic (FormatVariables cur_vars, * int type, * char *file_name, int link_spec ) * * Parameters: * type Specifies the type of graphic segment * being processed. * file_name Specifies the file name of the graphic. * link_spec Specifies the hypertext link specification * associated with the graphic. * * Returns: 0 if successful, -1 if errors. * * Purpose: Save a graphic segment. * If 'file_name' is not an absolute path, resolve it to * a full path by using the path to the volume. * *****************************************************************************/ static int CreateSaveGraphic ( FormatVariables *cur_vars, int type, char *file_name, int link_spec) { char *fullName; _DtCvSegment *cvRegion; if (CheckList (&(cur_vars->my_list), 1, 1) == -1) return -1; /* * create the path to the file name */ if (*file_name == '/') fullName = strdup (file_name); else { fullName = (char *) malloc (strlen (cur_vars->my_path) + strlen (file_name) + 2); if (fullName == NULL) return -1; strcpy (fullName, cur_vars->my_path); strcat (fullName, "/"); strcat (fullName, file_name); } /* * load the graphic into the current segment */ cvRegion = NextAvailSeg(cur_vars->my_list); if (NULL != cur_vars->ui_info->load_graphic && (*(cur_vars->ui_info->load_graphic))( cur_vars->ui_info->client_data, cur_vars->vol_name, cur_vars->topic_id, fullName, NULL, NULL, &(_DtCvWidthOfRegionSeg(cvRegion)), &(_DtCvHeightOfRegionSeg(cvRegion)), &(_DtCvInfoOfRegionSeg(cvRegion))) == 0) { /* * set the type and index. * and indicate that this segment has been used. */ _DtCvAscentOfRegionSeg(cvRegion) = -1; cvRegion->type = _DtCvSetTypeToRegion(type); cvRegion->link_idx = link_spec; cur_vars->my_list.cnt++; } /* * free the file name path */ free (fullName); return 0; } /****************************************************************************** * Function: int ChangeFont (int whichOne, int segType, * char **font_attr, int linkspec, * FormatVariables *cur_vars, int flags) * * Parameters: * whichOne Specifies the index into 'font_attr' to * change. * segType Specifies the type of segment currently * being processed. * font_attr Specifies the list of font quarks associated * with the current segment. * linkspec Specifies the hypertext link specification * associated with the segment. * flags Specifies the routines flags. * * Returns: The value returned from 'routine' if successful, -1 if errors. * * errno Values: * * Purpose: Saves any segment with the current font type and * process the next segment using the new font type. * *****************************************************************************/ static int ChangeFont( int whichOne, unsigned long seg_flags, _DtCvFrmtOption frmt_type, _DtHelpFontHints *font_attr, int linkspec, FormatVariables *cur_vars, ProcessState cur_state, int flags, int ret_on_nl, int fnt_flag) { int result; int oldMb_Len = cur_vars->cur_mb_max; char *fontString; _DtHelpFontHints oldFontStruct; if (CheckSaveSegment (seg_flags, font_attr, linkspec, cur_vars) == -1) return -1; oldFontStruct = *font_attr; if (GetStringParameter(cur_vars, _DtCvTRUE, _DtCvTRUE, _DtCvFALSE, _DtCvFALSE, &fontString) == -1) return -1; /* * Is this font change allowed to go through? */ if (!(fnt_flag & (1 << whichOne))) { switch (whichOne) { case _CEFONT_SPACING: font_attr->spacing = _DtHelpFontSpacingProp; if (fontString[0] == 'm') font_attr->spacing = _DtHelpFontSpacingMono; break; case _CEFONT_SIZE: font_attr->pointsz = atoi(fontString); break; case _CEFONT_ANGLE: font_attr->slant = _DtHelpFontSlantRoman; if (fontString[0] == 'i') font_attr->slant = _DtHelpFontSlantItalic; break; case _CEFONT_WEIGHT: font_attr->weight = _DtHelpFontWeightMedium; if (fontString[0] == 'b') font_attr->weight = _DtHelpFontWeightBold; break; case _CEFONT_TYPE: font_attr->style = _DtHelpFontStyleSanSerif; if (*fontString == 's') { if (fontString[1] == 'e') font_attr->style = _DtHelpFontStyleSerif; else if (fontString[1] == 'y') font_attr->style = _DtHelpFontStyleSymbol; } break; case _CEFONT_CHAR_SET: /* * Change to the correct mb_len. */ GetMbLen(cur_vars, fontString, &(_DtHelpFontHintsLang(*font_attr)), &(_DtHelpFontHintsCharSet(*font_attr))); break; } } result = FindEndMarker (cur_vars); if (!result) result = Parse (CCDF_FONT_CMD, cur_state, cur_vars, seg_flags, frmt_type, font_attr, linkspec, Specials, flags, ret_on_nl, fnt_flag); /* * free the lanugage and code sets strings. */ if (!(fnt_flag & (1 << whichOne)) && whichOne == _CEFONT_CHAR_SET) { free(_DtHelpFontHintsLang(*font_attr)); free(_DtHelpFontHintsCharSet(*font_attr)); } /* * reset the old quark * if necessary, reset the MB_LEN */ *font_attr = oldFontStruct; cur_vars->cur_mb_max = oldMb_Len; /* * free the memory */ free (fontString); if (result == -1) return -1; return 0; } /* ChangeFont */ /****************************************************************************** * Function: int SkipToNextToken (FormatVariables *cur_vars, int flag) * * Parameters: * flag Specifies whether the routine returns a -1 * if '>' is the next token. * * Returns: The value from __DtHelpSkipToNextToken: * -1 If problems encountered finding the next token. * 0 If no problems encountered finding the next token. * 1 If flag is true and the next token is a > character. * * errno Values: * * Purpose: Wrapper around __DtHelpSkipToNextToken. * Skip the current string and any spaces or newline * characters after it. * *****************************************************************************/ static int SkipToNextToken ( FormatVariables *cur_vars, _DtCvValue flag) { return (_DtHelpCeSkipToNextCcdfToken (cur_vars->my_file, cur_vars->rd_buf, cur_vars->rd_size, 1, &(cur_vars->rd_ptr), flag)); } /****************************************************************************** * Function: int GetStringParameter (FormatVariables *cur_vars, * int flag, int eat_escape, * int ignore_quotes, int less_test, * char **ret_string) * * Parameters: * flag Specifies whether the routine returns * a -1 if '>' is the next token. * eat_secape Specifies whether the backslash is not * placed in the returned string. * True - it is skipped. * False - it is saved in 'ret_string'. * ignore_quotes Specifies whether quotes are to be included * in the returned string. * less_test Specifies whether the routine should * stop when it finds a '<' character. * ret_string Returns the string found. * If NULL, throws the information away. * * Returns: The value from __DtHelpFormatGetStringParameter: * -1 If problems encountered. * 0 If no problems encountered getting the string. * 1 If flag is false and the no string was found. * * errno Values: * * Purpose: Wrapper around __DtHelpFormatGetStringParameter. * Skip the current string and any spaces or newline * characters after it. Get the next quoted/unquoted * string after that. * *****************************************************************************/ static int GetStringParameter( FormatVariables *cur_vars, _DtCvValue flag, _DtCvValue eat_escape, _DtCvValue ignore_quotes, _DtCvValue less_test, char **ret_string) { return (_DtHelpCeGetCcdfStrParam (cur_vars->my_file, cur_vars->rd_buf, cur_vars->rd_size, cur_vars->cur_mb_max, &(cur_vars->rd_ptr), flag, eat_escape, ignore_quotes, less_test, ret_string)); } /****************************************************************************** * Function: int GetValueParameter (FormatVariables *cur_vars, * int flag, int *ret_value) * * Parameters: * flag Specifies whether the routine returns * a -2 if '>' is the next token. * ret_value Returns the atoi conversion * of the string found. * * Returns: The value from __DtHelpFormatGetValueParameter: * -1 If problems encountered. * 0 If no problems encountered getting the string. * -2 If flag is true and the next token is a > * character. * * errno Values: * * Purpose: Wrapper around __DtHelpFormatGetValueParameter. * Skip the current string and any spaces or newline * characters after it. Process the next string as * a numeric value. * *****************************************************************************/ static int GetValueParameter( FormatVariables *cur_vars, _DtCvValue flag, int *ret_value ) { return (_DtHelpCeGetCcdfValueParam (cur_vars->my_file, cur_vars->rd_buf, cur_vars->rd_size, &(cur_vars->rd_ptr), flag, cur_vars->cur_mb_max, ret_value)); } /****************************************************************************** * Function: int GetParagraphParameters (FormatVariables *cur_vars, * int seg_type, int graphic_type, * char **label, char **file_name, * char **link_string, int *link_type, * char **description) * * Parameters: * seg_type Specifies the default type for the segment. * Returns the new type for the segment. * graphic_type Specifies the default type for a graphic * if a justified graphic is * encountered in the paragraph options. * Returns the new type for a graphic * if a justified graphic was * encountered in the paragraph options. * label Returns the label if one is specified * in the paragraph options. * file_name Returns the file name of a graphic if * one is specified in the paragraph * options. * link_string Returns the hypertext specification if one * is specified in the paragraph options. * link_type Returns the hypertext link type if one is * specified. * description Returns the hypertext description if one * is specified. * * Returns: 0 if successfult, -1 if errors. * * errno Values: * * Purpose: Wrapper around __DtHelpParagraphGetOptions. * Process the options found in syntax. * Test to see if the id specified in the * is the one we are looking at. * *****************************************************************************/ static int GetParagraphParameters( FormatVariables *cur_vars, _DtCvSegment *para, _DtCvFrmtOption *frmt_type, _DtCvFrmtOption *gpos, char **glink, int *glinktype, _DtCvUnit *gspace, char **ret_label, char **file_name, char **description) { int done = False; int result = 0; int optionCount = 0; int value; char *tmpString = NULL; /* * initialize string variables if valid addresses */ *ret_label = NULL; *file_name = NULL; *glink = NULL; *description = NULL; *gpos = _DtCvJUSTIFY_LEFT; *glinktype = -1; *gspace = 0; while (False == done && result != -1) { if (SkipToNextToken (cur_vars, _DtCvFALSE) == -1) return -1; switch (_DtCvToLower(*(cur_vars->rd_ptr))) { /* * end of paragraph spec */ case '>': (cur_vars->rd_ptr)++; done = True; break; /* * after value */ case 'a': if (GetValueParameter (cur_vars, _DtCvFALSE, &value) == -1) return -1; _DtCvContainerBMarginOfSeg(para) = 0; if (value > 0 && 0 < cur_vars->ui_info->line_height) _DtCvContainerBMarginOfSeg(para) = value * (cur_vars->ui_info->line_height / 2); break; /* * before value */ case 'b': if (GetValueParameter (cur_vars, _DtCvFALSE, &value) == -1) return -1; _DtCvContainerTMarginOfSeg(para) = 0; if (value > 0 && 0 < cur_vars->ui_info->line_height) _DtCvContainerTMarginOfSeg(para) = value * (cur_vars->ui_info->line_height / 2); break; /* * description [string | "string" | 'string'] */ case 'd': result = GetStringParameter(cur_vars, _DtCvTRUE, _DtCvTRUE, _DtCvFALSE, _DtCvFALSE, description); break; /* * firstindent value */ case 'f': if (GetValueParameter (cur_vars, _DtCvFALSE, &value) == -1) return -1; _DtCvContainerFMarginOfSeg(para) = value * cur_vars->ui_info->avg_char; break; /* * glink [string | "string" | 'string'] * gpos value_string * graphic string * gspace value * gtypelink value */ case 'g': /* * to determine what token this is we must look at the * second character. */ (cur_vars->rd_ptr)++; /* * do we need to read more? */ if (*(cur_vars->rd_ptr) == '\0' && GetNextBuffer(cur_vars) == -1) return -1; /* * check for the next permutation */ switch (_DtCvToLower(*(cur_vars->rd_ptr))) { /* * glink [string | "string" | 'string'] */ case 'l': result = GetStringParameter(cur_vars, _DtCvTRUE, _DtCvTRUE, _DtCvFALSE, _DtCvFALSE, glink); break; /* * gpos value_string */ case 'p': result = GetStringParameter(cur_vars, _DtCvTRUE, _DtCvTRUE, _DtCvFALSE, _DtCvFALSE, &tmpString); if (-1 != result && _DtCvToLower (*tmpString) == 'r') *gpos = _DtCvJUSTIFY_RIGHT; if (tmpString) free (tmpString); break; /* * graphic string */ case 'r': result = GetStringParameter(cur_vars, _DtCvTRUE, _DtCvTRUE, _DtCvFALSE, _DtCvFALSE, file_name); break; /* * gspace value */ case 's': if (GetValueParameter(cur_vars,_DtCvFALSE,&value) == -1 || value < 0) return -1; *gspace = value * cur_vars->ui_info->avg_char; break; /* * gtypelink value */ case 't': if (GetValueParameter(cur_vars,_DtCvFALSE,glinktype) == -1 || *glinktype < 0) return -1; break; } break; /* * id string */ case 'i': /* * get the id string */ if (GetStringParameter(cur_vars, _DtCvTRUE, _DtCvTRUE, _DtCvFALSE, _DtCvFALSE, &tmpString) == -1) return -1; _DtCvContainerIdOfSeg(para) = tmpString; break; /* * label [string | "string" | 'string'] * leftindent value */ case 'l': /* * to determine what token this is we must look at the * second and possibly the third characters. */ (cur_vars->rd_ptr)++; /* * do we need to read more? */ if (*(cur_vars->rd_ptr) == '\0' && GetNextBuffer(cur_vars) == -1) return -1; /* * check for the next permutation */ if (_DtCvToLower(*(cur_vars->rd_ptr)) == 'a') { /* * label */ if (GetStringParameter(cur_vars, _DtCvTRUE, _DtCvFALSE, _DtCvFALSE, _DtCvFALSE, &tmpString) == -1) return -1; /* * If we got a label process it. */ if (ret_label == NULL || *ret_label) { /* * we've already processed a label! * ignore this one! */ if (tmpString) free (tmpString); } else *ret_label = tmpString; } else if (_DtCvToLower(*(cur_vars->rd_ptr)) == 'e') { /* * leftindent */ if (GetValueParameter (cur_vars, _DtCvFALSE, &value) == -1) return -1; _DtCvContainerLMarginOfSeg(para) = value * cur_vars->ui_info->avg_char; } else result = -1; break; /* * nowrap */ case 'n': _DtCvContainerTypeOfSeg(para) = _DtCvLITERAL; *frmt_type = _DtCvLITERAL; break; /* * rightindent value */ case 'r': if (GetValueParameter (cur_vars, _DtCvFALSE, &value) == -1) return -1; _DtCvContainerRMarginOfSeg(para) = value * cur_vars->ui_info->avg_char; break; /* * wrap */ case 'w': _DtCvContainerTypeOfSeg(para) = _DtCvDYNAMIC; *frmt_type = _DtCvDYNAMIC; break; /* * Found an option we don't understand. */ default: result = -1; } optionCount++; } /* * adjust the first margin to correctly indicate the offset from the * left margin. In the old CCDF, the first margin indicated left plus * and additional indent. For the new Canvas Engine, it is suppose * to be an addition on top of the left margin. */ _DtCvContainerFMarginOfSeg(para) = _DtCvContainerLMarginOfSeg(para) - _DtCvContainerFMarginOfSeg(para); if (-1 == result) optionCount = 0; return (optionCount - 1); } /* End GetParagraphParameters */ /****************************************************************************** * Function: int FlowingParagraph ( * * Parameters: * * Returns: * * errno Values: * * Purpose: Process the specification. * *****************************************************************************/ static int FlowingParagraph( FormatVariables *cur_vars, ProcessState cur_state, _DtCvFrmtOption frmt_flags, int allowed, int link_idx, int ret_on_nl, int fnt_flag, _DtCvFrmtOption gpos, _DtCvUnit gspace, char *file_name, _DtHelpFontHints *font_attr) { int type = 0; int result = -1; _DtCvSegment *graphSeg; _DtCvSegment *bodySeg; SegList flowList = InitList; /* * reset current list */ cur_vars->my_list = InitList; /* * create two containers. */ if (0 == CheckList(&(flowList), 2, 2)) { /* * point to the containers for the graphic and body. */ graphSeg = flowList.list; bodySeg = flowList.list; bodySeg++; /* * set the bottom margins to zero. */ graphSeg->type = _DtCvSetTypeToContainer(graphSeg->type); bodySeg->type = _DtCvSetTypeToContainer(bodySeg->type); _DtCvContainerBMarginOfSeg(graphSeg) = 0; _DtCvContainerBMarginOfSeg(bodySeg) = 0; /* * so the first segment is the container for the graphic. * set the controller flag and values. */ graphSeg->type = _DtCvSetTypeToController(graphSeg->type); _DtCvContainerFlowOfSeg(graphSeg) = _DtCvWRAP; _DtCvContainerPercentOfSeg(graphSeg) = 0; _DtCvContainerOrientOfSeg(graphSeg) = gpos; if (_DtCvJUSTIFY_LEFT == gpos) { _DtCvContainerJustifyOfSeg(graphSeg) = gpos; _DtCvContainerRMarginOfSeg(graphSeg) = gspace; } else { _DtCvContainerJustifyOfSeg(graphSeg) = gpos; _DtCvContainerLMarginOfSeg(graphSeg) = gspace; } /* * mark the first segment as used. */ flowList.cnt++; /* * check for hypertext link. */ if (link_idx > -1) type = _DtCvHYPER_TEXT; /* * re-set the segment list and create the graphic. */ if (0 == CreateSaveGraphic(cur_vars, type, file_name, link_idx)) { /* * so the first segment in cur_vars is a region. * attach it to the graphic container. */ _DtCvContainerListOfSeg(graphSeg) = cur_vars->my_list.list; /* * now process the following information as the body of * the paragraph as the list for the non-controller * container. */ cur_vars->my_list = InitList; if (-1 != Parse (CCDF_PARAGRAPH_CMD, cur_state, cur_vars, 0, frmt_flags, font_attr, -1, Specials, allowed, ret_on_nl, fnt_flag)) { /* * establish the links between the segments */ TerminateSegList(&(cur_vars->my_list), True); /* * if there was a segment list generated, * attach the it to the non-controller * container and mark it as used. */ if (NULL != cur_vars->my_list.list) { _DtCvContainerListOfSeg(bodySeg) = cur_vars->my_list.list; flowList.cnt++; } result = 0; } } } cur_vars->my_list = flowList; TerminateSegList(&(cur_vars->my_list), True); return result; } /****************************************************************************** * Function: int ProcessParagraph ( * * Parameters: * * Returns: * * errno Values: * * Purpose: Process the specification. * *****************************************************************************/ static int ProcessParagraph( FormatVariables *cur_vars, ProcessState cur_state, int fnt_flag) { int result = 0; int labelFnd = False; int allowed = ~(CCDF_TOPIC_CMD | CCDF_TITLE_CMD | CCDF_ABBREV_CMD); int oldMbLenMax = cur_vars->cur_mb_max; int glinktype = -1; int linkIndex = -1; _DtCvUnit gspace = 0; char *glinkSpec = NULL; char *label = NULL; char *fileName = NULL; char *description = NULL; char numChar[16]; ProcessState myState = NormalState; _DtCvFrmtOption gpos; _DtCvFrmtOption frmtType = _DtCvDYNAMIC; _DtCvSegment *paraSeg; _DtCvSegment *labelSeg = NULL; _DtCvSegment *col1 = NULL; _DtCvSegment *col2 = NULL; _DtCvSegment **childList; SegList oldList; SegList tableList = InitList; _DtHelpFontHints fontAttrs; /* * remember the old font list. * initialize the font quark list * and use the char set specified for this topic. */ _DtHelpCeCopyDefFontAttrList (&fontAttrs); cur_vars->cur_mb_max = cur_vars->topic_mb_max; _DtHelpFontHintsLang(fontAttrs) = cur_vars->topic_lang; _DtHelpFontHintsCharSet(fontAttrs) = cur_vars->topic_char_set; /* * Make next segment in my parent's list for a container for this * paragraph. */ if (-1 == CheckSegList(cur_vars)) return -1; /* * remember the parent list * make sure the defaults are set */ oldList = cur_vars->my_list; paraSeg = NextAvailSeg(cur_vars->my_list); paraSeg->handle.container = DefContainer; paraSeg->type = _DtCvSetTypeToContainer(paraSeg->type); _DtCvContainerLeadingOfSeg(paraSeg) = cur_vars->ui_info->leading; cur_vars->my_list = InitList; /* * get the parameters on the paragraph * and set the default for the bottom. */ result = GetParagraphParameters (cur_vars, paraSeg, &frmtType, &gpos, &glinkSpec, &glinktype, &gspace, &label, &fileName, &description); /* * for lists, we will inherit our parent's bottom margin * when we return to the loop processing the list. Therefore, * set our bottom margin to zero if we are part of a label body. */ if (0 == result && LabelBody == cur_state) _DtCvContainerBMarginOfSeg(paraSeg) = 0; else if (result > 0) result = 0; /* * check for a label specification. Either as a 'label' parameter * or a the