/* * CDE - Common Desktop Environment * * Copyright (c) 1993-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these libraries and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ /* $TOG: 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 #include #include #include #include #include #include #include #include #ifdef X_NOT_STDC_ENV extern int errno; #endif /* * Canvas Engine includes */ #include "CanvasP.h" #include "CanvasSegP.h" #include "LinkMgrP.h" /* * private includes */ #include "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) { 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) { 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 ) { 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 . * DtErrorHyperSpec * Invalid 'hyper_specification' in the * the . * DtErrorFormattingId * Invalid 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 . * DtErrorHyperSpec * Invalid 'hyper_specification' in the * the . * DtErrorFormattingId * Invalid syntax. * DtErrorFormattingTitle * Invalid 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 = NULL; 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; }