cdesktopenv/cde/lib/DtHelp/FormatTerm.c

1546 lines
41 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: FormatTerm.c /main/14 1997/08/07 10:52:34 samborn $ */
/************************************<+>*************************************
****************************************************************************
**
** File: FormatTerm.c
**
** Project: CDE Help System
**
** Description: This code uses the core engine functionality of the
** the help system to get topics into a form understood
** by ASCII based applications.
**
** (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 <stdio.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <X11/Xos.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 "LinkMgrI.h"
#include "HelpTermP.h"
#include "HelpP.h"
#include "HelpI.h"
#include "bufioI.h"
#include "AsciiSpcI.h"
#include "Access.h"
#include "AccessI.h"
#include "CanvasI.h"
#include "CleanUpI.h"
#include "HelpErrorP.h"
#include "FileUtilsI.h"
#include "FontAttrI.h"
#include "StringFuncsI.h"
#include "SDLI.h"
#include "FormatUtilI.h"
#include "FormatSDLI.h"
#include "FormatCCDFI.h"
#include "Lock.h"
#ifdef NLS16
#endif
/******** Private Function Declarations ********/
static void TermMetrics(
_DtCvPointer client_data,
_DtCvElemType elem_type,
_DtCvPointer ret_metrics);
static _DtCvUnit TermStrWidth(
_DtCvPointer client_data,
_DtCvElemType elem_type,
_DtCvPointer data);
static void TermStrDraw(
_DtCvPointer client_data,
_DtCvUnit x,
_DtCvUnit y,
const void *string,
int byte_len,
int wc,
_DtCvPointer font_ptr,
_DtCvUnit box_x,
_DtCvUnit box_y,
_DtCvUnit box_height,
int link_type,
_DtCvFlags old_flags,
_DtCvFlags new_flags );
#ifdef XTAG
static _DtCvStatus TermFindGraphic(
_DtCvPointer client_data,
char *vol_xid,
char *topic_xid,
char *file_xid,
char *format,
char *method,
_DtCvUnit *ret_width,
_DtCvUnit *ret_height,
_DtCvPointer *ret_graphic);
#endif
static void TermGetFont(
_DtCvPointer client_data,
char *lang,
char *charset,
_DtHelpFontHints font_attr,
_DtCvPointer *ret_font );
static void TermFontMetrics(
_DtCvPointer client_data,
_DtCvPointer font_ptr,
_DtCvUnit *ret_ascent,
_DtCvUnit *ret_descent,
_DtCvUnit *char_width,
_DtCvUnit *ret_super,
_DtCvUnit *ret_sub);
static _DtCvStatus TermResolveSpc(
_DtCvPointer client_data,
char *lang,
char *charset,
_DtHelpFontHints font_attr,
char *spc_symbol,
_DtCvPointer *ret_handle,
_DtCvUnit *ret_width,
_DtCvUnit *ret_height,
_DtCvUnit *ret_ascent);
static void TermRenderElem(
_DtCvPointer client_data,
_DtCvElemType elem_type,
_DtCvUnit x,
_DtCvUnit y,
int link_type,
_DtCvFlags old_flags,
_DtCvFlags new_flags,
_DtCvElemType trav_type,
_DtCvPointer trav_data,
_DtCvPointer data );
/******** End Public Function Declarations ********/
/******************************************************************************
*
* Private variables and defines.
*
*****************************************************************************/
#define GROW_SIZE 10
#define EOS '\0'
/*
* My private values
*/
static _DtHelpVolumeHdl MyVolume = NULL;
static int HyperErr = 0;
static wchar_t WcSpace = 0;
/*
* These values change as the information is processed.
*/
typedef struct {
wchar_t **lines;
size_t *wc_num;
int max_lines;
_DtCvUnit max_columns;
_DtCvUnit max_rows;
short nl_to_space;
wchar_t *cant_begin_chars;
wchar_t *cant_end_chars;
} TerminalInfo;
/* default values */
static TerminalInfo DfltTermInfo = {NULL, NULL, 0, 1, 100000, 1, NULL, NULL};
static _DtCvVirtualInfo TermVirtInfo =
{
TermMetrics, /* void (*_DtCvGetMetrics)(); */
TermRenderElem, /* void (*_DtCvRenderElem)(); */
TermStrWidth, /* _DtCvUnit (*_DtCvGetElemWidth)(); */
TermFontMetrics, /* void (*_DtCvGetFontMetrics)(); */
NULL, /* _DtCvStatus (*_DtCvBuildSelection)(); */
NULL, /* _DtCvStatus (*_DtCvFilterExecCmd)(); */
};
static TerminalInfo MyInfo = {NULL, NULL, 0, 1, 100000, 1, NULL, NULL};
static _DtCvHandle MyCanvas = NULL;
#ifdef XTAG
int missingGraphics = 0; /* Counter used by cdewalk */
#endif /* XTAG */
/******************************************************************************
*
* Private functions
*
******************************************************************************/
/******************************************************************************
* Canvas functions
******************************************************************************/
#ifdef XTAG
/*****************************************************************************
* Function: _DtCvStatus TermFindGraphic ();
*
* Parameters:
*
* Returns:
*
* Purpose:
*
*****************************************************************************/
static _DtCvStatus
TermFindGraphic (
_DtCvPointer client_data,
char *vol_xid,
char *topic_xid,
char *file_xid,
char *format,
char *method,
_DtCvUnit *ret_width,
_DtCvUnit *ret_height,
_DtCvPointer *ret_graphic )
{
char *ptr;
char *fileName = file_xid;
if (fileName != NULL && *fileName != '/')
{
fileName = (char *) malloc (strlen(vol_xid) + strlen (file_xid) + 2);
if (fileName == NULL)
return -1;
strcpy(fileName, vol_xid);
if (_DtHelpCeStrrchr(fileName, "/", MB_CUR_MAX, &ptr) != -1)
*ptr = '\0';
strcat(fileName, "/");
strcat(fileName, file_xid);
}
if (access(fileName, R_OK) != 0)
{
missingGraphics++;
fprintf (stdout, "\tGRAPHICS LINK ***UNRESOLVED***\n");
fprintf (stdout, "\tUnable to find graphic file: %s\n\n", fileName);
}
if (fileName != file_xid)
free (fileName);
*ret_width = 0;
*ret_height = 0;
*ret_graphic = 0;
return 0;
}
#endif /* XTAG */
/*****************************************************************************
* Function: void TermStrDraw ();
*
* Parameters:
*
* Returns:
*
* Purpose:
*
*****************************************************************************/
static void
TermStrDraw (
_DtCvPointer client_data,
_DtCvUnit x,
_DtCvUnit y,
const void *string,
int byte_len,
int wc,
_DtCvPointer font_ptr,
_DtCvUnit box_x,
_DtCvUnit box_y,
_DtCvUnit box_height,
int link_type,
_DtCvFlags old_flags,
_DtCvFlags new_flags )
{
TerminalInfo *pTerm = (TerminalInfo *) client_data;
wchar_t *wcStr = pTerm->lines[y];
size_t length = 1;
length = x + byte_len;
if (wcStr == NULL)
{
pTerm->lines[y] = (wchar_t *) malloc (sizeof(wchar_t) * (length + 1));
if (pTerm->lines[y] != NULL)
{
register int i;
wcStr = pTerm->lines[y];
_DtHelpProcessLock();
for (i = 0; i < x; i++)
wcStr[i] = WcSpace;
_DtHelpProcessUnlock();
/*
* this will leave a hole that will be plugged by the next
* mbstowc call.
*/
wcStr[length] = 0;
pTerm->wc_num[y] = length;
}
}
else
{
if (length > pTerm->wc_num[y])
{
pTerm->lines[y] = (wchar_t *) realloc (wcStr,
(sizeof(wchar_t) * (length + 1)));
if (pTerm->lines[y] != NULL)
{
register int i;
wcStr = pTerm->lines[y];
_DtHelpProcessLock();
for (i = pTerm->wc_num[y]; i < x; i++)
wcStr[i] = WcSpace;
_DtHelpProcessUnlock();
wcStr[length] = 0;
pTerm->wc_num[y] = length;
}
}
}
if (0 == wc)
mbstowcs(&wcStr[x], string, byte_len);
else
{
wchar_t *wcp = (wchar_t *) string;
while (0 < byte_len)
{
wcStr[x++] = *wcp++;
byte_len--;
}
}
}
/*****************************************************************************
* Function: void TermRenderElem ();
*
* Parameters:
*
* Returns:
*
* Purpose:
*
*****************************************************************************/
static void
TermRenderElem (
_DtCvPointer client_data,
_DtCvElemType elem_type,
_DtCvUnit x,
_DtCvUnit y,
int link_type,
_DtCvFlags old_flags,
_DtCvFlags new_flags,
_DtCvElemType trav_type,
_DtCvPointer trav_data,
_DtCvPointer data)
{
_DtCvStringInfo *strInfo;
_DtCvRenderInfo *posInfo = (_DtCvRenderInfo *) data;
if (_DtCvSTRING_TYPE == elem_type)
{
strInfo = (_DtCvStringInfo *) posInfo->info;
TermStrDraw (client_data, x, y, strInfo->string, strInfo->byte_len,
strInfo->wc , strInfo->font_ptr,
posInfo->box_x , posInfo->box_y ,
posInfo->box_height, link_type,
old_flags , new_flags);
}
else if (_DtCvREGION_TYPE == elem_type)
{
const char *spcStr = (const char*) posInfo->info;
int len = spcStr ? strlen(spcStr) : 0;
TermStrDraw (client_data, x, y, spcStr, len, 0, 0,
posInfo->box_x , posInfo->box_y,
posInfo->box_height, link_type,
old_flags , new_flags);
}
}
/*****************************************************************************
* Function: void TermMetrics ();
*
* Parameters:
*
* Returns:
*
* Purpose:
*
*****************************************************************************/
static _DtCvSpaceMetrics defLinkMetrics = { 0, 0, 0, 0 };
static void
TermMetrics (
_DtCvPointer client_data,
_DtCvElemType elem_type,
_DtCvPointer ret_metrics)
{
TerminalInfo *pTerm = (TerminalInfo *) client_data;
_DtCvSpaceMetrics *retSpace = (_DtCvSpaceMetrics *) ret_metrics;
if (_DtCvCANVAS_TYPE == elem_type)
{
_DtCvMetrics *retCanvas = (_DtCvMetrics *) ret_metrics;
retCanvas->width = pTerm->max_columns;
retCanvas->height = 50;
retCanvas->top_margin = 0;
retCanvas->side_margin = 0;
retCanvas->line_height = 1;
retCanvas->horiz_pad_hint = 1;
}
else if (_DtCvLOCALE_TYPE == elem_type)
{
_DtCvLocale *retLocale = (_DtCvLocale *) ret_metrics;
retLocale->line_wrap_mode = _DtCvModeWrapNone;
retLocale->cant_begin_chars = pTerm->cant_begin_chars;
retLocale->cant_end_chars = pTerm->cant_end_chars;
}
else if (_DtCvLINK_TYPE == elem_type || _DtCvTRAVERSAL_TYPE == elem_type)
*retSpace = defLinkMetrics;
}
/*****************************************************************************
* Function: void TermGetFont ();
*
* Parameters:
*
* Returns:
*
* Purpose:
*
*****************************************************************************/
static void
TermGetFont (
_DtCvPointer client_data,
char *lang,
char *charset,
_DtHelpFontHints font_attr,
_DtCvPointer *ret_font )
{
*ret_font = (_DtCvPointer) 0;
}
/*****************************************************************************
* Function: _DtCvStatus TermResolveSpc ();
*
* Parameters:
*
* Returns:
*
* Purpose:
*
*****************************************************************************/
static _DtCvStatus
TermResolveSpc (
_DtCvPointer client_data,
char *lang,
char *charset,
_DtHelpFontHints font_attr,
char *spc_symbol,
_DtCvPointer *ret_handle,
_DtCvUnit *ret_width,
_DtCvUnit *ret_height,
_DtCvUnit *ret_ascent)
{
const char* spcStr;
/*
* initialize the returned information to nothing.
*/
*ret_handle = NULL;
*ret_height = 0;
*ret_width = 0;
*ret_ascent = 0;
spcStr = _DtHelpCeResolveSpcToAscii (spc_symbol);
if (spcStr != NULL)
{
*ret_handle = ((_DtCvPointer)(spcStr));
*ret_height = 1;
*ret_width = strlen(spcStr);
}
return 0;
}
/*****************************************************************************
* Function: void TermFontMetrics ();
*
* Parameters:
*
* Returns:
*
* Purpose:
*
*****************************************************************************/
static void
TermFontMetrics (
_DtCvPointer client_data,
_DtCvPointer font_ptr,
_DtCvUnit *ret_ascent,
_DtCvUnit *ret_descent,
_DtCvUnit *char_width,
_DtCvUnit *ret_super,
_DtCvUnit *ret_sub)
{
if (ret_ascent)
*ret_ascent = 0;
if (ret_descent)
*ret_descent = 0;
if (char_width)
*char_width = 0;
if (ret_super)
*ret_super = 0;
if (ret_sub)
*ret_sub = 0;
return;
}
/*****************************************************************************
* Function: _DtCvUnit TermStrWidth ();
*
* Parameters:
*
* Returns:
*
* Purpose:
*
*****************************************************************************/
static _DtCvUnit
TermStrWidth (
_DtCvPointer client_data,
_DtCvElemType elem_type,
_DtCvPointer data)
{
_DtCvStringInfo *strInfo = (_DtCvStringInfo *) data;
if (elem_type != _DtCvSTRING_TYPE)
return 0;
return ((_DtCvUnit)(strInfo->byte_len));
}
/******************************************************************************
* End Canvas functions
* Begin other private functions
******************************************************************************/
/******************************************************************************
* Function: DtHelpHyperLines *AddHyperToArray (DtHelpHyperLines *array_ptr,
* int value, char *link_spec, char *title)
*
* Parameters:
* array_ptr Specifies a NULL terminated list of
* DtHelpHyperLines or NULL.
* value Specifies the link type.
* link_spec Specifies the link specification.
* title Specifies the title of the link.
*
* Returns: A ptr to the new DtHelpHyperLines if successful,
* NULL if errors.
*
* errno Values:
* DtErrorMalloc
*
* Purpose: Add a hypertext link to an array of DtHelpHyperLines.
*
*****************************************************************************/
static DtHelpHyperLines *
AddHyperToArray(
DtHelpHyperLines *array_ptr,
int value,
int win_hint,
char *link_spec,
char *title )
{
DtHelpHyperLines *next;
int num = 0;
if (array_ptr)
{
for (next = array_ptr; next->specification != NULL; next++)
num++;
if (((num + 1) % GROW_SIZE) == 0)
array_ptr = (DtHelpHyperLines *) realloc ((void *) array_ptr,
(sizeof (DtHelpHyperLines) * (num + 1 + GROW_SIZE)));
}
else
array_ptr = (DtHelpHyperLines *) malloc (
sizeof (DtHelpHyperLines) * GROW_SIZE);
if (array_ptr == NULL)
errno = DtErrorMalloc;
else
{
next = array_ptr + num;
next->hyper_type = value;
next->win_hint = win_hint;
next->specification = strdup(link_spec);
next->title = title;
next++;
next->specification = NULL;
next->title = NULL;
}
return array_ptr;
}
/******************************************************************************
* Function: void DeallocateHyperArray (DtHelpHyperLines *array_ptr)
*
* Parameters:
* array_ptr Specifies a NULL terminated array of
* DtHelpHyperLines.
*
* Returns: Nothing
*
* errno Values:
*
* Purpose: De-allocate an array of DtHelpHyperLines structures.
*
*****************************************************************************/
static void
DeallocateHyperArray(
DtHelpHyperLines *array_ptr )
{
register DtHelpHyperLines *next = array_ptr;
if (array_ptr)
{
while (next->title && next->specification)
{
free (next->title);
free (next->specification);
next++;
}
free (array_ptr);
}
}
/******************************************************************************
* Function: int AddHyperToList(
*
* Parameters:
*
* Returns: 0 if successful.
* -1 if unrecoverable errors.
* -2 if could not resolve the hypertext link.
*
* errno Values:
* DtErrorMalloc
* DtErrorFormattingLabel
* A label has illegal syntax.
* DtErrorHyperType
* Invalid (negative) hypertype.
* DtErrorFormattingLink
* Invalid <LINK>.
* DtErrorHyperSpec
* Invalid 'hyper_specification' in the
* the <LINK>.
* DtErrorFormattingId
* Invalid <ID> syntax.
*
* Purpose: Process the result of a hypertext link, filling out
* a hypertext structure element with the information.
*
*****************************************************************************/
static int
AddHyperToList(
_DtHelpVolumeHdl volume,
_DtCvHandle canvas,
int i,
DtHelpHyperLines **ret_list)
{
_DtCanvasStruct *myCanvas = (_DtCanvasStruct *)canvas;
_DtCvLinkInfo hyperInfo;
_DtHelpVolumeHdl newVol = NULL;
_DtHelpVolumeHdl useVol = volume;
char *volName = NULL;
char *title = NULL;
char *allocName = NULL;
char *spec = NULL;
char *id;
int result = -3;
if (_DtLinkDbGetLinkInfo(myCanvas->link_data, i,
myCanvas->virt_functions.exec_cmd_filter,
myCanvas->client_data, &hyperInfo) == 0)
{
result = 0;
if (hyperInfo.description == NULL)
{
id = hyperInfo.specification;
switch (hyperInfo.hyper_type)
{
case _DtCvLinkType_CrossLink:
spec = strdup (id);
if (spec != NULL)
{
volName = spec;
id = NULL;
_DtHelpCeStrchr (spec," ",MB_CUR_MAX,&id);
if (id != NULL)
{
*id = '\0';
id++;
/* find the volume (volName is malloc'd) */
allocName = _DtHelpFileLocate(DtHelpVOLUME_TYPE, volName,
_DtHelpFileSuffixList,False,R_OK);
if (allocName == NULL)
result = -2;
if (_DtHelpOpenVolume(allocName, &newVol)==0)
useVol = newVol;
else
result = -2;
}
else
id = spec;
}
else
result = -1;
/* fall thru */
case _DtCvLinkType_SameVolume:
if (result == 0)
{
result = _DtHelpGetTopicTitle(useVol, id, &title);
if (result == -2)
HyperErr = DtErrorLocIdNotFound;
}
if (newVol != NULL)
_DtHelpCloseVolume(newVol);
if (spec != NULL)
free(spec);
if (allocName != NULL)
free(allocName);
break;
case _DtCvLinkType_Execute:
title = (char *) malloc(strlen(id) + 11);
sprintf(title, "Execute \"%s\"", id);
break;
case _DtCvLinkType_ManPage:
title = (char *) malloc(strlen(id) + 13);
sprintf(title, "Man Page \"%s\"", id);
break;
case _DtCvLinkType_AppDefine:
title = (char *) malloc(strlen(id) + 26);
sprintf(title, "Application Link Type \"%s\"", id);
break;
case _DtCvLinkType_TextFile:
title = (char *) malloc(strlen(id) + 12);
sprintf(title, "Text File \"%s\"", id);
break;
default:
title = strdup ("Unkown link type");
break;
}
}
else
{
title = strdup (hyperInfo.description);
}
}
if (result == -2)
*ret_list = AddHyperToArray (*ret_list, -(hyperInfo.hyper_type + 1),
hyperInfo.win_hint,
hyperInfo.specification,
strdup("Invalid Link"));
else if (result >= 0)
*ret_list = AddHyperToArray (*ret_list, hyperInfo.hyper_type,
hyperInfo.win_hint,
hyperInfo.specification,
title);
/*
* report unable to resolve the hypertext link
*/
if (result == -2)
return -2;
if (result == -1 || *ret_list == NULL)
return -1;
return (0);
} /* End AddHyperToList */
/******************************************************************************
* Function: TerminalInfo * GetTermInfo(canvasHandle)
*
* Parameters:
* canvasHandle Canvas whose client_data is a TerminalInfo *
*
* Returns: 0 for success, -1 for failure.
*
******************************************************************************/
static TerminalInfo *
GetTermInfo(
_DtCvHandle canvasHandle)
{
_DtCanvasStruct * canvas = (_DtCanvasStruct *) canvasHandle;
return (TerminalInfo *) canvas->client_data;
}
/******************************************************************************
*
* Public functions
*
******************************************************************************/
/******************************************************************************
* Function: int _DtHelpTermCreateCanvas (int maxColumns,_DtCvHandle * ret_canvas)
*
* Parameters:
* maxColumns Specifies the column width of the window
* for which to format the information.
* ret_canvas handle to the canvas that was created
*
* Returns: 0 for success, -1 for failure.
*
* errno Values:
* EINVAL 'ret_canvas' was NULL or 'maxColumns'
* was less than one.
* ENOMEM unable to allocate necessary memory
* DtErrorMalloc
*
* Purpose: _DtHelpTermCreateCanvas creates a canvas that use
* text-only content processing routines
*
*****************************************************************************/
int
_DtHelpTermCreateCanvas (
int maxColumns,
_DtCvHandle * ret_canvas)
{
TerminalInfo * termInfo;
/*
* check the parameters
*/
if (maxColumns < 1 || ret_canvas == NULL)
{
errno = EINVAL;
return -1;
}
termInfo = (TerminalInfo *) malloc(sizeof(TerminalInfo));
if (termInfo == NULL)
{
errno = ENOMEM;
return -1;
}
/* init info and create a canvas */
*termInfo = DfltTermInfo;
termInfo->max_columns = maxColumns;
if (1 < MB_CUR_MAX)
_DtHelpLoadMultiInfo(&(termInfo->cant_begin_chars),
&(termInfo->cant_begin_chars),
&(termInfo->nl_to_space));
*ret_canvas = _DtCanvasCreate (TermVirtInfo, (_DtCvPointer) termInfo);
if (*ret_canvas == NULL)
return -1;
return 0;
}
/******************************************************************************
* Function: int _DtHelpTermGetTopicData(canvasHandle,volHandle,
* locationId,helpList,hyperList)
*
* Parameters:
* canvasHandle Canvas used to retrieve the info; MUST
* be a Terminal canvas Since it isn't easy
* to verify this, we don't try. So if the
* Canvas ISN'T a Terminal Canvas, we'll
* crash.
* volHandle Help volume to use
* locationId Specifies the locationId of the desired topic.
* helpList Returns a NULL terminated array of
* strings.
* hyperList Returns a NULL terminated array of
* DtHelpHyperLines containing the hyperlinks
* found in the topic.
*
* Returns: 0 for success, -1 for failure.
*
* errno Values:
* EINVAL 'helpVolume', 'locationId', 'helpList',
* or 'hyperList' were NULL. 'maxColumns'
* was less than one.
* open(2) errno set via an open call on
* the file for 'locationId'.
* DtErrorMalloc
* DtErrorExceedMaxSize
* When following symbolic links, the
* new path will exceed the system
* maximum file path length.
* DtErrorIllegalPath
* When following symbolic links, the
* new path would change to a parent
* directory beyond the beginning
* of the base path.
* DtErrorIllegalDatabaseFile
* Specifies that 'helpVolume' is
* an illegal database file.
* DtErrorMissingFilenameRes
* Specifies that the 'Filename/filename'
* resource for the topic does not exist.
* DtErrorMissingFileposRes
* Specifies that the 'Filepos/filepos'
* resource for the topic does not exist.
* DtErrorLocIdNotFound
* Specifies that 'locationId' was not found.
* DtErrorFormattingLabel
* A label has illegal syntax.
* DtErrorHyperType
* Invalid (negative) hypertype.
* DtErrorFormattingLink
* Invalid <LINK>.
* DtErrorHyperSpec
* Invalid 'hyper_specification' in the
* the <LINK>.
* DtErrorFormattingId
* Invalid <ID> syntax.
* DtErrorFormattingTitle
* Invalid <TITLE> syntax.
*
* Purpose: _DtHelpTermGetTopicData retrieves Help Files content with
* in a form understood by a terminal
*
*****************************************************************************/
int
_DtHelpTermGetTopicData(
_DtCvHandle canvasHandle,
_DtHelpVolumeHdl volHandle,
char * locationId,
char * * * helpList,
DtHelpHyperLines ** hyperList)
{
int result = -1;
int offset;
_DtCvUnit maxRows;
_DtCvUnit maxWidth;
char * * strList;
char* fileName = NULL;
_DtHelpCeLockInfo lockInfo;
_DtCvTopicPtr topic;
TerminalInfo * termInfo;
_FrmtUiInfo myUiInfo;
termInfo = GetTermInfo(canvasHandle);
_DtHelpProcessLock();
if (WcSpace == 0)
mbtowc (&WcSpace, " ", 1);
_DtHelpProcessUnlock();
/*
* find the filename and the Id string.
*/
if (_DtHelpCeLockVolume(volHandle, &lockInfo) != 0)
{
return -1;
}
if (_DtHelpCeFindId(volHandle,locationId,lockInfo.fd,&fileName,&offset)==0)
{
_DtHelpCeUnlockVolume(lockInfo);
return -1;
}
/*
* create the ui structure for the parsing.
*/
#ifdef XTAG
myUiInfo.load_graphic = TermFindGraphic;
#else
myUiInfo.load_graphic = NULL;
#endif /* XTAG */
myUiInfo.resolve_spc = TermResolveSpc;
myUiInfo.load_font = TermGetFont;
myUiInfo.destroy_region = NULL;
myUiInfo.exec_filter = NULL;
myUiInfo.client_data = (_DtCvPointer) termInfo;
myUiInfo.line_width = 0;
myUiInfo.line_height = 1;
myUiInfo.leading = 0;
myUiInfo.avg_char = 1;
myUiInfo.nl_to_space = termInfo->nl_to_space;
/*
* Format the topic.
*/
result = _DtHelpCeGetVolumeFlag(volHandle);
_DtHelpProcessLock();
if (result == 1)
result = _DtHelpCeParseSdlTopic(volHandle,
&myUiInfo,
lockInfo.fd,
offset, NULL, True, &topic);
else if (result == 0)
result = _DtHelpCeFrmtCcdfTopic(volHandle, fileName,
offset, NULL, &myUiInfo,
&topic);
_DtHelpProcessUnlock();
/* if successfully formatted topic */
if (result != -1)
{
int i;
int len;
wchar_t **wcList;
_DtCanvasStruct *myCStruct = (_DtCanvasStruct *)canvasHandle;
/* build the help text list, if requested */
if (NULL != helpList)
{
_DtCanvasSetTopic(canvasHandle, topic, _DtCvIGNORE_BOUNDARY,
&maxWidth, &maxRows, NULL);
/*
* The 'maxRows' variable is really misnamed; it's really the
* 'maxY', and is 0-based. Thus, the 'lines' and 'wc_num'
* arrays need to be 'maxRows+1', in order to hold all the
* entries. Likewise, 'strList' must be 'maxRows+2', because
* it also needs to be NULL terminated.
*/
termInfo->lines = (wchar_t **)malloc(sizeof(wchar_t *) *(maxRows+1));
termInfo->wc_num = (size_t *)malloc(sizeof(size_t) * (maxRows+1));
strList = (char **) malloc(sizeof(char *) * (maxRows+2));
if (termInfo->lines == NULL || termInfo->wc_num == NULL ||
strList == NULL)
{
free(fileName);
if (termInfo->lines != NULL)
free(termInfo->lines);
if (termInfo->wc_num != NULL)
free(termInfo->wc_num);
if (strList != NULL)
free(strList);
_DtHelpCeUnlockVolume(lockInfo);
return -1;
}
for (i = 0; i <= maxRows; i++)
{
termInfo->lines[i] = NULL;
termInfo->wc_num[i] = 0;
}
_DtCanvasRender(canvasHandle, 0, 0, maxWidth, maxRows,
_DtCvRENDER_PARTIAL, _DtCvFALSE, NULL, NULL);
*helpList = strList;
wcList = termInfo->lines;
for (i = 0; i <= maxRows; i++, wcList++, strList++)
{
if (*wcList == NULL)
{
*strList = (char *) malloc (1);
**strList = '\0';
}
else
{
len = (termInfo->wc_num[i] + 1) * MB_CUR_MAX;
*strList = (char *) malloc (sizeof (char) * len);
if (*strList != NULL)
wcstombs(*strList, *wcList, len);
}
}
*strList = NULL;
/*
* free the allocated memory
*/
for (i = 0, wcList = termInfo->lines; i <= maxRows; i++, wcList++)
if (*wcList != NULL)
free(*wcList);
free(termInfo->lines);
free(termInfo->wc_num);
} /* if requested help text */
/*
* build the hyperlinks list, if requested
*/
if ( NULL != hyperList )
{
*hyperList = NULL;
for (i = 0; result != -1 && i < myCStruct->link_data->max; i++)
result = AddHyperToList(volHandle, canvasHandle, i, hyperList);
}
} /* if successfully formatted topic */
_DtCanvasClean(canvasHandle);
_DtHelpDestroyTopicData(topic, NULL, NULL);
free(fileName);
_DtHelpCeUnlockVolume(lockInfo);
return result;
} /* End _DtHelpTermGetTopicData */
/******************************************************************************
* Function: int _DtHelpGetTopicDataHandles(ret_canvasHandle,ret_volHandle)
*
* Parameters:
* ret_canvasHandle Canvas used to retrieve the info
* ret_volHandle Help volume in use
*
* Returns:
* 0: canvas handle & volHandle are not NULL
* -1: canvas handle & volHandle are NULL
******************************************************************************/
int
_DtHelpGetTopicDataHandles(
_DtCvHandle * ret_canvasHandle,
_DtHelpVolumeHdl * ret_volHandle)
{
_DtHelpProcessLock();
*ret_canvasHandle = MyCanvas;
*ret_volHandle = MyVolume;
if (MyCanvas != NULL && MyVolume != NULL)
{
_DtHelpProcessUnlock();
return 0;
}
else
{
_DtHelpProcessUnlock();
return -1;
}
}
/******************************************************************************
* Function: int _DtHelpGetTopicData (char *helpVolume, char *locationId,
* int maxColumns, char ***helpList, DtHelpHyperLines **hyperList)
*
* Parameters:
* helpVolume Specifies a file path to the volume.
* locationId Specifies the locationId of the desired topic.
* maxColumns Specifies the column width of the window
* for which to format the information.
* helpList Returns a NULL terminated array of
* strings.
* hyperList Returns a NULL terminated array of
* DtHelpHyperLines containing the hyperlinks
* found in the topic.
*
* Returns: 0 for success, -1 for failure.
*
* errno Values:
* EINVAL 'helpVolume', 'locationId', 'helpList',
* or 'hyperList' were NULL. 'maxColumns'
* was less than one.
* getcwd(2) errno set via a getcwd call.
* readlink(2) errno set via a readlink call.
* open(2) errno set via an open call on
* the file for 'locationId'.
* DtErrorMalloc
* DtErrorExceedMaxSize
* When following symbolic links, the
* new path will exceed the system
* maximum file path length.
* DtErrorIllegalPath
* When following symbolic links, the
* new path would change to a parent
* directory beyond the beginning
* of the base path.
* DtErrorIllegalDatabaseFile
* Specifies that 'helpVolume' is
* an illegal database file.
* DtErrorMissingFilenameRes
* Specifies that the 'Filename/filename'
* resource for the topic does not exist.
* DtErrorMissingFileposRes
* Specifies that the 'Filepos/filepos'
* resource for the topic does not exist.
* DtErrorLocIdNotFound
* Specifies that 'locationId' was not found.
* DtErrorFormattingLabel
* A label has illegal syntax.
* DtErrorHyperType
* Invalid (negative) hypertype.
* DtErrorFormattingLink
* Invalid <LINK>.
* DtErrorHyperSpec
* Invalid 'hyper_specification' in the
* the <LINK>.
* DtErrorFormattingId
* Invalid <ID> syntax.
* DtErrorFormattingTitle
* Invalid <TITLE> syntax.
*
* Purpose: _DtHelpGetTopicData formats Help Files with
* formatting information
* into a form understood by a terminal
*
*****************************************************************************/
int
_DtHelpGetTopicData (
char * helpVolume,
char * locationId,
int maxColumns,
char * * * helpList,
DtHelpHyperLines * * hyperList )
{
int result = -1;
_DtHelpVolumeHdl volume = NULL;
char * path = NULL;
/* find the volume (path is malloc'd) */
path = _DtHelpFileLocate(DtHelpVOLUME_TYPE, helpVolume,
_DtHelpFileSuffixList,False,R_OK);
if (path == NULL) { errno = EINVAL; return -1; } /* RETURN */
/* open new canvas or reuse old one with new size */
_DtHelpProcessLock();
if (MyCanvas == NULL)
{
_DtHelpTermCreateCanvas(maxColumns,&MyCanvas);
if (MyCanvas == NULL)
{
free(path);
_DtHelpProcessUnlock();
return -1; /* RETURN: errno=from CreateCanvas */
}
}
else
{
MyInfo.max_columns = maxColumns;
_DtCanvasResize (MyCanvas, _DtCvFALSE, NULL, NULL);
}
if (_DtHelpOpenVolume (helpVolume, &volume) == -1)
{
free(path);
_DtHelpProcessUnlock();
return -1; /* RETURN: errno=from OpenVolume */
}
/* release any previously opened volume */
if (MyVolume)
_DtHelpCloseVolume (MyVolume);
/* assign the new volume */
MyVolume = volume;
/* get the terminal info */
result = _DtHelpTermGetTopicData(MyCanvas,MyVolume,locationId,helpList,hyperList);
_DtHelpProcessUnlock();
free(path);
return result;
}
/*****************************************************************************
* Function: int _DtHelpProcessLinkData (char * ref_volume,DtHelpHyperLines *hyperLine,
* char **ret_helpVolume, char **ret_locationId)
*
* Parameters:
* hyperLine Specifies the hypertext line that
* the caller wishes to be resolved.
* helpVolume Returns the help volume specified by
* 'hyperLine'.
* locationId Returns the location Id specified by
* 'hyperLine'.
*
* Returns: 0 if successful, -1 if errors.
*
* errno Values:
* EINVAL 'hyperLines', 'helpVolume', or 'locationId'
* is NULL.
* DtErrorMalloc
* DtErrorHyperType
* The hyper type is not _DtJUMP_REUSE,
* _DtJUMP_NEW, or _DtDEFINITION.
* DtErrorHyperSpec
* Invalid hyper specification.
* DtErrorIllegalPath
* The volume used by the link spec (either
* embedded or the ref_volume) could not be
* located.
*
* Purpose: _DtHelpProcessLinkData resolves a hypertext specification
* into a pathname to a help volume and a location Id within
* the help volume.
*
*****************************************************************************/
int
_DtHelpProcessLinkData (
char * ref_volume,
DtHelpHyperLines * hyperLine,
char * * ret_helpVolume,
char * * ret_locationId )
{
char * linkSpec = NULL;
char * volumeName = NULL;
char * idToken = NULL;
/* check params */
if (ref_volume == NULL || hyperLine == NULL ||
ret_helpVolume == NULL || ret_locationId == NULL)
{
errno = EINVAL;
return -1;
}
/* only process SameVolume or CrossVolume links */
switch (hyperLine->hyper_type)
{
case _DtCvLinkType_SameVolume:
case _DtCvLinkType_CrossLink:
break;
default:
errno = DtErrorHyperType;
return -1; /* RETURN */
}
/* Initialize the pointers. */
*ret_helpVolume = NULL;
*ret_locationId = NULL;
/* get working copy of spec */
linkSpec = strdup (hyperLine->specification);
if (linkSpec == NULL)
{
errno = DtErrorMalloc;
return -1;
}
/* parse the link spec. Syntax is: "[volume] locationId" */
if (linkSpec == NULL || *linkSpec == EOS)
{
errno = DtErrorHyperSpec; /* no spec */
}
else /* at least one token exists */
{
volumeName = linkSpec; /* posit that first token is the volume */
/* look for another possible token */
idToken = NULL;
_DtHelpCeStrchr (linkSpec," ",MB_CUR_MAX,&idToken);
/* second token? */
if (idToken) /* second token */
{
/* separate the tokens and advance idToken to first valid char */
*idToken = EOS; idToken++;
/* find the fully qualified volume (volName is malloc'd) */
volumeName = _DtHelpFileLocate(DtHelpVOLUME_TYPE, volumeName,
_DtHelpFileSuffixList,False,R_OK);
if (volumeName == NULL)
errno = DtErrorIllegalPath;
}
else /* no second token */
{
idToken = volumeName;
/* find the fully qualified volume (volName is malloc'd) */
volumeName = _DtHelpFileLocate(DtHelpVOLUME_TYPE, ref_volume,
_DtHelpFileSuffixList,False,R_OK);
if (volumeName == NULL)
errno = DtErrorIllegalPath;
}
if (idToken && volumeName)
{
*ret_helpVolume = volumeName; /* already allocd by _DtHelpFileLocate */
*ret_locationId = strdup (idToken);
if (*ret_locationId == NULL)
errno = DtErrorMalloc;
}
} /* if at least one token exists */
free (linkSpec);
return ( (*ret_helpVolume && *ret_locationId) ? 0 : -1 );
} /* End _DtHelpProcessLinkData */
/*****************************************************************************
* Function: void _DtHelpFreeTopicData (char **helpList,
* DtHelpHyperLines *hyperList)
*
* Parameters:
* helpList Specifies a pointer to a NULL terminated
* array of strings.
* hyperList Specifies a pointer to a NULL terminated
* list of DtHelpHyperLines.
*
* Returns: Nothing
*
* Purpose: _DtHelpFreeTopicData frees the data associated with a topic.
*
*****************************************************************************/
void
_DtHelpFreeTopicData (
char **helpList,
DtHelpHyperLines *hyperList)
{
if (helpList != NULL)
_DtHelpCeFreeStringArray (helpList);
if (hyperList != NULL)
DeallocateHyperArray (hyperList);
} /* End _DtHelpFreeTopicData */
/******************************************************************************
* Function: int _DtHelpGetTopicChildren (char *helpVolume, char *topic_id,
* char ***ret_children)
*
* Parameters:
* helpVolume Specifies a file path to the volume.
* topic_id Specifies the id of the desired topic.
* ret_children Returns a NULL terminated array of
* strings. The memory for these strings
* *IS OWNED* by the caller and must be freed
* after use.
*
* Returns: > 0 for success, -1 for failure.
*
* errno Values:
*
* Purpose: _DtHelpGetTopicChildren returns the topic ids of the children
* for a given topic id.
*
*****************************************************************************/
int
_DtHelpGetTopicChildren (
char *helpVolume,
char *topic_id,
char ***ret_children)
{
int result = -1;
_DtHelpVolumeHdl volume = NULL;
char * path;
/* Initialize the pointer */
*ret_children = NULL;
/* find the volume (path is malloc'd) */
path = _DtHelpFileLocate(DtHelpVOLUME_TYPE, helpVolume,
_DtHelpFileSuffixList,False,R_OK);
if (path == NULL) { errno = EINVAL; return -1; } /* RETURN */
/* open new canvas or reuse old one with new size */
_DtHelpProcessLock();
if (MyCanvas == NULL)
{
_DtHelpTermCreateCanvas(72,&MyCanvas); /* 72: arbitary value for max columns */
if (MyCanvas == NULL)
{
free(path);
_DtHelpProcessUnlock();
return -1; /* RETURN: errno=??? */
}
}
if (_DtHelpOpenVolume (helpVolume, &volume) == -1)
{
free(path);
_DtHelpProcessUnlock();
return -1; /* RETURN: errno=??? */
}
/* release any previously opened volume */
if (MyVolume)
_DtHelpCloseVolume (MyVolume);
/* assign the new volume */
MyVolume = volume;
/* Get the children */
result = _DtHelpCeGetTopicChildren(MyVolume, topic_id, ret_children);
_DtHelpProcessUnlock();
free(path);
return result;
}