5475 lines
135 KiB
C
5475 lines
135 KiB
C
/*
|
|
* 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 librararies 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 <ctype.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#if defined(sun)
|
|
#include <sys/utsname.h>
|
|
#endif
|
|
#include <limits.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xresource.h>
|
|
|
|
#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 *CString = "C";
|
|
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;
|
|
|
|
/*
|
|
* 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 seperate strings by replacing
|
|
* the dot with a end of line.
|
|
*/
|
|
*ptr++ = '\0';
|
|
langPart = strdup(font_str);
|
|
codePart = strdup(ptr);
|
|
}
|
|
|
|
/*
|
|
* old CCDF volume
|
|
*/
|
|
else
|
|
{
|
|
_DtHelpCeXlateOpToStdLocale(DtLCX_OPER_CCDF, font_str,
|
|
NULL, &langPart, &codePart);
|
|
/*
|
|
* if the language is not specified for the code set,
|
|
* get the environment's.
|
|
*/
|
|
if (strcmp(langPart, "?") == 0)
|
|
{
|
|
free(langPart);
|
|
|
|
langPart = _DtHelpGetLocale();
|
|
if (langPart == NULL || *langPart == '\0')
|
|
langPart = strdup((char *) CString);
|
|
else if (_DtHelpCeStrrchr(langPart, "_", MB_CUR_MAX, &ptr) == 0)
|
|
*ptr = '\0';
|
|
else if (_DtHelpCeStrrchr(langPart, Period, MB_CUR_MAX, &ptr) == 0)
|
|
*ptr = '\0';
|
|
}
|
|
}
|
|
|
|
cur_vars->cur_mb_max = _DtHelpCeGetMbLen(langPart, codePart);
|
|
|
|
/*
|
|
* 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);
|
|
}
|
|
|
|
/******************************************************************************
|
|
* 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)
|
|
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 <PARAGRAPH> syntax.
|
|
* Test to see if the id specified in the <PARAGRAPH>
|
|
* 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 <PARAGRAPH> 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 <PARAGRAPH> 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 <LABEL> command.
|
|
*/
|
|
if (-1 != result)
|
|
{
|
|
/*
|
|
* check for the parameter
|
|
*/
|
|
if (NULL != label)
|
|
{
|
|
FormatVariables oldVars = *cur_vars;
|
|
|
|
cur_vars->rd_buf = label;
|
|
cur_vars->rd_flag = 0;
|
|
cur_vars->rd_ptr = label;
|
|
cur_vars->my_file = NULL;
|
|
|
|
result = Parse (CCDF_LABEL_CMD, NormalState, cur_vars,
|
|
0, frmtType,
|
|
&fontAttrs, -1,
|
|
Specials,
|
|
(CCDF_FONT_CMD | CCDF_OCTAL_CMD),
|
|
False, fnt_flag);
|
|
|
|
if (result != -1)
|
|
result = CheckSaveSegment (_DtCvSTRING, &fontAttrs,
|
|
-1, cur_vars);
|
|
|
|
TerminateSegList(&(cur_vars->my_list), True);
|
|
cur_vars->rd_buf = oldVars.rd_buf;
|
|
cur_vars->rd_flag = oldVars.rd_flag;
|
|
cur_vars->rd_ptr = oldVars.rd_ptr;
|
|
cur_vars->my_file = oldVars.my_file;
|
|
cur_vars->last_was_space = True;
|
|
|
|
labelSeg = cur_vars->my_list.list;
|
|
cur_vars->my_list = InitList;
|
|
labelFnd = True;
|
|
}
|
|
/*
|
|
* check for the command.
|
|
*/
|
|
else if (0 == _DtHelpCeCheckNextCcdfCmd("lab", cur_vars->my_file,
|
|
cur_vars->rd_buf,
|
|
cur_vars->rd_size, 1,
|
|
&(cur_vars->rd_ptr)))
|
|
{
|
|
result = ProcessLabelCmd(cur_vars, 0, frmtType,
|
|
&fontAttrs, -1,
|
|
allowed, False, fnt_flag,
|
|
&labelSeg);
|
|
labelFnd = True;
|
|
}
|
|
|
|
/*
|
|
* if a label was processed, create the containers for it.
|
|
*/
|
|
if (-1 != result && True == labelFnd)
|
|
{
|
|
/*
|
|
* set the correct state.
|
|
*/
|
|
myState = LabelBody;
|
|
|
|
/*
|
|
* create containers for the label and it's body
|
|
*/
|
|
result = CheckList(&tableList, 2, 2);
|
|
if (-1 != result)
|
|
{
|
|
/*
|
|
* set the top and bottom margins on both the child
|
|
* containers (so they are the same) to reflect
|
|
* the list's before/after values.
|
|
*/
|
|
/*
|
|
* set the pointer to the first column
|
|
* overwrite the left and right margin values.
|
|
*/
|
|
col1 = NextAvailSeg(tableList);
|
|
col1->type = _DtCvSetTypeToContainer(col1->type);
|
|
_DtCvContainerTMarginOfSeg(col1) =
|
|
_DtCvContainerTMarginOfSeg(paraSeg);
|
|
_DtCvContainerBMarginOfSeg(col1) =
|
|
_DtCvContainerBMarginOfSeg(paraSeg);
|
|
_DtCvContainerLMarginOfSeg(col1) = 0;
|
|
_DtCvContainerRMarginOfSeg(col1) = cur_vars->ui_info->avg_char;
|
|
tableList.cnt++;
|
|
|
|
/*
|
|
* set the pointer for the second column
|
|
* and set the top/bottom values.
|
|
*/
|
|
col2 = NextAvailSeg(tableList);
|
|
col2->type = _DtCvSetTypeToContainer(col2->type);
|
|
_DtCvContainerTMarginOfSeg(col2) =
|
|
_DtCvContainerTMarginOfSeg(paraSeg);
|
|
_DtCvContainerBMarginOfSeg(col2) =
|
|
_DtCvContainerBMarginOfSeg(paraSeg);
|
|
tableList.cnt++;
|
|
|
|
/*
|
|
* create an id for this label
|
|
*/
|
|
sprintf(numChar, "%d", cur_vars->cell_cnt++);
|
|
_DtCvContainerIdOfSeg(col1) = (char *) malloc (
|
|
strlen("&CCDF_RES_") + strlen(numChar) + 1);
|
|
if (NULL != _DtCvContainerIdOfSeg(col1))
|
|
{
|
|
/*
|
|
* copy over the id and attach the list.
|
|
*/
|
|
strcpy(_DtCvContainerIdOfSeg(col1), "&CCDF_RES_");
|
|
strcat(_DtCvContainerIdOfSeg(col1), numChar);
|
|
_DtCvContainerListOfSeg(col1) = labelSeg;
|
|
|
|
/*
|
|
* set the id for the second column.
|
|
*/
|
|
sprintf(numChar, "%d", cur_vars->cell_cnt++);
|
|
_DtCvContainerIdOfSeg(col2) = (char *) malloc (
|
|
strlen("&CCDF_RES_") + strlen(numChar) + 1);
|
|
if (NULL != _DtCvContainerIdOfSeg(col2))
|
|
{
|
|
strcpy(_DtCvContainerIdOfSeg(col2), "&CCDF_RES_");
|
|
strcat(_DtCvContainerIdOfSeg(col2), numChar);
|
|
}
|
|
else
|
|
result = -1;
|
|
}
|
|
else
|
|
result = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* disallow labels from here on out. Either one was found and processed
|
|
* or not.
|
|
*/
|
|
allowed &= (~(CCDF_LABEL_CMD));
|
|
|
|
/*
|
|
* Now check and process the graphic specification.
|
|
*/
|
|
if (-1 != result)
|
|
{
|
|
/*
|
|
* initialize the segment list for the children of the paragraph.
|
|
*/
|
|
cur_vars->my_list = InitList;
|
|
|
|
/*
|
|
* check for a graphic in the specification.
|
|
* If so, then we need to create, as the list for the
|
|
* paragraph container, two containers; one container
|
|
* that is a controller and has the graphic and the
|
|
* other contains the rest of the content of the
|
|
* paragraph.
|
|
*
|
|
* First, create the link index for the graphic.
|
|
*/
|
|
if (NULL != glinkSpec)
|
|
{
|
|
/*
|
|
* but if there isn't a graphic, throw away the link
|
|
* specifications since they are useless!
|
|
*/
|
|
if (NULL != fileName && strlen (glinkSpec))
|
|
{
|
|
linkIndex = _DtLinkDbAddLink (cur_vars->my_links,
|
|
NULL,
|
|
glinkSpec,
|
|
ReturnLinkType(glinktype, glinkSpec),
|
|
ReturnLinkWinHint(glinktype),
|
|
description);
|
|
|
|
/*
|
|
* had problems creating the link index, bail
|
|
*/
|
|
if (linkIndex == -1)
|
|
result = -1;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* now create the graphic and process the graphic body..
|
|
* or just process the rest of the paragraph....
|
|
*/
|
|
if (0 == result)
|
|
{
|
|
if (NULL != fileName)
|
|
result = FlowingParagraph(cur_vars,
|
|
myState,
|
|
frmtType,
|
|
allowed, linkIndex,
|
|
False, fnt_flag,
|
|
gpos, gspace, fileName,
|
|
&fontAttrs);
|
|
else
|
|
{
|
|
result = Parse (CCDF_PARAGRAPH_CMD, myState, cur_vars,
|
|
0, frmtType,
|
|
&fontAttrs, -1,
|
|
Specials, allowed,
|
|
False, fnt_flag);
|
|
if (-1 != result)
|
|
{
|
|
/*
|
|
* establish the links
|
|
*/
|
|
TerminateSegList (&(cur_vars->my_list), True);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (-1 != result)
|
|
{
|
|
char **colW;
|
|
_DtCvFrmtOption *colJ;
|
|
|
|
if (True == labelFnd)
|
|
{
|
|
char *colW1 = "1"; /* default bulletted list */
|
|
char *colW2 = "99,0,98"; /* default bulletted list */
|
|
char *ids;
|
|
|
|
/*
|
|
* set the body of the label in it's container.
|
|
*/
|
|
_DtCvContainerListOfSeg(col2) = cur_vars->my_list.list;
|
|
|
|
/*
|
|
* figure out which column widths should be used.
|
|
*/
|
|
if (14 * cur_vars->ui_info->avg_char
|
|
== _DtCvContainerLMarginOfSeg(paraSeg))
|
|
{
|
|
/* Labeled lists */
|
|
colW1 = "20,20,10";
|
|
colW2 = "80,10,20";
|
|
}
|
|
else if (3 * cur_vars->ui_info->avg_char
|
|
== _DtCvContainerLMarginOfSeg(paraSeg))
|
|
/* Ordered lists */
|
|
colW1 = "1,98,0";
|
|
else if (0 == _DtCvContainerLMarginOfSeg(paraSeg))
|
|
/* Plain lists */
|
|
colW1 = "0";
|
|
|
|
/*
|
|
* create the column width strings.
|
|
*/
|
|
colW = NULL;
|
|
colW = (char **) _DtCvAddPtrToArray((void **) colW,
|
|
((void *) strdup(colW1)));
|
|
if (NULL != colW)
|
|
colW = (char **) _DtCvAddPtrToArray((void **) colW,
|
|
((void *) strdup (colW2)));
|
|
|
|
/*
|
|
* create the array for column justification.
|
|
*/
|
|
colJ = (_DtCvFrmtOption *) malloc (sizeof(_DtCvFrmtOption) * 2);
|
|
if (NULL != colJ)
|
|
{
|
|
colJ[0] = _DtCvJUSTIFY_LEFT;
|
|
colJ[1] = _DtCvJUSTIFY_LEFT;
|
|
}
|
|
|
|
/*
|
|
* set this segment's type to a table and fill in all
|
|
* the relevant information.
|
|
*/
|
|
paraSeg->type = _DtCvTABLE;
|
|
_DtCvNumColsOfTableSeg(paraSeg) = 2;
|
|
_DtCvColWOfTableSeg(paraSeg) = colW;
|
|
_DtCvColJustifyOfTableSeg(paraSeg) = colJ;
|
|
_DtCvJustifyCharsOfTableSeg(paraSeg) = NULL;
|
|
|
|
/*
|
|
* now create the list of ids in this table.
|
|
*/
|
|
ids = (char *) malloc (
|
|
strlen(_DtCvContainerIdOfSeg(col1)) +
|
|
strlen(_DtCvContainerIdOfSeg(col2)) + 2);
|
|
if (NULL != ids)
|
|
{
|
|
strcpy(ids, _DtCvContainerIdOfSeg(col1));
|
|
strcat(ids, " ");
|
|
strcat(ids, _DtCvContainerIdOfSeg(col2));
|
|
}
|
|
_DtCvCellIdsOfTableSeg(paraSeg) = NULL;
|
|
_DtCvCellIdsOfTableSeg(paraSeg) = (char **)
|
|
_DtCvAddPtrToArray(
|
|
(void **) _DtCvCellIdsOfTableSeg(paraSeg),
|
|
(void *) ids);
|
|
|
|
/*
|
|
* now create the list of cells in the table.
|
|
*/
|
|
_DtCvCellsOfTableSeg(paraSeg) = NULL;
|
|
_DtCvCellsOfTableSeg(paraSeg) = (_DtCvSegment **)
|
|
_DtCvAddPtrToArray(
|
|
(void **) _DtCvCellsOfTableSeg(paraSeg),
|
|
(void *) col1);
|
|
if (NULL != _DtCvCellsOfTableSeg(paraSeg))
|
|
_DtCvCellsOfTableSeg(paraSeg) = (_DtCvSegment **)
|
|
_DtCvAddPtrToArray(
|
|
(void **) _DtCvCellsOfTableSeg(paraSeg),
|
|
(void *) col2);
|
|
|
|
if (NULL == colW || NULL == colJ || NULL == ids
|
|
|| NULL == _DtCvCellIdsOfTableSeg(paraSeg)
|
|
|| NULL == _DtCvCellsOfTableSeg(paraSeg))
|
|
result = -1;
|
|
}
|
|
else
|
|
{
|
|
_DtCvSegment *pSeg;
|
|
|
|
/*
|
|
* attach the list to my container.
|
|
*/
|
|
_DtCvContainerListOfSeg(paraSeg) = cur_vars->my_list.list;
|
|
|
|
/*
|
|
* consolidate any table children I have.
|
|
*/
|
|
for (pSeg = cur_vars->my_list.list, labelSeg = NULL;
|
|
-1 != result && NULL != pSeg;
|
|
pSeg = pSeg->next_seg)
|
|
{
|
|
if (_DtCvIsSegTable(pSeg))
|
|
{
|
|
if (NULL != labelSeg)
|
|
{
|
|
/*
|
|
* bypass this segment since it will no
|
|
* longer be 'used' by consolidating it
|
|
* with another label set.
|
|
*/
|
|
labelSeg->next_seg = pSeg->next_seg;
|
|
|
|
/*
|
|
* free the other justification and width info.
|
|
*/
|
|
free((void *) _DtCvColJustifyOfTableSeg(pSeg));
|
|
colW = _DtCvColWOfTableSeg(pSeg);
|
|
free(*colW++);
|
|
free(*colW);
|
|
free(_DtCvColWOfTableSeg(pSeg));
|
|
|
|
/*
|
|
* add the segments to the list
|
|
*/
|
|
childList = _DtCvCellsOfTableSeg(pSeg);
|
|
_DtCvCellsOfTableSeg(labelSeg) = (_DtCvSegment **)
|
|
_DtCvAddPtrToArray(
|
|
(void **) _DtCvCellsOfTableSeg(labelSeg),
|
|
*childList);
|
|
childList++;
|
|
if (NULL != _DtCvCellsOfTableSeg(labelSeg))
|
|
_DtCvCellsOfTableSeg(labelSeg) = (_DtCvSegment **)
|
|
_DtCvAddPtrToArray(
|
|
(void **)_DtCvCellsOfTableSeg(labelSeg),
|
|
*childList);
|
|
free((void *) _DtCvCellsOfTableSeg(pSeg));
|
|
|
|
/*
|
|
* add the ids to the list
|
|
*/
|
|
_DtCvCellIdsOfTableSeg(labelSeg) = (char **)
|
|
_DtCvAddPtrToArray(
|
|
(void **)_DtCvCellIdsOfTableSeg(labelSeg),
|
|
(void *)(*(_DtCvCellIdsOfTableSeg(pSeg))));
|
|
|
|
free((void *) _DtCvCellIdsOfTableSeg(pSeg));
|
|
|
|
if (NULL == _DtCvCellIdsOfTableSeg(labelSeg)
|
|
|| NULL == _DtCvCellsOfTableSeg(labelSeg))
|
|
result = -1;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* this segment becomes the segment holding
|
|
* the consolidated table.
|
|
*/
|
|
labelSeg = pSeg;
|
|
}
|
|
}
|
|
else
|
|
labelSeg = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* restore the font MB_CUR_MAX
|
|
*/
|
|
cur_vars->cur_mb_max = oldMbLenMax;
|
|
|
|
/*
|
|
* free all the strings
|
|
*/
|
|
if (label != NULL)
|
|
free (label);
|
|
if (fileName != NULL)
|
|
free (fileName);
|
|
|
|
/*
|
|
* free the linkSpec and description,
|
|
*/
|
|
if (NULL != description)
|
|
free(description);
|
|
if (NULL != glinkSpec)
|
|
free(glinkSpec);
|
|
|
|
if (result == -1)
|
|
return -1;
|
|
|
|
oldList.cnt++;
|
|
cur_vars->my_list = oldList;
|
|
cur_vars->last_was_space = True;
|
|
return 0;
|
|
|
|
} /* End ProcessParagraph */
|
|
|
|
/******************************************************************************
|
|
* Function: int ProcessHypertext (
|
|
* FormatVariables *cur_vars, int segType,
|
|
* char **font_attr, int flags )
|
|
*
|
|
* Parameters:
|
|
* segType Specifies the type of segment currently
|
|
* being processed.
|
|
* font_attr Specifies the list of font quarks to
|
|
* associate with the string.
|
|
* flags Specifies the formatting commands allowed.
|
|
*
|
|
* Returns: 0 if successful, -1 if errors.
|
|
*
|
|
* errno Values:
|
|
*
|
|
* Purpose: Process the <LINK> specification.
|
|
*
|
|
*****************************************************************************/
|
|
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)
|
|
{
|
|
int result = 0;
|
|
int hyperType;
|
|
int hyperIndex;
|
|
char *description = NULL;
|
|
char *hyperlink = NULL;
|
|
|
|
/*
|
|
* is a <LINK> command allowed here?
|
|
*/
|
|
if (CCDF_NOT_ALLOW_CMD(flags, CCDF_LINK_CMD))
|
|
return -1;
|
|
|
|
/*
|
|
* get the hypertext type
|
|
*/
|
|
if (GetValueParameter (cur_vars, _DtCvTRUE, &hyperType) < 0)
|
|
return -1;
|
|
|
|
if (hyperType < 0)
|
|
{
|
|
errno = CEErrorHyperType;
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* get the hypertext link spec.
|
|
*/
|
|
result = GetStringParameter(cur_vars, _DtCvTRUE, _DtCvTRUE, _DtCvFALSE,
|
|
_DtCvFALSE, &hyperlink);
|
|
if (0 == result)
|
|
{
|
|
/*
|
|
* See if we have the optional description string
|
|
*/
|
|
result = GetStringParameter (cur_vars, _DtCvFALSE, _DtCvTRUE,
|
|
_DtCvFALSE, _DtCvFALSE, &description);
|
|
if (result == 1)
|
|
description = NULL;
|
|
|
|
result = _DtLinkDbAddLink (cur_vars->my_links,
|
|
NULL,
|
|
hyperlink,
|
|
ReturnLinkType(hyperType, hyperlink),
|
|
ReturnLinkWinHint(hyperType),
|
|
description);
|
|
if (NULL != description)
|
|
free(description);
|
|
|
|
free(hyperlink);
|
|
}
|
|
|
|
/*
|
|
* if no problems encountered, start parsing with this
|
|
* hypertext link.
|
|
*/
|
|
if (result != -1)
|
|
{
|
|
hyperIndex = result;
|
|
result = FindEndMarker (cur_vars);
|
|
if (!result)
|
|
{
|
|
/*
|
|
* set the hypertext flag and type.
|
|
*/
|
|
seg_flags = _DtCvSetTypeToHyperText(seg_flags);
|
|
|
|
result = Parse (CCDF_LINK_CMD, cur_state, cur_vars,
|
|
seg_flags, frmt_type,
|
|
font_attr,
|
|
hyperIndex,
|
|
Specials, flags,
|
|
ret_on_nl, fnt_flag);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Don't free the hypertext string or description.
|
|
* It is now owned by the Link List.
|
|
*/
|
|
|
|
if (result == -1)
|
|
return -1;
|
|
|
|
return 0;
|
|
|
|
} /* End ProcessHypertext */
|
|
|
|
/******************************************************************************
|
|
* Function: int ProcessLabelCmd (
|
|
* FormatVariables *cur_vars, int seg_type,
|
|
* char **font_attr, int link_spec,
|
|
* int flags )
|
|
*
|
|
* Parameters:
|
|
* font_attr Specifies the list of font quarks to
|
|
* associate with the string.
|
|
* link_spec Specifies the hypertext link to associate
|
|
* with the string.
|
|
* flags Specifies the formatting commands allowed.
|
|
*
|
|
* Returns: 0 if successful, -1 if errors.
|
|
*
|
|
* errno Values:
|
|
*
|
|
* Purpose: Process the <LABEL> specification.
|
|
*
|
|
*****************************************************************************/
|
|
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)
|
|
{
|
|
SegList oldList = cur_vars->my_list;
|
|
|
|
/*
|
|
* is a <LABEL> command allowed?
|
|
*/
|
|
if (CCDF_NOT_ALLOW_CMD(flags, CCDF_LABEL_CMD))
|
|
return -1;
|
|
|
|
/*
|
|
* can't have another <LABEL> command inside this one
|
|
*/
|
|
flags &= (~(CCDF_LABEL_CMD));
|
|
|
|
/*
|
|
* Find the end marker
|
|
*/
|
|
if (FindEndMarker (cur_vars) != 0)
|
|
return -1;
|
|
|
|
cur_vars->my_list = InitList;
|
|
if (Parse (CCDF_LABEL_CMD, NormalState, cur_vars,
|
|
seg_flags,
|
|
frmt_type,
|
|
font_attr,
|
|
link_spec,
|
|
Specials, flags,
|
|
ret_on_nl, fnt_flag) == -1)
|
|
return -1;
|
|
|
|
/*
|
|
* set the links, return the segment list and restore the old list.
|
|
*/
|
|
TerminateSegList(&(cur_vars->my_list), True);
|
|
*ret_list = cur_vars->my_list.list;
|
|
cur_vars->my_list = oldList;
|
|
|
|
/*
|
|
* Indicate that preceding space on the next text should be ignored
|
|
*/
|
|
cur_vars->last_was_space = True;
|
|
|
|
return 0;
|
|
|
|
} /* End ProcessLabelCmd */
|
|
|
|
/******************************************************************************
|
|
* Function: int ProcessFigureCmd (
|
|
* FormatVariables *cur_vars,
|
|
* char **font_attr)
|
|
*
|
|
* Parameters:
|
|
* font_attr Specifies the list of font quarks to
|
|
* associate with the string.
|
|
*
|
|
* Returns: 0 if successful, -1 if errors.
|
|
*
|
|
* errno Values:
|
|
*
|
|
* Purpose: Process the <FIGURE> specification.
|
|
*
|
|
*****************************************************************************/
|
|
static int
|
|
ProcessFigureCmd(
|
|
FormatVariables *cur_vars,
|
|
ProcessState cur_state,
|
|
_DtCvFrmtOption frmt_type,
|
|
_DtHelpFontHints *font_attr,
|
|
int ret_on_nl,
|
|
int fnt_flag)
|
|
{
|
|
int cnt;
|
|
int done = False;
|
|
int result = 0;
|
|
int linkType = CCDF_LINK_JUMP_REUSE;
|
|
int linkIndex = -1;
|
|
int segType = _DtCvREGION;
|
|
char *description = NULL;
|
|
char *idString = NULL;
|
|
char *filename = NULL;
|
|
char *linkspec = NULL;
|
|
_DtCvFrmtOption vertOrientCap = _DtCvJUSTIFY_BOTTOM;
|
|
_DtCvFrmtOption horzOrientCap = _DtCvJUSTIFY_CENTER;
|
|
_DtCvFrmtOption justifyCap = _DtCvJUSTIFY_CENTER;
|
|
_DtCvFrmtOption justifyGraphic = _DtCvJUSTIFY_CENTER;
|
|
_DtCvSegment *figContainer;
|
|
SegList oldList;
|
|
SegList capList;
|
|
SegList figList = InitList;
|
|
|
|
/*
|
|
* create a container for this figure (and possibly a caption)
|
|
*/
|
|
if (-1 == CheckSegList(cur_vars))
|
|
return -1;
|
|
|
|
figContainer = NextAvailSeg(cur_vars->my_list);
|
|
figContainer->handle.container = DefContainer;
|
|
figContainer->type = _DtCvSetTypeToContainer(figContainer->type);
|
|
_DtCvContainerLeadingOfSeg(figContainer) = cur_vars->ui_info->leading;
|
|
|
|
/*
|
|
* remember the old list and initialize for the figure.
|
|
*/
|
|
oldList = cur_vars->my_list;
|
|
cur_vars->my_list = InitList;
|
|
|
|
/*
|
|
* process the parameters of the figure cmd.
|
|
*/
|
|
while (!done && result != -1)
|
|
{
|
|
if (SkipToNextToken (cur_vars, _DtCvFALSE) == -1)
|
|
{
|
|
result = -1;
|
|
continue;
|
|
}
|
|
|
|
switch (_DtCvToLower(*(cur_vars->rd_ptr)))
|
|
{
|
|
/*
|
|
* end of figure spec
|
|
*/
|
|
case '>':
|
|
/*
|
|
* move past the end of token marker
|
|
* and skip the leading blanks in the caption.
|
|
*/
|
|
(cur_vars->rd_ptr)++;
|
|
while (result != -1 && !done)
|
|
{
|
|
if (*(cur_vars->rd_ptr) == '\0')
|
|
result = GetNextBuffer (cur_vars);
|
|
else if ((cur_vars->cur_mb_max == 1 ||
|
|
mblen(cur_vars->rd_ptr, cur_vars->cur_mb_max) == 1)
|
|
&& *(cur_vars->rd_ptr) == ' ')
|
|
(cur_vars->rd_ptr)++;
|
|
else
|
|
done = True;
|
|
}
|
|
break;
|
|
|
|
/*
|
|
* ccenter
|
|
* center
|
|
* cbottom
|
|
* cleft
|
|
* cright
|
|
* ctop
|
|
*/
|
|
case 'c':
|
|
/*
|
|
* Go to the next character.
|
|
*/
|
|
(cur_vars->rd_ptr)++;
|
|
|
|
/*
|
|
* Do we need to read more information?
|
|
*/
|
|
if (*(cur_vars->rd_ptr) == '\0' && GetNextBuffer (cur_vars) == -1)
|
|
result = -1;
|
|
|
|
if (result != -1)
|
|
{
|
|
/*
|
|
* look at the next charager to determine the token.
|
|
*/
|
|
switch (_DtCvToLower(*(cur_vars->rd_ptr)))
|
|
{
|
|
case 'c': /* caption center */
|
|
justifyCap = _DtCvJUSTIFY_CENTER;
|
|
horzOrientCap = _DtCvJUSTIFY_CENTER;
|
|
break;
|
|
|
|
case 'e': /* graphic centered */
|
|
justifyGraphic = _DtCvJUSTIFY_CENTER;
|
|
break;
|
|
|
|
case 'b': /* caption below graphic */
|
|
vertOrientCap = _DtCvJUSTIFY_BOTTOM;
|
|
break;
|
|
|
|
case 'l': /* caption justified left */
|
|
justifyCap = _DtCvJUSTIFY_LEFT;
|
|
horzOrientCap = _DtCvJUSTIFY_LEFT_MARGIN;
|
|
break;
|
|
|
|
case 'r': /* caption right justified */
|
|
justifyCap = _DtCvJUSTIFY_RIGHT;
|
|
horzOrientCap = _DtCvJUSTIFY_RIGHT_MARGIN;
|
|
break;
|
|
|
|
case 't': /* caption at top */
|
|
vertOrientCap = _DtCvJUSTIFY_TOP;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
/*
|
|
* description [string | "string" | 'string']
|
|
*/
|
|
case 'd':
|
|
result = GetStringParameter (cur_vars, _DtCvTRUE, _DtCvTRUE,
|
|
_DtCvFALSE, _DtCvFALSE, &description);
|
|
break;
|
|
|
|
/*
|
|
* file
|
|
*/
|
|
case 'f':
|
|
result = GetStringParameter (cur_vars, _DtCvTRUE, _DtCvTRUE,
|
|
_DtCvFALSE, _DtCvFALSE, &filename);
|
|
break;
|
|
|
|
/*
|
|
* id string
|
|
*/
|
|
case 'i':
|
|
/*
|
|
* get the id string
|
|
*/
|
|
result = GetStringParameter (cur_vars, _DtCvTRUE, _DtCvTRUE,
|
|
_DtCvFALSE, _DtCvFALSE, &idString);
|
|
/*
|
|
* if this figure had an id associated with it, create
|
|
* marker segment for it.
|
|
*/
|
|
if (-1 != result && NULL != idString && '\0' != *idString)
|
|
{
|
|
/*
|
|
* create the marker. If there is an error, free the
|
|
* string.
|
|
*/
|
|
result = CreateMarker(cur_vars, idString);
|
|
if (-1 == result)
|
|
free (idString);
|
|
}
|
|
break;
|
|
|
|
/*
|
|
* left
|
|
* link [string | "string" | 'string']
|
|
*/
|
|
case 'l':
|
|
/*
|
|
* Go to the next character.
|
|
*/
|
|
(cur_vars->rd_ptr)++;
|
|
|
|
/*
|
|
* Do we need to read more information?
|
|
*/
|
|
if (*(cur_vars->rd_ptr) == '\0' && GetNextBuffer (cur_vars) == -1)
|
|
result = -1;
|
|
|
|
if (result != -1)
|
|
{
|
|
/*
|
|
* look at the next charager to determine the token.
|
|
*/
|
|
switch (_DtCvToLower(*(cur_vars->rd_ptr)))
|
|
{
|
|
case 'e':
|
|
justifyGraphic = _DtCvJUSTIFY_LEFT;
|
|
break;
|
|
|
|
case 'i':
|
|
segType = _DtCvSetTypeToHyperText (segType);
|
|
result = GetStringParameter (cur_vars, _DtCvTRUE,
|
|
_DtCvTRUE, _DtCvFALSE, _DtCvFALSE,
|
|
&linkspec);
|
|
break;
|
|
|
|
default:
|
|
result = -1;
|
|
}
|
|
}
|
|
break;
|
|
|
|
/*
|
|
* right
|
|
*/
|
|
case 'r':
|
|
justifyGraphic = _DtCvJUSTIFY_RIGHT;
|
|
break;
|
|
|
|
/*
|
|
* typelink value
|
|
*/
|
|
case 't':
|
|
if (GetValueParameter (cur_vars, _DtCvTRUE, &linkType) == -1)
|
|
result = -1;
|
|
else if (linkType < 0)
|
|
{
|
|
errno = CEErrorHyperType;
|
|
result = -1;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
result = -1;
|
|
}
|
|
}
|
|
|
|
if (result != -1 && (filename == NULL || strlen(filename) == 0))
|
|
result = -1;
|
|
|
|
if (result != -1)
|
|
{
|
|
/*
|
|
* check to see if the hypertext flag is set but we don't
|
|
* have a link specification.
|
|
*/
|
|
if (IsTypeHyperText(segType) && !linkspec)
|
|
{
|
|
segType = segType & ~(_DtCvHYPER_TEXT);
|
|
|
|
if (NULL != description)
|
|
free (description);
|
|
description = NULL;
|
|
}
|
|
|
|
/*
|
|
* do we still have a good hypertext?
|
|
* if so, create a link index for it.
|
|
*/
|
|
if (IsTypeHyperText(segType))
|
|
{
|
|
linkIndex = _DtLinkDbAddLink (cur_vars->my_links,
|
|
NULL,
|
|
linkspec,
|
|
ReturnLinkType(linkType, linkspec),
|
|
ReturnLinkWinHint(linkType),
|
|
description);
|
|
if (linkIndex == -1)
|
|
result = -1;
|
|
}
|
|
}
|
|
|
|
if (result != -1)
|
|
{
|
|
/*
|
|
* parse the caption. If there is a caption, we will need to
|
|
* wrap it and the figure in containers with the appropriate
|
|
* controller flags set to get the correct layout.
|
|
*/
|
|
result = Parse (CCDF_FIGURE_CMD, cur_state, cur_vars,
|
|
0, frmt_type,
|
|
font_attr, -1,
|
|
Specials,
|
|
(CCDF_NEWLINE_CMD | CCDF_LINK_CMD |
|
|
CCDF_FONT_CMD | CCDF_ID_CMD),
|
|
ret_on_nl, fnt_flag);
|
|
|
|
/*
|
|
* save the caption List.
|
|
*/
|
|
TerminateSegList(&(cur_vars->my_list), True);
|
|
capList = cur_vars->my_list;
|
|
|
|
/*
|
|
* is there a caption? If so, create two segments instead
|
|
* of one.
|
|
*/
|
|
cnt = 1;
|
|
if (-1 != result && 0 != capList.cnt)
|
|
cnt = 2;
|
|
|
|
/*
|
|
* allocate room for the figure (and caption)
|
|
*/
|
|
if (-1 != result)
|
|
result = CheckList(&figList, cnt, cnt);
|
|
|
|
if (-1 != result)
|
|
{
|
|
/*
|
|
* process any caption that was specified
|
|
*/
|
|
if (0 != capList.cnt)
|
|
{
|
|
_DtCvSegment *pSeg = figList.list;
|
|
|
|
/*
|
|
* create a controller for the caption.
|
|
*/
|
|
pSeg->type = _DtCvSetTypeToController(
|
|
_DtCvSetTypeToContainer(pSeg->type));
|
|
|
|
/*
|
|
* set its orientation and justification.
|
|
*/
|
|
_DtCvContainerOrientOfSeg(pSeg) = horzOrientCap;
|
|
_DtCvContainerVOrientOfSeg(pSeg) = vertOrientCap;
|
|
_DtCvContainerJustifyOfSeg(pSeg) = justifyCap;
|
|
_DtCvContainerBMarginOfSeg(pSeg) = 0;
|
|
|
|
/*
|
|
* attach the caption to the container.
|
|
*/
|
|
_DtCvContainerListOfSeg(pSeg) = capList.list;
|
|
|
|
/*
|
|
* indicate this segment has been used.
|
|
*/
|
|
figList.cnt++;
|
|
}
|
|
|
|
/*
|
|
* now load the graphic into the next available segment
|
|
* allocated for the figure.
|
|
*/
|
|
cur_vars->my_list = figList;
|
|
result = CreateSaveGraphic (cur_vars, segType, filename, linkIndex);
|
|
|
|
/*
|
|
* if no problems, attach the figure (and caption) to the
|
|
* wrapper container
|
|
*/
|
|
if (-1 != result)
|
|
{
|
|
/*
|
|
* set the links
|
|
*/
|
|
TerminateSegList(&(cur_vars->my_list), True);
|
|
|
|
/*
|
|
* attach the figure (and caption) to the wrapper
|
|
*/
|
|
_DtCvContainerListOfSeg(figContainer) = cur_vars->my_list.list;
|
|
|
|
/*
|
|
* set the justify to the correct value to act on the
|
|
* figure.
|
|
*/
|
|
_DtCvContainerJustifyOfSeg(figContainer) = justifyGraphic;
|
|
|
|
/*
|
|
* indicate that this segment has been used
|
|
*/
|
|
oldList.cnt++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* restore the segment list.
|
|
* and free memory.
|
|
*/
|
|
cur_vars->my_list = oldList;
|
|
free (filename);
|
|
|
|
/*
|
|
* don't free the link string or description,
|
|
* the link list owns them now.
|
|
*/
|
|
|
|
return result;
|
|
|
|
} /* End ProcessFigureCmd */
|
|
|
|
/******************************************************************************
|
|
* Function: int ProcessInLine (FormatVariables cur_vars,
|
|
* int seg_type, int link_spec )
|
|
*
|
|
* Parameters:
|
|
* seg_type Specifes the type of segment currently
|
|
* being processed.
|
|
* link_spec Specifies the hypertext link associated
|
|
* with this segment.
|
|
*
|
|
* Returns: 0 if successful, -1 if errors.
|
|
*
|
|
* errno Values:
|
|
*
|
|
* Purpose: Process a <GRAPHIC> specification.
|
|
*
|
|
*****************************************************************************/
|
|
static int
|
|
ProcessInLine(
|
|
FormatVariables *cur_vars,
|
|
int seg_type,
|
|
int link_spec )
|
|
{
|
|
int done = False;
|
|
int result = 0;
|
|
char *idString = NULL;
|
|
char *filename = NULL;
|
|
|
|
/*
|
|
* process the graphic parameters
|
|
*/
|
|
while (!done && result != -1)
|
|
{
|
|
if (SkipToNextToken (cur_vars, _DtCvFALSE) == -1)
|
|
return -1;
|
|
|
|
switch (_DtCvToLower(*(cur_vars->rd_ptr)))
|
|
{
|
|
/*
|
|
* end of in line spec
|
|
*/
|
|
case '>':
|
|
/*
|
|
* move past the end of token marker
|
|
*/
|
|
(cur_vars->rd_ptr)++;
|
|
done = True;
|
|
break;
|
|
|
|
/*
|
|
* file
|
|
*/
|
|
case 'f':
|
|
result = GetStringParameter (cur_vars, _DtCvTRUE, _DtCvTRUE,
|
|
_DtCvFALSE, _DtCvFALSE, &filename);
|
|
break;
|
|
|
|
/*
|
|
* id string
|
|
*/
|
|
case 'i':
|
|
/*
|
|
* get the id string
|
|
*/
|
|
result = GetStringParameter (cur_vars, _DtCvTRUE, _DtCvTRUE,
|
|
_DtCvFALSE, _DtCvFALSE, &idString);
|
|
/*
|
|
* if this graphic had an id associated with it, create
|
|
* marker segment for it.
|
|
*/
|
|
if (-1 != result && NULL != idString && '\0' != *idString)
|
|
{
|
|
/*
|
|
* create the marker. If there is an error, free the
|
|
* string.
|
|
*/
|
|
result = CreateMarker(cur_vars, idString);
|
|
if (-1 == result)
|
|
free (idString);
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
result = -1;
|
|
}
|
|
}
|
|
|
|
if (result != -1 && (filename == NULL || strlen(filename) == 0))
|
|
result = -1;
|
|
|
|
if (result != -1)
|
|
{
|
|
/*
|
|
* create the graphic.
|
|
*/
|
|
result = CreateSaveGraphic (cur_vars,
|
|
_DtCvSetTypeToInLine(seg_type),
|
|
filename, link_spec);
|
|
cur_vars->last_was_space = False;
|
|
}
|
|
|
|
free (filename);
|
|
|
|
return result;
|
|
|
|
} /* End ProcessInLine */
|
|
|
|
/******************************************************************************
|
|
* Function: int CheckIdString (
|
|
* FormatVariables *cur_vars, int segType,
|
|
* char **font_attr, int linkspec,
|
|
* int flags)
|
|
*
|
|
* Parameters:
|
|
* segType Specifies the type of segment currently
|
|
* being processed.
|
|
* font_attr Specifies the list of font quarks to
|
|
* associate with the string.
|
|
* linkspec Specifies the hypertext link associated
|
|
* with the segment.
|
|
* flags Specifies the formatting commands allowed.
|
|
*
|
|
* Returns: 0 if successful, -1 if errors.
|
|
*
|
|
* errno Values:
|
|
*
|
|
* Purpose: Create a marker at this location.
|
|
*
|
|
*****************************************************************************/
|
|
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)
|
|
{
|
|
int result = -1;
|
|
char *ptr = NULL;
|
|
|
|
/*
|
|
* is it legal to have a <ID> command at this point?
|
|
*/
|
|
if (CCDF_NOT_ALLOW_CMD (flags, CCDF_ID_CMD))
|
|
return -1;
|
|
|
|
/*
|
|
* get the id string
|
|
* clear out any current information in the buffer
|
|
* and make sure there is a segment available.
|
|
*/
|
|
if (-1 != GetStringParameter (cur_vars, _DtCvTRUE, _DtCvTRUE,
|
|
_DtCvFALSE, _DtCvFALSE, &ptr)
|
|
&&
|
|
-1 != CheckSaveSegment (seg_flags, font_attr, linkspec, cur_vars))
|
|
{
|
|
/*
|
|
* create the marker. If there is an error, free the
|
|
* string.
|
|
*/
|
|
result = CreateMarker(cur_vars, ptr);
|
|
if (-1 == result)
|
|
free (ptr);
|
|
|
|
/*
|
|
* find the end of the <ID> syntax
|
|
* and parse the data between the begin <ID> and </ID>.
|
|
*/
|
|
if (0 == result && -1 != FindEndMarker (cur_vars) &&
|
|
-1 != Parse (CCDF_ID_CMD, cur_state, cur_vars,
|
|
seg_flags, frmt_type,
|
|
font_attr,
|
|
linkspec,
|
|
Specials, flags,
|
|
ret_on_nl, fnt_flag))
|
|
result = 0;
|
|
}
|
|
|
|
/*
|
|
* return an error code if necessary
|
|
*/
|
|
return result;
|
|
|
|
} /* End CheckIdString */
|
|
|
|
/******************************************************************************
|
|
* Function: int Parse (int cur_cmd,
|
|
* FormatVariables *cur_vars, int segType,
|
|
* char **font_attr,
|
|
* int linkspec, int allowed)
|
|
*
|
|
* Parameters:
|
|
* cur_cmd Specifies the current formatting command
|
|
* being processed.
|
|
* parent Specifies the parent paragraph.
|
|
* segType Specifies the type of segment currently
|
|
* being processed.
|
|
* font_attr Specifies the list of font quarks to
|
|
* associate with the string.
|
|
* linkspec Specifies the hypertext link associated
|
|
* with the segment.
|
|
* allowed Specifies the formatting commands allowed.
|
|
*
|
|
* Returns:
|
|
* 1 if ran into a </> specification.
|
|
* -1 if errors.
|
|
*
|
|
* errno Values:
|
|
*
|
|
* Purpose: Parse the data.
|
|
*
|
|
*****************************************************************************/
|
|
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)
|
|
{
|
|
int charSize = 1;
|
|
int leftOver = 0;
|
|
int done = False;
|
|
int fontType = False;
|
|
int cmdType = False;
|
|
char *ptr;
|
|
|
|
while (!done)
|
|
{
|
|
if (cur_vars->cur_mb_max != 1)
|
|
charSize = mblen(cur_vars->rd_ptr, cur_vars->cur_mb_max);
|
|
|
|
if (charSize == 1)
|
|
{
|
|
/*
|
|
* check to see if a newline was the previous character.
|
|
* If so, it may need to be replaced with a space.
|
|
*/
|
|
if (cur_vars->last_was_nl == True &&
|
|
AppendSpaceToInfo(cur_vars, NULL, frmt_type) == -1)
|
|
return -1;
|
|
|
|
cur_vars->last_was_nl = False;
|
|
cur_vars->last_was_mb = False;
|
|
|
|
switch (*(cur_vars->rd_ptr))
|
|
{
|
|
case '<':
|
|
/*
|
|
* Go to the next character.
|
|
*/
|
|
(cur_vars->rd_ptr)++;
|
|
|
|
/*
|
|
* determine the cmd
|
|
*/
|
|
cmdType = _DtHelpCeGetCcdfCmd (cur_cmd, cur_vars->rd_buf,
|
|
&(cur_vars->rd_ptr),
|
|
cur_vars->my_file,
|
|
cur_vars->rd_size,
|
|
allowed);
|
|
switch (cmdType)
|
|
{
|
|
/*
|
|
* <figure>
|
|
*/
|
|
case CCDF_FIGURE_CMD:
|
|
if (CheckSaveSegment(seg_flags, font_attr,
|
|
linkspec, cur_vars) == -1
|
|
||
|
|
ProcessFigureCmd(cur_vars,
|
|
cur_state,
|
|
frmt_type,
|
|
font_attr,
|
|
ret_on_nl, fnt_flag) == -1)
|
|
return -1;
|
|
break;
|
|
|
|
/*
|
|
* <angle>
|
|
* <characterset>
|
|
* <size>
|
|
* <spacing>
|
|
* <type>
|
|
* <weight>
|
|
*/
|
|
case CCDF_FONT_CMD:
|
|
fontType = _DtHelpCeGetCcdfFontType (cur_vars->rd_ptr);
|
|
done = ChangeFont(fontType, seg_flags,
|
|
frmt_type,
|
|
font_attr , linkspec,
|
|
cur_vars,
|
|
cur_state,
|
|
allowed,
|
|
ret_on_nl,
|
|
fnt_flag);
|
|
|
|
break;
|
|
|
|
/*
|
|
* </>
|
|
*/
|
|
case CCDF_FORMAT_END:
|
|
if (CheckSaveSegment(seg_flags, font_attr,
|
|
linkspec, cur_vars) == -1 ||
|
|
FindEndMarker (cur_vars) == -1)
|
|
return -1;
|
|
|
|
return 1;
|
|
|
|
/*
|
|
* <graphic>
|
|
*/
|
|
case CCDF_GRAPHIC_CMD:
|
|
/*
|
|
* clear out any information
|
|
* in the buffer and then
|
|
* process the figure.
|
|
*/
|
|
if (CheckSaveSegment (seg_flags, font_attr,
|
|
linkspec, cur_vars) == -1
|
|
||
|
|
ProcessInLine (cur_vars, seg_flags,
|
|
linkspec) == -1)
|
|
done = -1;
|
|
break;
|
|
|
|
/*
|
|
* <id>
|
|
*/
|
|
case CCDF_ID_CMD:
|
|
done = CheckIdString (cur_vars,
|
|
cur_state,
|
|
seg_flags,
|
|
frmt_type,
|
|
font_attr,
|
|
linkspec,
|
|
allowed,
|
|
ret_on_nl, fnt_flag);
|
|
break;
|
|
|
|
/*
|
|
* <link>
|
|
*/
|
|
case CCDF_LINK_CMD:
|
|
if (CheckSaveSegment (seg_flags, font_attr,
|
|
linkspec, cur_vars) == -1
|
|
||
|
|
ProcessHypertext(cur_vars, cur_state,
|
|
seg_flags, frmt_type,
|
|
font_attr, allowed,
|
|
ret_on_nl, fnt_flag) == -1)
|
|
done = -1;
|
|
break;
|
|
|
|
/*
|
|
* <newline>
|
|
*/
|
|
case CCDF_NEWLINE_CMD:
|
|
if (SaveNewLine (cur_vars, seg_flags, font_attr,
|
|
linkspec) == -1
|
|
||
|
|
FindEndMarker (cur_vars) == -1)
|
|
done = -1;
|
|
break;
|
|
|
|
case CCDF_OCTAL_CMD:
|
|
if (AppendOctalToInfo(cur_vars,
|
|
cur_vars->rd_ptr) == -1
|
|
|| FindEndMarker (cur_vars) == -1)
|
|
done = -1;
|
|
break;
|
|
|
|
/*
|
|
* <paragraph>
|
|
*/
|
|
case CCDF_PARAGRAPH_CMD:
|
|
if (CheckSaveSegment (seg_flags, font_attr,
|
|
linkspec, cur_vars) == -1
|
|
||
|
|
ProcessParagraph(cur_vars, cur_state,
|
|
fnt_flag) == -1)
|
|
done = -1;
|
|
break;
|
|
|
|
/*
|
|
* <label>
|
|
* this should never be hit if the markup is
|
|
* correct. Processing labels is through the
|
|
* the paragraph processor now.
|
|
*/
|
|
case CCDF_LABEL_CMD:
|
|
|
|
/*
|
|
* unknown command.
|
|
*/
|
|
default:
|
|
return -1;
|
|
}
|
|
break;
|
|
|
|
case '\n':
|
|
/*
|
|
* Go to the next character
|
|
*/
|
|
(cur_vars->rd_ptr)++;
|
|
|
|
/*
|
|
* If processing a static segment, we want to
|
|
* keep the author defined end-of-lines.
|
|
*
|
|
* Otherwise, we throw them away.
|
|
*/
|
|
if (_DtCvLITERAL == frmt_type || True == ret_on_nl)
|
|
{
|
|
done = SaveStringAsSegments (cur_vars,
|
|
_DtCvSetTypeToNewLine(seg_flags),
|
|
font_attr, linkspec);
|
|
|
|
if (ret_on_nl)
|
|
return 0;
|
|
}
|
|
else if (cur_vars->last_was_space == False)
|
|
cur_vars->last_was_nl = True;
|
|
|
|
break;
|
|
|
|
case '\t':
|
|
/*
|
|
* go past this character.
|
|
*/
|
|
(cur_vars->rd_ptr)++;
|
|
|
|
/*
|
|
* append 1-8 characters on the end of the buffer.
|
|
*/
|
|
_DtHelpCeCountChars(cur_vars->fmt_buf, MB_CUR_MAX,
|
|
&leftOver);
|
|
leftOver = leftOver % 8;
|
|
ptr = ((char *) SpaceString) + leftOver;
|
|
done = _DtHelpCeAddStrToBuf (&ptr,
|
|
&(cur_vars->fmt_buf),
|
|
&(cur_vars->fmt_size),
|
|
&(cur_vars->fmt_buf_max),
|
|
(8 - leftOver),
|
|
INFO_GROW);
|
|
break;
|
|
|
|
case '\\':
|
|
/*
|
|
* The author has escaped a character.
|
|
* Increment to the escaped character.
|
|
*/
|
|
(cur_vars->rd_ptr)++;
|
|
|
|
/*
|
|
* Do we need to read more information?
|
|
*/
|
|
if (*(cur_vars->rd_ptr) == '\0' &&
|
|
GetNextBuffer (cur_vars) == -1)
|
|
return -1;
|
|
/*
|
|
* If we didn't read more information or
|
|
* was successful on the read, save the
|
|
* escaped character.
|
|
*/
|
|
done = AppendCharToInfo (cur_vars, &(cur_vars->rd_ptr));
|
|
break;
|
|
|
|
case ' ':
|
|
/*
|
|
* Put a space in the segment.
|
|
*/
|
|
done = AppendSpaceToInfo (cur_vars,
|
|
&(cur_vars->rd_ptr), frmt_type);
|
|
break;
|
|
|
|
default:
|
|
/*
|
|
* put the information in the buffer
|
|
*/
|
|
if (AppendToInfo (cur_vars, &(cur_vars->rd_ptr),
|
|
scan_string) == -1)
|
|
return -1;
|
|
}
|
|
|
|
}
|
|
else if (charSize > 1)
|
|
{
|
|
if ((cur_vars->ui_info->nl_to_space == 1 ||
|
|
(cur_vars->last_was_mb == False
|
|
&& cur_vars->last_was_nl == True))
|
|
&& AppendSpaceToInfo(cur_vars, NULL, frmt_type) == -1)
|
|
done = -1;
|
|
|
|
cur_vars->last_was_nl = False;
|
|
cur_vars->last_was_mb = True;
|
|
if (AppendToInfo (cur_vars, &(cur_vars->rd_ptr), scan_string) == -1)
|
|
return -1;
|
|
}
|
|
else if (charSize < 0)
|
|
{
|
|
/*
|
|
* we have either invalid characters or part of a multi-byte
|
|
* character. Read the next buffer for more info.
|
|
*/
|
|
leftOver = strlen (cur_vars->rd_ptr);
|
|
if (leftOver < ((int) MB_CUR_MAX))
|
|
{
|
|
if (GetNextBuffer (cur_vars) == -1)
|
|
done = -1;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* In trouble brothers and sisters. We have garbage in the
|
|
* buffer - BAIL OUT!
|
|
*/
|
|
done = -1;
|
|
}
|
|
}
|
|
if (!done && *(cur_vars->rd_ptr) == '\0')
|
|
{
|
|
/*
|
|
* We're at the end of the buffer, can we read more?
|
|
*/
|
|
if (cur_vars->rd_flag > 0 && GetNextBuffer (cur_vars) == -1)
|
|
return -1;
|
|
|
|
if (cur_vars->rd_flag == 0)
|
|
done = True;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* DO NOT MODIFY 'done' HERE
|
|
* If you do, the caller is unable to test for return value == 1!!!!
|
|
*/
|
|
if (done == -1 ||
|
|
CheckSaveSegment (seg_flags, font_attr, linkspec, cur_vars) == -1)
|
|
return -1;
|
|
|
|
return done;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Function: int ParseTitle (FormatVariables cur_vars)
|
|
*
|
|
* Parameters:
|
|
* cur_vars Specifies the current values for formatting.
|
|
*
|
|
* Returns: 0 if successful, -1 if failure.
|
|
*
|
|
* errno Values:
|
|
*
|
|
* Purpose: ParseTitle gets the data between a <TITLE> and </TITLE>
|
|
* pair; putting it in a controlling container.
|
|
*
|
|
*****************************************************************************/
|
|
static int
|
|
ParseTitle(
|
|
FormatVariables *cur_vars,
|
|
int cont_flag,
|
|
int skip_abbrev,
|
|
int fnt_flag,
|
|
_DtHelpFontHints *fontAttrs)
|
|
{
|
|
int result = -1;
|
|
SegList oldList = cur_vars->my_list;
|
|
|
|
/*
|
|
* rest the current segment list
|
|
*/
|
|
cur_vars->my_list = InitList;
|
|
|
|
/*
|
|
* check for the <TITLE> directive.
|
|
*/
|
|
if (_DtHelpCeCheckNextCcdfCmd ("ti", cur_vars->my_file, cur_vars->rd_buf,
|
|
cur_vars->rd_size, 1, &(cur_vars->rd_ptr)) != 0
|
|
|| FindEndMarker (cur_vars) != 0)
|
|
return -1;
|
|
|
|
/*
|
|
* Parse will return
|
|
* 1 when a </> is found,
|
|
* 0 if the data runs out before we finish parsing,
|
|
* -1 if errors.
|
|
*
|
|
* A return of 1 is required from Parse
|
|
*/
|
|
if (1 == Parse (CCDF_TITLE_CMD, NormalState, cur_vars,
|
|
0, _DtCvDYNAMIC,
|
|
fontAttrs, -1, Specials,
|
|
~(CCDF_TOPIC_CMD | CCDF_TITLE_CMD | CCDF_ABBREV_CMD |
|
|
CCDF_PARAGRAPH_CMD | CCDF_FIGURE_CMD | CCDF_LABEL_CMD),
|
|
False, fnt_flag))
|
|
{
|
|
/*
|
|
* skip the any abbreviation that might be there
|
|
*/
|
|
result = 0;
|
|
if (skip_abbrev)
|
|
result = _DtHelpCeSkipCcdfAbbrev (cur_vars->my_file,
|
|
cur_vars->rd_buf,
|
|
&(cur_vars->rd_ptr), cur_vars->rd_size,
|
|
cur_vars->cur_mb_max);
|
|
|
|
/*
|
|
* if we successfully skipped the abbreviation and there is
|
|
* a title - then attach the title body to the controlling
|
|
* container (and make the container a controller).
|
|
*/
|
|
if (result != -1 && cur_vars->my_list.list)
|
|
{
|
|
_DtCvSegment *list = oldList.list;
|
|
int cnt = oldList.cnt;
|
|
|
|
TerminateSegList (&(cur_vars->my_list), True);
|
|
|
|
/*
|
|
* when this segment was allocated, it was initialized
|
|
* to the correct vertical and horizontal orientation
|
|
* for a CCDF title. Simply set the type to container
|
|
* and controller to get it to act properly.
|
|
*/
|
|
if (NULL != list)
|
|
{
|
|
list[cnt].type = _DtCvSetTypeToContainer(list[cnt].type);
|
|
if (True == cont_flag)
|
|
list[cnt].type = _DtCvSetTypeToController(list[cnt].type);
|
|
|
|
/*
|
|
* attach the title body to the controller container.
|
|
*/
|
|
_DtCvContainerListOfSeg(&list[cnt]) = cur_vars->my_list.list;
|
|
|
|
/*
|
|
* and count this segment as used.
|
|
*/
|
|
oldList.cnt++;
|
|
}
|
|
/*
|
|
* otherwise, a container hasn't been created for this list.
|
|
* but we don't want to loose the information.
|
|
*/
|
|
else
|
|
oldList.list = cur_vars->my_list.list;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* restore segment usage information.
|
|
*/
|
|
cur_vars->my_list = oldList;
|
|
|
|
return result;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Function: int Format (FormatVariables cur_vars, char *id_string,
|
|
*
|
|
* Parameters:
|
|
*
|
|
* Returns:
|
|
*
|
|
* errno Values:
|
|
*
|
|
* Purpose: Format is the top entry point for formating Help Files with
|
|
* formatting information into a form understood by a display area.
|
|
* It will keep calling Parse, until the entire topic is read
|
|
* or an error occurs.
|
|
*
|
|
*****************************************************************************/
|
|
static int
|
|
Format(
|
|
FormatVariables *cur_vars,
|
|
_FrmtUiInfo *ui_info,
|
|
char *id_string,
|
|
_DtCvTopicPtr *ret_topic )
|
|
{
|
|
int cnt;
|
|
int result = 0;
|
|
int done = 0;
|
|
char *charSet = NULL;
|
|
char readBuf[BUFF_SIZE];
|
|
_DtHelpFontHints fontAttrs;
|
|
_DtCvTopicInfo *topicHandle;
|
|
SegList myList = InitList;
|
|
|
|
/*
|
|
* malloc space for the topic handle.
|
|
*/
|
|
topicHandle = (_DtCvTopicInfo *) malloc (sizeof(_DtCvTopicInfo));
|
|
if (topicHandle == NULL)
|
|
return -1;
|
|
|
|
/*
|
|
* initialize the font attributes to the default hints
|
|
*/
|
|
_DtHelpCeCopyDefFontAttrList (&fontAttrs);
|
|
|
|
/*
|
|
* set up the formatting variable structure
|
|
*/
|
|
if (InitStructure (cur_vars, ui_info, readBuf, BUFF_SIZE) == -1)
|
|
return -1;
|
|
|
|
/*
|
|
* read the first buffer's worth of the topic.
|
|
*/
|
|
cur_vars->rd_flag = _DtHelpCeReadBuf (cur_vars->my_file, cur_vars->rd_buf,
|
|
cur_vars->rd_size);
|
|
if (cur_vars->rd_flag == -1)
|
|
return -1;
|
|
|
|
/*
|
|
* The first command in the buffer MUST be the <TOPIC> command.
|
|
* It is in a one byte charset.
|
|
*/
|
|
if (_DtHelpCeGetCcdfTopicCmd (((void *) NULL), cur_vars->my_file,
|
|
cur_vars->rd_buf, &(cur_vars->rd_ptr),
|
|
cur_vars->rd_size, 1, &charSet) == -1)
|
|
return -1;
|
|
|
|
/*
|
|
* change the character set to the returned character set
|
|
* Assume that the charset is 'iso8859' if not specified.
|
|
*/
|
|
cur_vars->cur_mb_max = 1;
|
|
if (NULL != charSet)
|
|
GetMbLen(cur_vars, charSet, &(_DtHelpFontHintsLang(fontAttrs)),
|
|
&(_DtHelpFontHintsCharSet(fontAttrs)));
|
|
|
|
/*
|
|
* Remember the topic code set and MB_CUR_MAX.
|
|
*/
|
|
cur_vars->topic_char_set = _DtHelpFontHintsCharSet(fontAttrs);
|
|
cur_vars->topic_lang = _DtHelpFontHintsLang(fontAttrs);
|
|
cur_vars->topic_mb_max = cur_vars->cur_mb_max;
|
|
|
|
/*
|
|
* allocate two segments for the topic - one for the <title>
|
|
* and one for the body of the topic.
|
|
*/
|
|
if (0 != CheckList(&(cur_vars->my_list), 2, 2))
|
|
{
|
|
if (NULL != charSet)
|
|
{
|
|
free(_DtHelpFontHintsLang(fontAttrs));
|
|
free(_DtHelpFontHintsCharSet(fontAttrs));
|
|
free(charSet);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* get the title and skip the abbreviation.
|
|
*/
|
|
if (0 != ParseTitle(cur_vars, True, True, 0, &fontAttrs))
|
|
{
|
|
if (NULL != charSet)
|
|
{
|
|
free(_DtHelpFontHintsLang(fontAttrs));
|
|
free(_DtHelpFontHintsCharSet(fontAttrs));
|
|
free(charSet);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* remember this current list since we will be attaching any more
|
|
* information as a child of these segments.
|
|
*/
|
|
myList = cur_vars->my_list;
|
|
|
|
/*
|
|
* process the rest of the information
|
|
*/
|
|
while (0 == result && !done)
|
|
{
|
|
/*
|
|
* reset the segment count before processing the information
|
|
* for this paragraph
|
|
*/
|
|
cur_vars->my_list = InitList;
|
|
|
|
/*
|
|
* make sure we've got a container for this paragraph
|
|
*/
|
|
done = CheckList(&myList, 1, GROW_SIZE);
|
|
|
|
/*
|
|
* now process the information while finding paragraphs.
|
|
*/
|
|
if (0 == done)
|
|
do {
|
|
done = Parse (CCDF_PARAGRAPH_CMD, NormalState, cur_vars,
|
|
0, _DtCvDYNAMIC,
|
|
&fontAttrs, -1, Specials,
|
|
~(CCDF_TOPIC_CMD | CCDF_TITLE_CMD | CCDF_ABBREV_CMD),
|
|
False, 0);
|
|
} while (0 == done);
|
|
|
|
/*
|
|
* if no errors, attach the resulting child information to the
|
|
* paragraph container.
|
|
*/
|
|
if (done != -1)
|
|
{
|
|
/*
|
|
* clean up the last segment.
|
|
*/
|
|
if (cur_vars->my_list.list)
|
|
{
|
|
_DtCvSegment *list = NextAvailSeg(myList);
|
|
|
|
TerminateSegList (&(cur_vars->my_list), True);
|
|
|
|
/*
|
|
* make it a container.
|
|
*/
|
|
list->type = _DtCvSetTypeToContainer(list->type);
|
|
|
|
/*
|
|
* attach the information to the container
|
|
*/
|
|
_DtCvContainerListOfSeg(list) = cur_vars->my_list.list;
|
|
|
|
/*
|
|
* and count this container as used.
|
|
*/
|
|
myList.cnt++;
|
|
}
|
|
}
|
|
else
|
|
result = -1;
|
|
}
|
|
|
|
/*
|
|
* If we had errors, deallocate the memory.
|
|
*/
|
|
if (result == -1)
|
|
_DtHelpFreeSegments(myList.list, _DtCvFALSE, ui_info->destroy_region,
|
|
ui_info->client_data);
|
|
else
|
|
{
|
|
/*
|
|
* Tighten up the paragraph structures if too many allocated.
|
|
*/
|
|
if (0 != myList.cnt)
|
|
TerminateSegList (&(myList), True);
|
|
else
|
|
{
|
|
free ((char *) myList.list);
|
|
myList.list = NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* return the values, even if they are null and zero.
|
|
*/
|
|
|
|
if (id_string == NULL)
|
|
topicHandle->id_str = id_string;
|
|
else
|
|
topicHandle->id_str = strdup(id_string);
|
|
|
|
topicHandle->seg_list = myList.list;
|
|
topicHandle->mark_list = NULL;
|
|
topicHandle->link_data = cur_vars->my_links;
|
|
|
|
*ret_topic = (void *) topicHandle;
|
|
|
|
/*
|
|
* free memory
|
|
*/
|
|
if (NULL != charSet)
|
|
{
|
|
free(_DtHelpFontHintsLang(fontAttrs));
|
|
free(_DtHelpFontHintsCharSet(fontAttrs));
|
|
free(charSet);
|
|
}
|
|
|
|
if (result == -1)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Function: int FormatCCDFTitle (FormatVariables cur_vars
|
|
*
|
|
* Parameters:
|
|
* cur_vars Specifies the current values for formatting.
|
|
* id_string Specifies the id to look for or NULL.
|
|
* ret_para Returns a pointer to a list of _DtCvSegment
|
|
* structures.
|
|
* ret_num Specifies the number of structures in
|
|
* 'ret_para'.
|
|
* ret_seg Specifies the segment containing 'id_string'
|
|
* or NULL.
|
|
*
|
|
* Returns:
|
|
*
|
|
* errno Values:
|
|
*
|
|
* Purpose: Format is the top entry point for formating Help Files with
|
|
* formatting information into a form understood by a display area.
|
|
* It will keep calling Parse, until the entire topic is read
|
|
* or an error occurs.
|
|
*
|
|
*****************************************************************************/
|
|
static int
|
|
FormatCCDFTitle(
|
|
FormatVariables *cur_vars,
|
|
_DtHelpFontHints fontAttrs,
|
|
char *filename,
|
|
int offset,
|
|
int level,
|
|
int fnt_flags,
|
|
int want_abbrev)
|
|
{
|
|
char *strPtr;
|
|
char *charSet = NULL;
|
|
int result = 0;
|
|
int origCnt = cur_vars->my_list.cnt;
|
|
int len;
|
|
_DtCvSegment *titleSeg;
|
|
_DtCvSegment *list;
|
|
|
|
cur_vars->rd_buf[0] = '\0';
|
|
cur_vars->rd_ptr = cur_vars->rd_buf;
|
|
|
|
if (_DtHelpCeFileOpenAndSeek(filename, offset, -1,
|
|
&(cur_vars->my_file), NULL) != 0)
|
|
return -1;
|
|
|
|
cur_vars->rd_flag = _DtHelpCeReadBuf (cur_vars->my_file, cur_vars->rd_buf,
|
|
cur_vars->rd_size);
|
|
|
|
if (cur_vars->rd_flag == -1)
|
|
{
|
|
_DtHelpCeBufFileClose (cur_vars->my_file, True);
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* The first command in the buffer MUST be the <TOPIC> command.
|
|
* It is in a one byte charset.
|
|
*/
|
|
if (_DtHelpCeGetCcdfTopicCmd (((void *) NULL), cur_vars->my_file,
|
|
cur_vars->rd_buf, &(cur_vars->rd_ptr),
|
|
cur_vars->rd_size, 1, &charSet) == -1)
|
|
{
|
|
_DtHelpCeBufFileClose (cur_vars->my_file, True);
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* change the character set to the returned character set
|
|
* Assume that the charset is 'iso8859' if not specified.
|
|
*/
|
|
cur_vars->cur_mb_max = 1;
|
|
if (NULL != charSet)
|
|
GetMbLen(cur_vars, charSet, &(_DtHelpFontHintsLang(fontAttrs)),
|
|
&(_DtHelpFontHintsCharSet(fontAttrs)));
|
|
|
|
/*
|
|
* Remember the topic code set and MB_CUR_MAX.
|
|
*/
|
|
cur_vars->topic_char_set = _DtHelpFontHintsCharSet(fontAttrs);
|
|
cur_vars->topic_lang = _DtHelpFontHintsLang(fontAttrs);
|
|
cur_vars->topic_mb_max = cur_vars->cur_mb_max;
|
|
|
|
/*
|
|
* allocate another segment for this title.
|
|
*/
|
|
if (0 != CheckSegList(cur_vars))
|
|
{
|
|
if (NULL != charSet)
|
|
{
|
|
free(_DtHelpFontHintsLang(fontAttrs));
|
|
free(_DtHelpFontHintsCharSet(fontAttrs));
|
|
free(charSet);
|
|
}
|
|
_DtHelpCeBufFileClose(cur_vars->my_file, True);
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* set the left margin correctly.
|
|
*/
|
|
titleSeg = NextAvailSeg(cur_vars->my_list);
|
|
titleSeg->handle.container = DefContainer;
|
|
titleSeg->type = _DtCvSetTypeToContainer(titleSeg->type);
|
|
_DtCvContainerLMarginOfSeg(titleSeg) = level*2*cur_vars->ui_info->avg_char;
|
|
_DtCvContainerBMarginOfSeg(titleSeg) = 0;
|
|
_DtCvContainerTypeOfSeg(titleSeg) = _DtCvLITERAL;
|
|
_DtCvContainerLeadingOfSeg(titleSeg) = cur_vars->ui_info->leading;
|
|
|
|
/*
|
|
* Parse the title.
|
|
*/
|
|
if (-1 == ParseTitle(cur_vars, False, False, fnt_flags, &fontAttrs))
|
|
{
|
|
if (NULL != charSet)
|
|
{
|
|
free(_DtHelpFontHintsLang(fontAttrs));
|
|
free(_DtHelpFontHintsCharSet(fontAttrs));
|
|
free(charSet);
|
|
}
|
|
_DtHelpCeBufFileClose(cur_vars->my_file, True);
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* We've parsed the title. see if we want the abbrev.
|
|
*/
|
|
/*
|
|
* if the title is null or we want the abbrev,
|
|
* process the abbreviation.
|
|
*/
|
|
if (NULL == _DtCvContainerListOfSeg(titleSeg) || want_abbrev)
|
|
{
|
|
SegList titleList = cur_vars->my_list;
|
|
|
|
/*
|
|
* reset the buffer to get the abbreviation
|
|
*/
|
|
if (cur_vars->fmt_buf != NULL)
|
|
{
|
|
free(cur_vars->fmt_buf);
|
|
cur_vars->fmt_buf = NULL;
|
|
cur_vars->fmt_size = 0;
|
|
cur_vars->fmt_buf_max = 0;
|
|
}
|
|
|
|
result = _DtHelpCeGetCcdfAbbrevCmd (cur_vars->my_file, cur_vars->rd_buf,
|
|
cur_vars->rd_size, cur_vars->cur_mb_max,
|
|
&(cur_vars->rd_ptr), &(cur_vars->fmt_buf));
|
|
|
|
/*
|
|
* If no errors getting the abbreviation, save it
|
|
*/
|
|
if (result != -1)
|
|
{
|
|
/*
|
|
* save the abbreviation
|
|
*/
|
|
if (cur_vars->fmt_buf != NULL)
|
|
{
|
|
/*
|
|
* If there was a title, free it
|
|
*/
|
|
if (NULL != _DtCvContainerListOfSeg(titleSeg))
|
|
_DtHelpFreeSegments(_DtCvContainerListOfSeg(titleSeg),
|
|
_DtCvFALSE,
|
|
cur_vars->ui_info->destroy_region,
|
|
cur_vars->ui_info->client_data);
|
|
|
|
/*
|
|
* save the abbreviation
|
|
*/
|
|
cur_vars->my_list = InitList;
|
|
cur_vars->fmt_size = strlen (cur_vars->fmt_buf);
|
|
cur_vars->fmt_buf_max = cur_vars->fmt_size + 1;
|
|
if (cur_vars->fmt_size > 0)
|
|
result = SaveStringAsSegments (cur_vars, 0, &fontAttrs, -1);
|
|
|
|
if (result != -1)
|
|
TerminateSegList(&(cur_vars->my_list), True);
|
|
|
|
titleSeg->type = _DtCvSetTypeToContainer(titleSeg->type);
|
|
_DtCvContainerListOfSeg(titleSeg) = cur_vars->my_list.list;
|
|
titleList.cnt++;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* eliminate this segment if no title or abbrev was found.
|
|
*/
|
|
if (NULL == _DtCvContainerListOfSeg(titleSeg))
|
|
{
|
|
titleList.cnt = origCnt;
|
|
_DtCvContainerTypeOfSeg(titleSeg) = _DtCvDYNAMIC;
|
|
}
|
|
|
|
/*
|
|
* reset the title list
|
|
*/
|
|
cur_vars->my_list = titleList;
|
|
}
|
|
else
|
|
result = _DtHelpCeSkipCcdfAbbrev (cur_vars->my_file, cur_vars->rd_buf,
|
|
&(cur_vars->rd_ptr), cur_vars->rd_size,
|
|
cur_vars->cur_mb_max);
|
|
|
|
if (cur_vars->fmt_buf != NULL)
|
|
cur_vars->fmt_buf[0] = '\0';
|
|
cur_vars->fmt_size = 0;
|
|
|
|
/*
|
|
* remove the newline from the lists and
|
|
* change all the newlines on the segments into a space.
|
|
*/
|
|
for (list = _DtCvContainerListOfSeg(titleSeg);
|
|
NULL != list; list = list->next_seg)
|
|
{
|
|
if (_DtCvIsSegNewLine(list))
|
|
{
|
|
/*
|
|
* clear the newline flag.
|
|
*/
|
|
list->type &= ~(_DtCvNEW_LINE);
|
|
|
|
/*
|
|
* check to see if the last character of this segment or
|
|
* the first character of the next segment is a space.
|
|
* if not, add one.
|
|
*/
|
|
if (NULL != list->next_disp && _DtCvIsSegString(list)
|
|
&& _DtCvIsSegRegChar(list))
|
|
{
|
|
/*
|
|
* is the last character of the string a space?
|
|
* if so do nothing.
|
|
*/
|
|
len = strlen((char *) _DtCvStringOfStringSeg(list)) - 1;
|
|
if (' ' != ((char *) _DtCvStringOfStringSeg(list))[len])
|
|
{
|
|
/*
|
|
* is the next segment a one byte string?
|
|
* and if so, is the first character a space?
|
|
* if so, do nothing.
|
|
*/
|
|
if (_DtCvIsSegString(list->next_disp)
|
|
&& _DtCvIsSegRegChar(list->next_disp)
|
|
&& ' ' != *((char *)_DtCvStringOfStringSeg(list->next_disp)))
|
|
{
|
|
/*
|
|
* need to add a space to one of these strings.
|
|
*/
|
|
len += 3;
|
|
_DtCvStringOfStringSeg(list) = (char *) realloc(
|
|
(void *) _DtCvStringOfStringSeg(list),
|
|
sizeof(char *) * len);
|
|
if (NULL == _DtCvStringOfStringSeg(list))
|
|
return -1;
|
|
|
|
strPtr = (char *) _DtCvStrPtr(
|
|
_DtCvStringOfStringSeg(list),
|
|
0,
|
|
len - 3);
|
|
*strPtr++ = ' ';
|
|
*strPtr = '\0';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
_DtHelpCeBufFileClose (cur_vars->my_file, True);
|
|
|
|
/*
|
|
* free memory
|
|
*/
|
|
if (NULL != charSet)
|
|
{
|
|
free(_DtHelpFontHintsLang(fontAttrs));
|
|
free(_DtHelpFontHintsCharSet(fontAttrs));
|
|
free(charSet);
|
|
}
|
|
|
|
if (result == -1)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Function: int FormatEntryInToc (
|
|
*
|
|
* Parameters:
|
|
*
|
|
* Returns: 0 if successful, -1 if errors
|
|
*
|
|
* errno Values:
|
|
*
|
|
* Purpose:
|
|
*
|
|
******************************************************************************/
|
|
static int
|
|
FormatEntryInToc(
|
|
_DtHelpVolumeHdl volume,
|
|
char *loc_id,
|
|
FormatVariables *cur_vars,
|
|
_DtHelpFontHints font_attrs,
|
|
int level)
|
|
{
|
|
int result = -1;
|
|
int tocLen = 0;
|
|
int offset;
|
|
int num;
|
|
char *strPtr = NULL;
|
|
_DtCvSegment *pSeg;
|
|
_DtCvSegment *titleSeg;
|
|
SegList titleList;
|
|
|
|
/*
|
|
* check to see that there is a segment for this title.
|
|
*/
|
|
if (0 != CheckSegList(cur_vars))
|
|
return -1;
|
|
|
|
/*
|
|
* The next segment in the list will become the next title.
|
|
* Get a pointer to it for later use.
|
|
*/
|
|
titleList = cur_vars->my_list;
|
|
titleSeg = NextAvailSeg(titleList);
|
|
titleSeg->handle.container = DefContainer;
|
|
titleSeg->type = _DtCvSetTypeToContainer(titleSeg->type);
|
|
_DtCvContainerBMarginOfSeg(titleSeg) = 0;
|
|
_DtCvContainerLeadingOfSeg(titleSeg) = cur_vars->ui_info->leading;
|
|
|
|
/*
|
|
* Get the file and offset for the topic.
|
|
* and process the topic's title, ignoring most font changes.
|
|
*/
|
|
if (True == _DtHelpCeFindId(volume, loc_id, -1, &strPtr, &offset) &&
|
|
-1 != FormatCCDFTitle(cur_vars, font_attrs, strPtr, offset, level,
|
|
((1<<_CEFONT_SIZE)|(1<<_CEFONT_WEIGHT)|(1<<_CEFONT_ANGLE)|(1<<_CEFONT_TYPE)),
|
|
False))
|
|
{
|
|
/*
|
|
* now create the hypertext link index for the ghostlink.
|
|
*/
|
|
num = _DtLinkDbAddLink(cur_vars->my_links, NULL, loc_id,
|
|
_DtCvLinkType_SameVolume,
|
|
_DtCvWindowHint_CurrentWindow,
|
|
NULL);
|
|
/*
|
|
* if a link index was successfully created, process the item.
|
|
*/
|
|
if (num != -1)
|
|
{
|
|
result = 0;
|
|
|
|
/*
|
|
* check to see if this title had any segments.
|
|
*/
|
|
pSeg = _DtCvContainerListOfSeg(titleSeg);
|
|
if (NULL != pSeg)
|
|
{
|
|
while (NULL != pSeg)
|
|
{
|
|
/*
|
|
* If this segment has a hypertext link, remove it.
|
|
*/
|
|
if (pSeg->link_idx != -1)
|
|
_DtLinkDbRemoveLink(cur_vars->my_links, pSeg->link_idx);
|
|
|
|
/*
|
|
* change the link index and flag to the ghost link.
|
|
*/
|
|
pSeg->link_idx = num;
|
|
pSeg->type &= ~(_DtCvHYPER_TEXT);
|
|
pSeg->type = _DtCvSetTypeToGhostLink(pSeg->type);
|
|
|
|
/*
|
|
* go to the next segment.
|
|
*/
|
|
pSeg = pSeg->next_seg;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* no title or abbreviation, so use the location id.
|
|
* allocate room for it and put it between parens.
|
|
*/
|
|
tocLen = strlen (loc_id) + 9;
|
|
if (tocLen > cur_vars->fmt_buf_max)
|
|
{
|
|
if (NULL == cur_vars->fmt_buf)
|
|
cur_vars->fmt_buf = (char *) malloc (tocLen);
|
|
else
|
|
cur_vars->fmt_buf = (char *) realloc(
|
|
cur_vars->fmt_buf,
|
|
tocLen);
|
|
cur_vars->fmt_buf_max = tocLen;
|
|
}
|
|
|
|
cur_vars->fmt_size = tocLen - 1;
|
|
strcpy (cur_vars->fmt_buf, "...(");
|
|
strcat (cur_vars->fmt_buf, loc_id);
|
|
strcat (cur_vars->fmt_buf, ")...");
|
|
|
|
/*
|
|
* don't overwrite the title's
|
|
*/
|
|
cur_vars->my_list = InitList;
|
|
|
|
/*
|
|
* save the string off and then attach to the title
|
|
* container.
|
|
*/
|
|
result = SaveStringAsSegments(cur_vars, _DtCvGHOST_LINK,
|
|
&font_attrs, num);
|
|
if (-1 != result)
|
|
_DtCvContainerListOfSeg(titleSeg) = cur_vars->my_list.list;
|
|
|
|
/*
|
|
* restore the title list.
|
|
*/
|
|
cur_vars->my_list = titleList;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NULL != strPtr)
|
|
free(strPtr);
|
|
|
|
return result;
|
|
|
|
} /* End FormatEntryInToc */
|
|
|
|
/******************************************************************************
|
|
* Function: int FormatExpandToc (
|
|
* _DtHelpVolumeHdl volume,
|
|
*
|
|
* Purpose:
|
|
******************************************************************************/
|
|
static int
|
|
FormatExpandedToc(
|
|
_DtHelpVolumeHdl volume,
|
|
char *cur_id,
|
|
char **path_lst,
|
|
FormatVariables *cur_vars,
|
|
_DtHelpFontHints font_attrs,
|
|
int level)
|
|
{
|
|
int result = 0;
|
|
|
|
if (*path_lst != NULL)
|
|
{
|
|
font_attrs.weight = _DtHelpFontWeightMedium;
|
|
if (_DtCvStrCaseCmpLatin1(*path_lst, cur_id) == 0)
|
|
font_attrs.weight = _DtHelpFontWeightBold;
|
|
|
|
result = FormatEntryInToc(volume, *path_lst, cur_vars,
|
|
font_attrs, level);
|
|
|
|
if (result != -1)
|
|
{
|
|
char **children;
|
|
char **childLst;
|
|
int count = _DtHelpCeGetCcdfTopicChildren(volume,
|
|
*path_lst, &children);
|
|
|
|
/*
|
|
* if there are children, format them
|
|
*/
|
|
level++;
|
|
path_lst++;
|
|
childLst = children;
|
|
font_attrs.weight = _DtHelpFontWeightMedium;
|
|
while (result != -1 && count > 0)
|
|
{
|
|
/*
|
|
* found the next item in the list
|
|
*/
|
|
if (*path_lst != NULL &&
|
|
_DtCvStrCaseCmpLatin1(*path_lst, *childLst) == 0)
|
|
result = FormatExpandedToc(volume,
|
|
cur_id, path_lst,
|
|
cur_vars, font_attrs, level);
|
|
else
|
|
result = FormatEntryInToc(volume, *childLst,
|
|
cur_vars, font_attrs, level);
|
|
|
|
childLst++;
|
|
count--;
|
|
}
|
|
|
|
if (children != NULL)
|
|
_DtCvFreeArray((void **) children);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Semi-Public Functions
|
|
*
|
|
*****************************************************************************/
|
|
/******************************************************************************
|
|
* Function: VarHandle *__DtHelpCeSetUpVars (char *rd_buf, grow_size)
|
|
*
|
|
* Parameters:
|
|
*
|
|
* Returns: NULL if unsuccessful.
|
|
*
|
|
* errno Values:
|
|
*
|
|
* Purpose:
|
|
*
|
|
******************************************************************************/
|
|
VarHandle
|
|
__DtHelpCeSetUpVars(
|
|
char *lang,
|
|
char *code_set,
|
|
_FrmtUiInfo *ui_info)
|
|
{
|
|
FormatVariables *newVars;
|
|
|
|
newVars = (FormatVariables *) malloc (sizeof(FormatVariables));
|
|
*newVars = DefVars;
|
|
newVars->ui_info = ui_info;
|
|
|
|
newVars->topic_mb_max = _DtHelpCeGetMbLen(lang, code_set);
|
|
newVars->cur_mb_max = newVars->topic_mb_max;
|
|
|
|
return ((VarHandle) newVars);
|
|
|
|
} /* End __DtHelpCeSetUpVars */
|
|
|
|
/******************************************************************************
|
|
* Function: int __DtHelpCeProcessString (char *in_string, int seg_type,
|
|
* char **font_attr)
|
|
*
|
|
* Parameters:
|
|
*
|
|
* Returns: 0 if successful, -1 if errors.
|
|
*
|
|
* errno Values:
|
|
*
|
|
* Purpose:
|
|
*
|
|
******************************************************************************/
|
|
int
|
|
__DtHelpCeProcessString(
|
|
VarHandle var_handle,
|
|
BufFilePtr my_file,
|
|
_DtCvFrmtOption frmt_type,
|
|
char *scan_string,
|
|
char *in_string,
|
|
int in_size,
|
|
int fnt_flag,
|
|
int ret_on_nl,
|
|
_DtHelpFontHints *font_attr )
|
|
{
|
|
int done = 0;
|
|
FormatVariables *myVars = (FormatVariables *) var_handle;
|
|
SegList oldList = myVars->my_list;
|
|
|
|
myVars->rd_buf = in_string;
|
|
myVars->rd_size = in_size;
|
|
myVars->rd_ptr = in_string;
|
|
myVars->my_file = my_file;
|
|
|
|
if (my_file == NULL)
|
|
myVars->rd_flag = 0;
|
|
else
|
|
myVars->rd_flag = strlen(in_string);
|
|
|
|
while (!done)
|
|
{
|
|
if (True == ret_on_nl)
|
|
myVars->my_list = InitList;
|
|
|
|
done = Parse (CCDF_FONT_CMD, NormalState, myVars,
|
|
0, frmt_type,
|
|
font_attr,
|
|
-1, scan_string, (CCDF_FONT_CMD | CCDF_OCTAL_CMD), ret_on_nl,
|
|
fnt_flag);
|
|
|
|
if (done != -1 && True == ret_on_nl)
|
|
{
|
|
TerminateSegList (&(myVars->my_list), True);
|
|
if (NULL != myVars->my_list.list)
|
|
{
|
|
done = CheckList (&oldList, 1, GROW_SIZE);
|
|
if (-1 != done)
|
|
{
|
|
_DtCvSegment *newSeg = NextAvailSeg(oldList);
|
|
|
|
newSeg->type = _DtCvSetTypeToContainer(newSeg->type);
|
|
_DtCvContainerListOfSeg(newSeg) = myVars->my_list.list;
|
|
_DtCvContainerTypeOfSeg(newSeg) = _DtCvDYNAMIC;
|
|
|
|
oldList.cnt++;
|
|
|
|
TerminateSegList(&oldList, False);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (False == ret_on_nl)
|
|
oldList = myVars->my_list;
|
|
|
|
myVars->my_list = oldList;
|
|
return done;
|
|
|
|
} /* End __DtHelpCeProcessString */
|
|
|
|
/*****************************************************************************
|
|
* Function: int __DtHelpCeGetParagraphList (
|
|
*
|
|
* Parameters:
|
|
*
|
|
* Returns: 0 if successful, -1 if errors.
|
|
*
|
|
* errno Values:
|
|
*
|
|
* Purpose: _DtHelpFormatGetParagraphList places a terminator on the
|
|
* last segment in the current paragraph and returns the
|
|
* segment list included in the topic information structure.
|
|
*
|
|
* If make_cont is true, the segment list is first included
|
|
* in a container with the specified type.
|
|
*
|
|
*****************************************************************************/
|
|
int
|
|
__DtHelpCeGetParagraphList (
|
|
VarHandle var_handle,
|
|
int make_cont,
|
|
_DtCvFrmtOption type,
|
|
_DtCvTopicPtr *ret_handle)
|
|
{
|
|
int result = -1;
|
|
FormatVariables *myVars = (FormatVariables *) var_handle;
|
|
_DtCvTopicInfo *topicHandle;
|
|
|
|
/*
|
|
* check the parameters.
|
|
*/
|
|
if (ret_handle == NULL || myVars == NULL)
|
|
{
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
TerminateSegList(&(myVars->my_list), True);
|
|
|
|
topicHandle = (_DtCvTopicInfo *) malloc (sizeof(_DtCvTopicInfo));
|
|
if (topicHandle != NULL)
|
|
{
|
|
result = 0;
|
|
|
|
if (True == make_cont)
|
|
{
|
|
_DtCvSegment *myCont = AllocateSegments(NULL, 0, 1);
|
|
|
|
if (NULL != myCont)
|
|
{
|
|
myCont->type = _DtCvSetTypeToContainer(myCont->type);
|
|
_DtCvContainerTypeOfSeg(myCont) = type;
|
|
_DtCvContainerListOfSeg(myCont) = myVars->my_list.list;
|
|
|
|
myVars->my_list.list = myCont;
|
|
myVars->my_list.cnt = 1;
|
|
myVars->my_list.max = 1;
|
|
}
|
|
else
|
|
result = -1;
|
|
}
|
|
|
|
topicHandle->id_str = NULL;
|
|
topicHandle->seg_list = myVars->my_list.list;
|
|
topicHandle->mark_list = NULL;
|
|
topicHandle->link_data = myVars->my_links;
|
|
|
|
*ret_handle = (_DtCvTopicPtr) topicHandle;
|
|
}
|
|
|
|
if (myVars->fmt_buf != NULL)
|
|
free(myVars->fmt_buf);
|
|
|
|
return result;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Function: int _DtHelpCeFrmtCcdfTopic (_DtHelpVolumeHdl volume, char *filename,
|
|
* int offset, char *id_string,
|
|
* _DtCvTopicPtr *ret_handle)
|
|
*
|
|
* Parameters:
|
|
* volume Specifies the Help Volume the information
|
|
* is associated with.
|
|
* filename Specifies the file containing the Help Topic
|
|
* desired.
|
|
* offset Specifies the offset into 'filename' to
|
|
* the Help Topic desired.
|
|
* id_string Specifies the location id to look for or NULL.
|
|
* ret_handle Returns a handle to the topic information
|
|
* including the number of paragraphs and the
|
|
* id match segment.
|
|
*
|
|
* Returns: 0 if successful, -1 if errors
|
|
*
|
|
* errno Values:
|
|
*
|
|
* Purpose: _DtHelpCeFrmtCcdfTopic formats Help Files with formatting
|
|
* information into a Canvas Engine structure.
|
|
*
|
|
******************************************************************************/
|
|
int
|
|
_DtHelpCeFrmtCcdfTopic(
|
|
_DtHelpVolumeHdl volume,
|
|
char *filename,
|
|
int offset,
|
|
char *id_string,
|
|
_FrmtUiInfo *ui_info,
|
|
_DtCvTopicPtr *ret_handle )
|
|
{
|
|
int result = -1;
|
|
char *ptr;
|
|
FormatVariables variables;
|
|
|
|
/*
|
|
* Check the parameters
|
|
*/
|
|
if (volume == NULL || filename == NULL || offset < 0 || ret_handle == NULL)
|
|
{
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* get the current file path.
|
|
*/
|
|
variables = DefVars;
|
|
variables.topic_id = id_string;
|
|
if (volume)
|
|
{
|
|
variables.vol_name = _DtHelpCeGetVolumeName(volume);
|
|
variables.my_path = strdup (variables.vol_name);
|
|
if (variables.my_path == NULL)
|
|
return -1;
|
|
|
|
result = _DtHelpCeStrrchr (variables.my_path, Slash, MB_CUR_MAX, &ptr);
|
|
if (result == -1)
|
|
ptr = strrchr (variables.my_path, '/');
|
|
|
|
if (ptr)
|
|
*ptr = '\0';
|
|
}
|
|
|
|
/*
|
|
* open the file and seek to the correct place.
|
|
*/
|
|
result = _DtHelpCeFileOpenAndSeek (filename, offset, -1,
|
|
&(variables.my_file), NULL);
|
|
if (result != -1)
|
|
{
|
|
/*
|
|
* Initialize the X variables.
|
|
*/
|
|
result = Format (&variables, ui_info, id_string, ret_handle);
|
|
|
|
_DtHelpCeBufFileClose (variables.my_file, True);
|
|
}
|
|
|
|
if (variables.fmt_buf != NULL)
|
|
free (variables.fmt_buf);
|
|
|
|
if (variables.my_path != NULL)
|
|
free (variables.my_path);
|
|
|
|
return result;
|
|
|
|
} /* End _DtHelpCeFrmtCcdfTopic */
|
|
|
|
/******************************************************************************
|
|
* Function: int _DtHelpCeFrmtCcdfPathAndChildren (
|
|
* _DtHelpVolumeHdl volume,
|
|
* _DtCvTopicPtr *ret_handle)
|
|
*
|
|
* Parameters:
|
|
* ret_handle Returns a handle to the topic information
|
|
* including the number of paragraphs and the
|
|
* id match segment.
|
|
*
|
|
* Returns: 0 if successful, -1 if errors, 1 if there the path is empty.
|
|
*
|
|
* errno Values:
|
|
*
|
|
* Purpose: _DtHelpCeFormatCcdfToc formats Table of Contents for
|
|
* a CCDF Help File.
|
|
*
|
|
******************************************************************************/
|
|
int
|
|
_DtHelpCeFrmtCcdfPathAndChildren(
|
|
_DtHelpVolumeHdl volume,
|
|
char *loc_id,
|
|
_FrmtUiInfo *ui_info,
|
|
_DtCvTopicPtr *ret_handle )
|
|
{
|
|
int result = 0;
|
|
int pathCnt;
|
|
char *ptr;
|
|
char **pathHead;
|
|
char readBuf[BUFF_SIZE];
|
|
FormatVariables myVars;
|
|
_DtHelpFontHints fontAttrs;
|
|
|
|
_DtHelpCeCopyDefFontAttrList (&fontAttrs);
|
|
fontAttrs.pointsz = 10;
|
|
fontAttrs.weight = _DtHelpFontWeightMedium;
|
|
fontAttrs.style = _DtHelpFontStyleSanSerif;
|
|
|
|
/*
|
|
* Check the parameters
|
|
*/
|
|
if (volume == NULL || ret_handle == NULL)
|
|
{
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
readBuf[0] = '\0';
|
|
myVars = DefVars;
|
|
if (InitStructure (&myVars, ui_info, readBuf, BUFF_SIZE) == -1)
|
|
return -1;
|
|
|
|
/*
|
|
* get the list of topics in the volume.
|
|
*/
|
|
pathCnt = _DtHelpCeGetCcdfIdPath(volume, loc_id, &pathHead);
|
|
if (pathCnt == -1)
|
|
return -1;
|
|
|
|
/*
|
|
* Check to see if this topic is in the topic list.
|
|
* I.e. if a count of 1 is returned this should match the
|
|
* top topic, otherwise this is an hidden topic.
|
|
*/
|
|
if (pathCnt == 1)
|
|
{
|
|
if (_DtHelpCeGetCcdfTopTopic(volume, &ptr) == -1)
|
|
result = -1;
|
|
else if (_DtCvStrCaseCmpLatin1(ptr, *pathHead) != 0)
|
|
result = 1;
|
|
}
|
|
|
|
/*
|
|
* if result is non-zero, we had problems or this is a hidden topic
|
|
*/
|
|
if (result == 0)
|
|
{
|
|
fontAttrs.slant = _DtHelpFontSlantRoman;
|
|
|
|
myVars.topic_id = loc_id;
|
|
myVars.vol_name = _DtHelpCeGetVolumeName(volume);
|
|
myVars.my_path = strdup (myVars.vol_name);
|
|
if (myVars.my_path == NULL)
|
|
return -1;
|
|
|
|
if (-1 == _DtHelpCeStrrchr (myVars.my_path, Slash, MB_CUR_MAX, &ptr))
|
|
ptr = strrchr (myVars.my_path, '/');
|
|
|
|
if (ptr)
|
|
*ptr = '\0';
|
|
|
|
result = FormatExpandedToc(volume, loc_id, pathHead,
|
|
&myVars, fontAttrs, 0);
|
|
_DtCvFreeArray((void **) pathHead);
|
|
}
|
|
|
|
if (result != -1)
|
|
result = __DtHelpCeGetParagraphList (&myVars, False, _DtCvDYNAMIC,
|
|
ret_handle);
|
|
|
|
/*
|
|
* check for an empty path.
|
|
*/
|
|
if (-1 != result && NULL == ((_DtCvTopicInfo *) *ret_handle)->seg_list)
|
|
result = 1;
|
|
|
|
if (myVars.my_path != NULL)
|
|
free(myVars.my_path);
|
|
|
|
return result;
|
|
|
|
} /* End _DtHelpCeFrmtCcdfPathAndChildren */
|
|
|
|
/******************************************************************************
|
|
* Function: int _DtHelpCeGetCcdfTitleChunks (
|
|
* _DtHelpVolumeHdl volume,
|
|
* _DtCvTopicPtr *ret_handle)
|
|
*
|
|
* Parameters:
|
|
* ret_handle Returns a handle to the topic information
|
|
* including the number of paragraphs and the
|
|
* id match segment.
|
|
*
|
|
* Returns: 0 if successful, -1 if errors
|
|
*
|
|
* errno Values:
|
|
*
|
|
* Purpose: _DtHelpCeFormatCcdfToc formats Table of Contents for
|
|
* a CCDF Help File.
|
|
*
|
|
******************************************************************************/
|
|
int
|
|
_DtHelpCeGetCcdfTitleChunks(
|
|
_DtHelpVolumeHdl volume,
|
|
char *loc_id,
|
|
_FrmtUiInfo *ui_info,
|
|
void ***ret_chunks)
|
|
{
|
|
int type = 0;
|
|
int result = 0;
|
|
int offset;
|
|
char *fileName;
|
|
char *ptr;
|
|
char readBuf[BUFF_SIZE];
|
|
_DtCvSegment *titleSeg;
|
|
_DtCvSegment *list = NULL;
|
|
FormatVariables myVars;
|
|
_DtHelpFontHints fontAttrs;
|
|
_DtHelpCeLockInfo lockInfo;
|
|
|
|
/*
|
|
* Check the parameters
|
|
*/
|
|
if (volume == NULL || ret_chunks == NULL)
|
|
{
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* init the return value
|
|
*/
|
|
*ret_chunks = NULL;
|
|
|
|
/*
|
|
* get the topic in the volume.
|
|
*/
|
|
if (_DtHelpCeLockVolume(volume, &lockInfo) != 0)
|
|
return -1;
|
|
|
|
if (_DtHelpCeFindId(volume, loc_id, -1, &fileName, &offset) == False)
|
|
{
|
|
_DtHelpCeUnlockVolume(lockInfo);
|
|
return -1;
|
|
}
|
|
|
|
_DtHelpCeCopyDefFontAttrList (&fontAttrs);
|
|
myVars = DefVars;
|
|
if (InitStructure (&myVars, ui_info, readBuf, BUFF_SIZE) == -1)
|
|
{
|
|
_DtHelpCeUnlockVolume(lockInfo);
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* initialize my variables.
|
|
*/
|
|
myVars.topic_id = loc_id;
|
|
myVars.vol_name = _DtHelpCeGetVolumeName(volume);
|
|
myVars.my_path = strdup (myVars.vol_name);
|
|
if (myVars.my_path == NULL)
|
|
{
|
|
_DtHelpCeUnlockVolume(lockInfo);
|
|
return -1;
|
|
}
|
|
|
|
if (-1 == _DtHelpCeStrrchr (myVars.my_path, Slash, MB_CUR_MAX, &ptr))
|
|
ptr = strrchr (myVars.my_path, '/');
|
|
|
|
if (ptr)
|
|
*ptr = '\0';
|
|
|
|
result = FormatCCDFTitle(&myVars, fontAttrs, fileName,
|
|
offset, 0, (1 << _CEFONT_SIZE), True);
|
|
free(fileName);
|
|
|
|
if (-1 != result && 0 < myVars.my_list.cnt)
|
|
{
|
|
titleSeg = &(myVars.my_list.list[myVars.my_list.cnt - 1]);
|
|
list = _DtCvContainerListOfSeg(titleSeg);
|
|
}
|
|
|
|
if (result != -1 && NULL != list)
|
|
{
|
|
_DtCvSegment *pSeg = list;
|
|
|
|
while (-1 != result && NULL != pSeg)
|
|
{
|
|
/*
|
|
* create the types and add the informatio to the array.
|
|
*/
|
|
type = DT_HELP_CE_FONT_PTR | DT_HELP_CE_STRING;
|
|
if (_DtCvIsSegNewLine(pSeg))
|
|
type |= DT_HELP_CE_NEWLINE;
|
|
|
|
if (_DtCvIsSegString(pSeg))
|
|
{
|
|
*ret_chunks = (void **) _DtCvAddPtrToArray(*ret_chunks,
|
|
(void *) type);
|
|
if (NULL != *ret_chunks)
|
|
*ret_chunks = (void **) _DtCvAddPtrToArray(*ret_chunks,
|
|
(void *) _DtCvFontOfStringSeg(pSeg));
|
|
|
|
if (NULL != *ret_chunks)
|
|
{
|
|
if (_DtCvIsSegWideChar(pSeg))
|
|
{
|
|
offset = _DtCvStrLen(_DtCvStringOfStringSeg(pSeg), 1)
|
|
* MB_CUR_MAX + 1;
|
|
ptr = (char *) malloc (sizeof(char) * offset);
|
|
if (NULL != ptr)
|
|
wcstombs(ptr,
|
|
(wchar_t *)_DtCvStringOfStringSeg(pSeg),
|
|
offset);
|
|
}
|
|
else
|
|
ptr = strdup((char *) _DtCvStringOfStringSeg(pSeg));
|
|
|
|
if (NULL != ptr)
|
|
*ret_chunks = (void **)_DtCvAddPtrToArray(
|
|
*ret_chunks, (void *) ptr);
|
|
}
|
|
|
|
if (NULL == *ret_chunks || NULL == ptr)
|
|
result = -1;
|
|
}
|
|
|
|
/*
|
|
* go to the next segment
|
|
*/
|
|
pSeg = pSeg->next_seg;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
char buf[128];
|
|
char *idStr;
|
|
int idLen = strlen (loc_id) + 9;
|
|
|
|
/*
|
|
* create the location id string.
|
|
*/
|
|
idStr = (char *) malloc (idLen);
|
|
if (NULL != idStr)
|
|
{
|
|
/*
|
|
* format the location id
|
|
*/
|
|
strcpy (idStr, "...(");
|
|
strcat (idStr, loc_id);
|
|
strcat (idStr, ")...");
|
|
|
|
/*
|
|
* format the language and codeset
|
|
*/
|
|
strcpy(buf, _DtHelpFontHintsLang(fontAttrs));
|
|
strcat(buf, ".");
|
|
strcpy(buf, _DtHelpFontHintsCharSet(fontAttrs));
|
|
|
|
/*
|
|
* creat a chunk table
|
|
*/
|
|
*ret_chunks = (void **) _DtCvAddPtrToArray(*ret_chunks,
|
|
(void *) (DT_HELP_CE_CHARSET | DT_HELP_CE_STRING));
|
|
if (NULL != *ret_chunks)
|
|
*ret_chunks = (void **) _DtCvAddPtrToArray(*ret_chunks,
|
|
(void *) strdup(buf));
|
|
if (NULL != *ret_chunks)
|
|
*ret_chunks = (void **) _DtCvAddPtrToArray(*ret_chunks,
|
|
(void *) idStr);
|
|
}
|
|
}
|
|
|
|
if (NULL != *ret_chunks)
|
|
*ret_chunks = (void **) _DtCvAddPtrToArray(*ret_chunks,
|
|
(void *) DT_HELP_CE_END);
|
|
|
|
/*
|
|
* free the list
|
|
*/
|
|
if (0 < myVars.my_list.cnt)
|
|
_DtHelpFreeSegments(myVars.my_list.list, _DtCvFALSE,
|
|
ui_info->destroy_region,
|
|
ui_info->client_data);
|
|
|
|
/*
|
|
* free the link database
|
|
*/
|
|
_DtLinkDbDestroy(myVars.my_links);
|
|
|
|
/*
|
|
* free memory
|
|
*/
|
|
if (myVars.my_path != NULL)
|
|
free(myVars.my_path);
|
|
if (myVars.fmt_buf != NULL)
|
|
free(myVars.fmt_buf);
|
|
|
|
_DtHelpCeUnlockVolume(lockInfo);
|
|
|
|
/*
|
|
* indicate an error if problems.
|
|
*/
|
|
result = 0;
|
|
if (NULL == *ret_chunks)
|
|
result = -1;
|
|
|
|
return result;
|
|
|
|
} /* End _DtHelpCeGetCcdfTitleChunks */
|
|
|
|
/******************************************************************************
|
|
* Function: int _DtHelpCeGetCcdfVolTitleChunks (
|
|
* _DtHelpVolumeHdl volume,
|
|
* void ***ret_chunks)
|
|
*
|
|
* Parameters:
|
|
* ret_chunks Returns a ptr to the title information chunks
|
|
* The title chunks are stored in allocated memory
|
|
* that is owned by the caller and should be
|
|
* freed when no longer needed.
|
|
* id match segment.
|
|
*
|
|
* Returns: 0 if successful, -1 if errors
|
|
*
|
|
* errno Values:
|
|
*
|
|
* Purpose: _DtHelpCeFormatCcdfVolTitleChunks formats volume title for
|
|
* a CCDF Help File.
|
|
*
|
|
******************************************************************************/
|
|
int
|
|
_DtHelpCeGetCcdfVolTitleChunks(
|
|
_DtHelpVolumeHdl volume,
|
|
_FrmtUiInfo *ui_info,
|
|
void ***ret_chunks)
|
|
{
|
|
char *charSet;
|
|
char *titleStr;
|
|
|
|
/*
|
|
* get the title of the volume (we own the memory).
|
|
*/
|
|
charSet = _DtHelpCeGetCcdfVolLocale(volume);
|
|
if (charSet == NULL)
|
|
charSet = strdup("C.ISO-8859-1");
|
|
|
|
titleStr = _DtHelpCeGetCcdfVolTitle(volume);
|
|
if (titleStr != NULL)
|
|
{
|
|
*ret_chunks = (void **) malloc(sizeof(void *) * 4);
|
|
if (*ret_chunks == NULL)
|
|
return -1;
|
|
|
|
(*ret_chunks)[0] = (void *) (DT_HELP_CE_CHARSET | DT_HELP_CE_STRING);
|
|
(*ret_chunks)[1] = (void *) strdup(charSet);
|
|
(*ret_chunks)[2] = (void *) strdup(titleStr);
|
|
(*ret_chunks)[3] = (void *) DT_HELP_CE_END;
|
|
}
|
|
else
|
|
{
|
|
free(charSet);
|
|
if (_DtHelpCeGetCcdfTitleChunks(volume, "_title",
|
|
ui_info, ret_chunks) != 0
|
|
&&
|
|
_DtHelpCeGetCcdfTitleChunks(volume, "_hometopic",
|
|
ui_info, ret_chunks) != 0)
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
|
|
} /* End _DtHelpCeGetCcdfVolTitleChunks */
|