FileUtils.c: fix CERT VU#575804
[oweals/cde.git] / cde / lib / DtHelp / Format.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: Format.c /main/18 1996/11/22 12:23:59 cde-hp $ */
24 /************************************<+>*************************************
25  ****************************************************************************
26  **
27  **   File:     Format.c
28  **
29  **   Project:     Text Graphic Display Library
30  **
31  **   Description: This body of formats the input into a form understood by
32  **             a Display Area.
33  **
34  **  (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
35  **
36  **  (c) Copyright 1993, 1994 Hewlett-Packard Company
37  **  (c) Copyright 1993, 1994 International Business Machines Corp.
38  **  (c) Copyright 1993, 1994 Sun Microsystems, Inc.
39  **  (c) Copyright 1993, 1994 Novell, Inc.
40  **
41  **
42  ****************************************************************************
43  ************************************<+>*************************************/
44
45 /*
46  * system includes
47  */
48 #include <stdio.h>
49 #include <errno.h>
50 #include <fcntl.h>
51 #include <locale.h>
52 #include <stdlib.h>
53 #include <unistd.h>
54 #include <X11/Xlib.h>
55 #include <X11/Xresource.h>
56 #include <Xm/Xm.h>
57
58 #ifdef X_NOT_STDC_ENV
59 extern int errno;
60 #endif
61
62 /*
63  * Core Engine includes
64  */
65 #include "CanvasP.h"
66 #include "CanvasSegP.h"
67
68 /*
69  * private includes
70  */
71 #include "bufioI.h"
72 #include "CvtToArrayP.h"
73 #include "DisplayAreaP.h"
74 #include "FontAttrI.h"
75 #include "FontI.h"
76 #include "HelpXlate.h"
77 #include "XInterfaceI.h"
78 #include "Lock.h"
79
80 /*
81  * private core engine
82  */
83 #include "Access.h"
84 #include "AccessP.h"
85 #include "AccessI.h"
86 #include "SDLI.h"
87 #include "FormatUtilI.h"
88 #include "FormatCCDFI.h"
89 #include "FormatSDLI.h"
90
91
92 #ifdef NLS16
93 #endif
94
95 /********    Private Function Declarations    ********/
96
97 /********    End Public Function Declarations    ********/
98
99 /******************************************************************************
100  *
101  * Private variables and defines.
102  *
103  *****************************************************************************/
104 #define BUFF_SIZE       1024
105
106 static  char    *ScanString = "\n\t";
107 static const _FrmtUiInfo defUiInfo = { NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 1, False };
108
109 /******************************************************************************
110  *
111  * Private Functions
112  *
113  *****************************************************************************/
114 /******************************************************************************
115  * Function:    int FormatChunksToXmString ()
116  *
117  * Parameters:
118  *               *ret_list may be NULL when called
119  *
120  * Returns:     0 if successful, -1 if errors
121  *
122  * errno Values:
123  *
124  * Purpose:     Take some rich text chunks and turn it into an XmString.
125  *
126  ******************************************************************************/
127 static int
128 FormatChunksToXmString(
129     DtHelpDispAreaStruct *pDAS,
130     Boolean               free_flag,
131     void                **title_chunks,
132     XmString             *ret_title,
133     XmFontList           *ret_list,
134     Boolean              *ret_mod )
135 {
136     int                  result = 0;
137     int                  i;
138     int                  j;
139     int                  quarkCount;
140     int                  chunkType;
141     int                  myIdx;
142     _DtCvPointer         fontPtr;
143     char                *charSet;
144     const char          *strChunk;
145     char                 buffer[16];
146     _DtHelpFontHints             fontSpecs;
147     XmFontContext        fontContext;
148     XmString             partTitle;
149     XmString             newTitle;
150     XrmQuark             charSetQuark;
151     XrmName              myCharSetQuarks[20];
152     XrmName              xrmName[_CEFontAttrNumber];
153     Boolean              myMore;
154
155     /*
156      * Initialize the pointers.
157      */
158     *ret_title = NULL;
159     *ret_mod   = False;
160
161     if (title_chunks == NULL)
162         return -1;
163
164     /*
165      * initialize the font context
166      */
167     _DtHelpCeCopyDefFontAttrList(&fontSpecs);
168     if ( NULL != *ret_list )
169       {
170         if (XmFontListInitFontContext (&fontContext, *ret_list) == False)
171             result = -1;
172         else 
173           {
174             XFontStruct *myFontStruct;
175             /*
176              * quarkize all the character sets found.
177              */
178             quarkCount = 0;
179             do
180               {
181                 myMore = XmFontListGetNextFont (fontContext, &charSet,
182                                                                 &myFontStruct);
183                 if (myMore)
184                   {
185                     myCharSetQuarks[quarkCount++] = 
186                                                 XrmStringToQuark (charSet);
187                     XtFree (charSet);
188                   }
189               } while (myMore);
190     
191             XmFontListFreeFontContext (fontContext);
192           }
193       } /* if NULL != *ret_list */
194     else
195       { /* if NULL == *ret_list */
196          quarkCount = 0;
197          myCharSetQuarks[0] = 0;
198       }
199
200     /*
201      * Build the XrmString based on the segments.
202      * The format of the returned information is
203      *          'DT_HELP_CE_CHARSET  locale  string'
204      *          'DT_HELP_CE_FONT_PTR fontptr string'
205      *          'DT_HELP_CE_SPC      spc'
206      *          'DT_HELP_CE_STRING   string' - uses last specified
207      *                                         charset/font_ptr.
208      *
209      * The order and manner in which the title_chunks are processed
210      * is known and depended upon in several locations.
211      * Do not change this without changing the other locations.
212      * See the _DtHelpFormatxxx() routines and the ones that
213      * create the title_chunk arrays in FormatSDL.c and FormatCCDF.c
214      */
215     myIdx = __DtHelpDefaultFontIndexGet(pDAS);
216     _DtHelpCopyDefaultList(xrmName);
217     for (i = 0; result == 0 && title_chunks[i] != DT_HELP_CE_END; i++)
218       {
219         /*
220          * create a string for the char set and a quark for it.
221          */
222         chunkType = (int) title_chunks[i++];
223
224         /*
225          * i now points to the first value after the type
226          */
227         if (chunkType & DT_HELP_CE_CHARSET)
228           {
229             char *charSet;
230             char *lang = (char *) title_chunks[i];
231
232             /*
233              * test to see if the locale is in a lang.codeset form
234              */
235             if (_DtHelpCeStrchr(lang, ".", 1, &charSet) == 0)
236               {
237                 *charSet = '\0';
238                 charSet++;
239               }
240             else
241               {
242                 charSet = lang;
243                 lang    = NULL;
244               }
245
246             /*
247              * resolve/load the font for the default fonts
248              */
249             _DtHelpDAResolveFont(pDAS, lang, charSet, fontSpecs, &fontPtr);
250             myIdx = (int) fontPtr;
251             if (lang != NULL)
252               {
253                 charSet--;
254                 *charSet = '.';
255               }
256
257             if (free_flag)
258                 free(title_chunks[i]);
259
260             /*
261              * move the i to point to the string.
262              */
263             i++;
264           }
265         else if (chunkType & DT_HELP_CE_FONT_PTR)
266           {
267             /*
268              * get the default font for the language and code set.
269              */
270             (void) __DtHelpFontCharSetQuarkGet(pDAS, (int)title_chunks[i],
271                                         &xrmName[_DT_HELP_FONT_CHAR_SET]);
272             (void) __DtHelpFontLangQuarkGet(pDAS, (int)title_chunks[i],
273                                         &xrmName[_DT_HELP_FONT_LANG_TER]);
274             (void) __DtHelpFontIndexGet(pDAS, xrmName, &myIdx);
275
276             /*
277              * move the i to point to the string.
278              */
279             i++;
280           }
281
282         /*
283          * the i point spc or string.
284          */
285         if (chunkType & DT_HELP_CE_SPC)
286           {
287             j        = (int) title_chunks[i];
288             strChunk = _DtHelpDAGetSpcString(pDAS->spc_chars[j].spc_idx);
289             fontPtr  = pDAS->spc_chars[j].font_ptr;
290
291             /*
292              * get the default font for the language and code set.
293              */
294             (void) __DtHelpFontCharSetQuarkGet(pDAS, (int)fontPtr,
295                                         &xrmName[_DT_HELP_FONT_CHAR_SET]);
296             (void) __DtHelpFontLangQuarkGet(pDAS, (int)fontPtr,
297                                         &xrmName[_DT_HELP_FONT_LANG_TER]);
298             (void) __DtHelpFontIndexGet(pDAS, xrmName, &myIdx);
299           }
300         else /* if (chunkType & _DT_HELP_CE_STRING) */
301             strChunk = (char *) title_chunks[i];
302
303         sprintf(buffer, "%d", myIdx);
304         charSetQuark = XrmStringToQuark(buffer);
305
306         j = 0;
307         while (j < quarkCount && myCharSetQuarks[j] != charSetQuark)
308             j++;
309
310         /*
311          * If we didn't find a matching character set,
312          * add it to the list.
313          */
314         if (j >= quarkCount)
315           {
316             /* Copy the input list so XmFontListAppendEntry can mangle it. */
317             /* But only do it once! */
318             if (False == *ret_mod)
319                *ret_list = XmFontListCopy(*ret_list);
320
321             if (myIdx < 0)
322               {
323                 XFontSet fontSet = __DtHelpFontSetGet(pDAS->font_info, myIdx);
324                 XmFontListEntry fontEntry;
325
326                 fontEntry = XmFontListEntryCreate (buffer,
327                                                 XmFONT_IS_FONTSET,
328                                                 (XtPointer) fontSet);
329                 *ret_list = XmFontListAppendEntry (*ret_list, fontEntry);
330                 XmFontListEntryFree (&fontEntry);
331               }
332             else
333               {
334                 XFontStruct *fontStruct =
335                                 __DtHelpFontStructGet(pDAS->font_info, myIdx);
336                 XmFontListEntry fontEntry;
337
338                 fontEntry = XmFontListEntryCreate (buffer,
339                                                 XmFONT_IS_FONT,
340                                                 (XtPointer) fontStruct);
341                 *ret_list = XmFontListAppendEntry (*ret_list, fontEntry);
342                 XmFontListEntryFree (&fontEntry);
343               }
344
345            *ret_mod = True;
346             if (*ret_list == NULL)
347                 result = -1;
348
349             myCharSetQuarks[quarkCount++] = charSetQuark;
350           }
351
352         /*
353          * add this segment to the XmString.
354          */
355         if (result == 0)
356           {
357             if (*ret_title == NULL)
358                 *ret_title = XmStringGenerate ((char *) strChunk, buffer, 
359                                                XmCHARSET_TEXT, NULL);
360             else
361               {
362                 partTitle = XmStringGenerate ((char *) strChunk, buffer,
363                                               XmCHARSET_TEXT, NULL);
364
365                 newTitle = XmStringConcat (*ret_title, partTitle);
366
367                 XmStringFree (*ret_title);
368                 XmStringFree (partTitle);
369                 *ret_title = newTitle;
370               }
371
372             /*
373              * if a newline was specified,
374              * replace it with a blank.
375              */
376             if (*ret_title != NULL && (chunkType & DT_HELP_CE_NEWLINE))
377               {
378                 partTitle = XmStringGenerate (" ", buffer, XmCHARSET_TEXT, NULL);
379                 newTitle = XmStringConcat (*ret_title, partTitle);
380                 XmStringFree (*ret_title);
381                 XmStringFree (partTitle);
382                 *ret_title = newTitle;
383               }
384
385             if (*ret_title == NULL)
386                 result = -1;
387           }
388
389         if (free_flag && (chunkType & DT_HELP_CE_STRING))
390             free(title_chunks[i]);
391       }
392     /*
393      * deallocate the memory.
394      */
395     if (free_flag) free(title_chunks);
396     return result;
397 }
398
399 /******************************************************************************
400  *
401  * Semi-Public Functions
402  *
403  *****************************************************************************/
404 /*****************************************************************************
405  * Function:    int _DtHelpFormatAsciiFile (char *filename,
406  *                                      CEParagraph **ret_para, int *ret_num)
407  *
408  * Parameters:
409  *              filename        Specifies the ascii file to read.
410  *              ret_para        Returns a pointer to a list of CEParagraph
411  *                              structures.
412  *              ret_num         Returns the number of structures in 'ret_para'.
413  *
414  * Returns:     0 if successful, -1 if errors
415  *
416  * errno Values:
417  *              EINVAL
418  *
419  * Purpose:     _DtHelpFormatAsciiFile formats Ascii Files into a list of
420  *              CEParagraph structures.
421  *
422  *****************************************************************************/
423 int
424 _DtHelpFormatAsciiFile(
425         XtPointer         client_data,
426         char             *filename,
427         XtPointer        *ret_handle)
428 {
429     int        myFile;
430     int        result = -1;
431     _DtHelpFontHints fontAttrs;
432     char       buffer [BUFF_SIZE];
433     BufFilePtr rawInput;
434     XtPointer   varHandle;
435     _DtCvTopicPtr         topic    = NULL;
436     DtHelpDispAreaStruct *pDAS     = (DtHelpDispAreaStruct *) client_data;
437     _FrmtUiInfo           myUiInfo = defUiInfo;
438
439     /*
440      * check the parameters
441      */
442     if (filename == NULL || ret_handle == NULL)
443       {
444         errno = EINVAL;
445         return -1;
446       }
447
448     /*
449      * Initialize the pointers, buffers and counters
450      */
451     *ret_handle  = NULL;
452
453     /*
454      * open the file.
455      */
456     myFile = open (filename, O_RDONLY);
457     if (myFile != -1)
458       {
459         /*
460          * set the information
461          */
462         rawInput = _DtHelpCeBufFileRdWithFd(myFile);
463         if (rawInput == 0)
464           {
465             close (myFile);
466             return -1;
467           }
468
469         result = _DtHelpCeReadBuf (rawInput, buffer, BUFF_SIZE);
470
471         if (result != -1)
472           {
473             _DtHelpCeCopyDefFontAttrList (&fontAttrs);
474             fontAttrs.spacing = _DtHelpFontSpacingMono;
475             _DtHelpCeXlateOpToStdLocale(DtLCX_OPER_SETLOCALE,
476                                 setlocale(LC_CTYPE,NULL), NULL,
477                                 &(fontAttrs.language), &(fontAttrs.char_set));
478
479             /*
480              * fill out the ui information
481              */
482             myUiInfo.load_font    = _DtHelpDAResolveFont;
483             myUiInfo.client_data  = (_DtCvPointer) pDAS;
484             myUiInfo.line_width   = pDAS->lineThickness;
485             myUiInfo.line_height  = pDAS->lineHeight;
486             myUiInfo.leading      = pDAS->leading;
487             myUiInfo.avg_char     = (int)(pDAS->charWidth / 10 +
488                                         ((pDAS->charWidth % 10) ? 1 : 0));
489             myUiInfo.nl_to_space  = pDAS->nl_to_space;
490
491             /*
492              * get the formatting structure.
493              */
494             varHandle = __DtHelpCeSetUpVars(fontAttrs.language,
495                                                 fontAttrs.char_set, &myUiInfo);
496             if (varHandle == NULL)
497               {
498                 free(fontAttrs.language);
499                 free(fontAttrs.char_set);
500                 return -1;
501               }
502
503             result = __DtHelpCeProcessString (varHandle, rawInput,
504                                 _DtCvLITERAL,
505                                 ScanString, buffer, BUFF_SIZE,
506                                 0, False, &fontAttrs);
507
508             if (result != -1)
509                 result = __DtHelpCeGetParagraphList (varHandle, True,
510                                                 _DtCvLITERAL,
511                                                 &topic);
512
513             free(fontAttrs.language);
514             free(fontAttrs.char_set);
515             free(varHandle);
516           }
517
518         _DtHelpCeBufFileClose(rawInput, True);
519       }
520
521     *ret_handle = (XtPointer) topic;
522     return result;
523
524 }  /* End _DtHelpFormatAsciiFile */
525
526 /*****************************************************************************
527  * Function:    int _DtHelpFormatAsciiString (char *input_string,
528  *                                      CEParagraph **ret_para, int *ret_num)
529  *
530  * Parameters:
531  *              input_string    Specifies the ascii string to format.
532  *              ret_para        Returns a pointer to a list of CEParagraph
533  *                              structures.
534  *              ret_num         Returns the number of structures in 'ret_para'.
535  *
536  * Returns:     0 if successful, -1 if errors
537  *
538  * errno Values:
539  *
540  * Purpose:     _DtHelpFormatAsciiString formats a string as if it were a
541  *              static string - watching for newlines and using them
542  *              to force a break in the line.
543  *
544  *****************************************************************************/
545 int
546 _DtHelpFormatAsciiString(
547         XtPointer         client_data,
548         char             *input_string,
549         XtPointer        *ret_handle)
550 {
551     int      result = -1;
552     _DtHelpFontHints fontAttrs;
553     XtPointer varHandle;
554     _DtCvTopicPtr         topic    = NULL;
555     DtHelpDispAreaStruct *pDAS     = (DtHelpDispAreaStruct *) client_data;
556     _FrmtUiInfo           myUiInfo = defUiInfo;
557
558     /*
559      * check the parameters.
560      */
561     if (input_string == NULL || ret_handle == NULL)
562       {
563         errno = EINVAL;
564         return -1;
565       }
566
567     /*
568      * fill out the ui information
569      */
570     myUiInfo.load_font    = _DtHelpDAResolveFont;
571     myUiInfo.client_data  = (_DtCvPointer) pDAS;
572     myUiInfo.line_width   = pDAS->lineThickness;
573     myUiInfo.line_height  = pDAS->lineHeight;
574     myUiInfo.leading      = pDAS->leading;
575     myUiInfo.avg_char     = (int)(pDAS->charWidth / 10 +
576                                     ((pDAS->charWidth % 10) ? 1 : 0));
577     myUiInfo.nl_to_space  = pDAS->nl_to_space;
578
579     /*
580      * Get the initialized variables
581      */
582     *ret_handle  = NULL;
583
584     _DtHelpCeCopyDefFontAttrList (&fontAttrs);
585     _DtHelpCeXlateOpToStdLocale(DtLCX_OPER_SETLOCALE,setlocale(LC_CTYPE,NULL),
586                                 NULL, &(fontAttrs.language),
587                                 &(fontAttrs.char_set));
588
589     varHandle = __DtHelpCeSetUpVars(fontAttrs.language, fontAttrs.char_set,
590                                                 &myUiInfo);
591     if (varHandle == NULL)
592       {
593         free(fontAttrs.language);
594         free(fontAttrs.char_set);
595         return -1;
596       }
597
598     result = __DtHelpCeProcessString (varHandle, NULL,
599                                 _DtCvLITERAL,
600                                 ScanString, input_string,
601                                 strlen(input_string),
602                                 0, False,
603                                 &fontAttrs);
604
605     if (result != -1)
606         result = __DtHelpCeGetParagraphList (varHandle, True, _DtCvLITERAL,
607                                                                 &topic);
608
609     *ret_handle = (XtPointer) topic;
610
611     free(fontAttrs.language);
612     free(fontAttrs.char_set);
613     free(varHandle);
614
615     return result;
616
617 }  /* End _DtHelpFormatAsciiString */
618
619 /*****************************************************************************
620  * Function:    int _DtHelpFormatAsciiStringDynamic (char *input_string,
621  *                                      CEParagraph **ret_para, int *ret_num)
622  *
623  * Parameters:
624  *              input_string    Specifies the ascii string to format.
625  *              ret_para        Returns a pointer to a list of CEParagraph
626  *                              structures.
627  *              ret_num         Returns the number of structures in 'ret_para'.
628  *
629  * Returns:     0 if successful, -1 if errors
630  *
631  * errno Values:
632  *
633  * Purpose:     _DtHelpFormatAsciiStringDynamic formats a string as if it were
634  *              a dynamic string - it uses newline characters to terminate
635  *              the current paragraph, not a line.
636  *
637  *****************************************************************************/
638 int
639 _DtHelpFormatAsciiStringDynamic(
640         XtPointer         client_data,
641         char             *input_string,
642         XtPointer        *ret_handle)
643 {
644     int      result = -1;
645     _DtHelpFontHints fontAttrs;
646     XtPointer varHandle;
647     _DtCvTopicPtr         topic    = NULL;
648     DtHelpDispAreaStruct *pDAS     = (DtHelpDispAreaStruct *) client_data;
649     _FrmtUiInfo           myUiInfo = defUiInfo;
650
651     /*
652      * check the parameters.
653      */
654     if (input_string == NULL || ret_handle == NULL)
655       {
656         errno = EINVAL;
657         return -1;
658       }
659
660     /*
661      * fill out the ui information
662      */
663     myUiInfo.load_font    = _DtHelpDAResolveFont;
664     myUiInfo.client_data  = (_DtCvPointer) pDAS;
665     myUiInfo.line_width   = pDAS->lineThickness;
666     myUiInfo.line_height  = pDAS->lineHeight;
667     myUiInfo.leading      = pDAS->leading;
668     myUiInfo.avg_char     = (int)(pDAS->charWidth / 10 +
669                                     ((pDAS->charWidth % 10) ? 1 : 0));
670     myUiInfo.nl_to_space  = pDAS->nl_to_space;
671
672     /*
673      * Fake the flag and give the string as the input buffer.
674      */
675     *ret_handle  = NULL;
676
677     _DtHelpCeCopyDefFontAttrList (&fontAttrs);
678     _DtHelpCeXlateOpToStdLocale(DtLCX_OPER_SETLOCALE,setlocale(LC_CTYPE,NULL),
679                                 NULL, &(fontAttrs.language),
680                                 &(fontAttrs.char_set));
681
682     varHandle = __DtHelpCeSetUpVars(fontAttrs.language, fontAttrs.char_set,
683                                                 &myUiInfo);
684     if (varHandle == NULL)
685       {
686         free(fontAttrs.language);
687         free(fontAttrs.char_set);
688         return -1;
689       }
690
691     result = __DtHelpCeProcessString (varHandle, NULL,
692                                 _DtCvDYNAMIC,
693                                 ScanString, input_string,
694                                 strlen(input_string),
695                                 0, True,
696                                 &fontAttrs);
697
698     if (result != -1)
699         result = __DtHelpCeGetParagraphList (varHandle, False, _DtCvDYNAMIC,
700                                                                 &topic);
701     *ret_handle = (XtPointer) topic;
702
703     free(fontAttrs.language);
704     free(fontAttrs.char_set);
705     free(varHandle);
706
707     return result;
708
709 }  /* End _DtHelpFormatAsciiStringDynamic */
710
711 /******************************************************************************
712  * Function:    int _DtHelpFormatTopicTitle (Display *dpy, _XvhVolume volume,
713  *                              char *filename, int offset,
714  *                              XmString *ret_title, XmFontList *ret_list,
715  *                              Boolean *ret_mod)
716  *
717  * Parameters:
718  *              dpy             Specifies the connection to the server.
719  *              volume          Specifies the Help Volume the information
720  *                              is associated with.
721  *              filename        Specifies the file containing the Help Topic
722  *                              desired.
723  *              offset          Specifies the offset into 'filename' to
724  *                              the Help Topic desired.
725  *              ret_title       Returns XmString containing the title.
726  *              ret_list        Specifies the current font list being used.
727  *                              Returns a new font list if new character
728  *                              sets are added to it.
729  *              ret_mod         Returns True if fonts were added to the
730  *                              font list.
731  *
732  * Returns:     0 if successful, -1 if errors
733  *
734  * errno Values:
735  *
736  * Purpose:     _DtHelpFormatTopicTitle formats a topic title and associates
737  *              the correct font with it.
738  *
739  ******************************************************************************/
740 int
741 _DtHelpFormatTopicTitle(
742     XtPointer             client_data,
743     _DtHelpVolumeHdl      volume_handle,
744     char                 *location_id,
745     XmString             *ret_title,
746     XmFontList           *ret_list,
747     Boolean              *ret_mod )
748 {
749     int          result = -1;
750     void        **titleChunks = NULL;
751     _FrmtUiInfo           myUiInfo = defUiInfo;
752     _DtHelpCeLockInfo     lockInfo;
753     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
754
755     /*
756      * Check the parameters
757      */
758     if (ret_title == NULL || ret_list == NULL || ret_mod == NULL)
759       {
760         errno = EINVAL;
761         return -1;
762       }
763
764     /*
765      * lock the volume
766      */
767     if (_DtHelpCeLockVolume(volume_handle, &lockInfo) != 0)
768         return -1;
769
770     /*
771      * set up my UI information
772      */
773     myUiInfo.load_graphic = _DtHelpDALoadGraphic;
774     myUiInfo.resolve_spc  = _DtHelpDAResolveSpc;
775     myUiInfo.load_font    = _DtHelpDAResolveFont;
776     myUiInfo.exec_filter  = pDAS->exec_filter;
777     myUiInfo.destroy_region = _DtHelpDADestroyRegion;
778     myUiInfo.client_data  = (_DtCvPointer) pDAS;
779     /* since we're going for chunks, set avg_char width to 1 */
780     myUiInfo.line_width   = 0;
781     myUiInfo.line_height  = 0;
782     myUiInfo.leading      = 0;
783     myUiInfo.avg_char     = 1;
784     myUiInfo.nl_to_space  = pDAS->nl_to_space;
785
786     /*
787      * Get the title and charsets associated with the title segments.
788      * The format of the returned information is
789      *          [type,charset/fontptr,]type,string/spc
790      */
791     result = _DtHelpCeGetVolumeFlag(volume_handle);
792     _DtHelpProcessLock();
793     if (result == 1)
794         result = _DtHelpCeGetSdlTitleChunks(volume_handle, location_id,
795                                 &myUiInfo, &titleChunks);
796     else if (result == 0)
797         result = _DtHelpCeGetCcdfTitleChunks( volume_handle, location_id,
798                                 &myUiInfo, &titleChunks);
799     _DtHelpProcessUnlock();
800     if (result != -1)
801         result = FormatChunksToXmString(pDAS, True, titleChunks,
802                                                 ret_title, ret_list, ret_mod);
803     _DtHelpCeUnlockVolume(lockInfo);
804     return result;
805
806 }  /* End _DtHelpFormatTopicTitle */
807
808 /******************************************************************************
809  * Function:    int _DtHelpFormatVolumeTitle (DtHelpDispAreaStruct *pDAS,
810  *                              _XvhVolume volume,
811  *                              XmString *ret_title, XmFontList *ret_list,
812  *                              Boolean *ret_mod)
813  *
814  * Parameters:
815  *              volume          Specifies the Help Volume the information
816  *                              is associated with.
817  *              ret_title       Returns XmString containing the title.
818  *              ret_list        Specifies the current font list being used.
819  *                              Returns a new font list if new character
820  *                              sets are added to it.
821  *              ret_mod         Returns True if fonts were added to the
822  *                              font list.
823  *
824  * Returns:     0 if successful, -1 if errors
825  *
826  * errno Values:
827  *
828  * Purpose:     _DtHelpFormatVolumeTitle formats a volume title and associates
829  *              the correct font with it.
830  *
831  ******************************************************************************/
832 int
833 _DtHelpFormatVolumeTitle(
834     XtPointer             client_data,
835     _DtHelpVolumeHdl      volume_handle,
836     XmString             *ret_title,
837     XmFontList           *ret_list,
838     Boolean              *ret_mod )
839 {
840     int          result = -1;
841     void        **titleChunks = NULL;
842     _FrmtUiInfo           myUiInfo = defUiInfo;
843     _DtHelpCeLockInfo lockInfo;
844     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
845
846     /*
847      * Check the parameters
848      */
849     if (ret_title == NULL || ret_list == NULL || ret_mod == NULL)
850       {
851         errno = EINVAL;
852         return -1;
853       }
854
855     /*
856      * lock the volume
857      */
858     *ret_title = NULL;
859     if (_DtHelpCeLockVolume(volume_handle, &lockInfo) != 0)
860         return -1;
861
862     /*
863      * set up my UI information
864      */
865     myUiInfo.load_graphic = _DtHelpDALoadGraphic;
866     myUiInfo.resolve_spc  = _DtHelpDAResolveSpc;
867     myUiInfo.load_font    = _DtHelpDAResolveFont;
868     myUiInfo.exec_filter  = pDAS->exec_filter;
869     myUiInfo.destroy_region = _DtHelpDADestroyRegion;
870     myUiInfo.client_data  = (_DtCvPointer) pDAS;
871     /* since we're going for chunks, set avg_char width to 1 */
872     myUiInfo.line_width   = 0;
873     myUiInfo.line_height  = 0;
874     myUiInfo.leading      = 0;
875     myUiInfo.avg_char     = 1;
876     myUiInfo.nl_to_space  = pDAS->nl_to_space;
877
878     /*
879      * Get the title and charsets associated with the volume title.
880      * The format of the returned information is
881      *          [type,charset/fontptr,]type,string/spc
882      */
883     result = _DtHelpCeGetVolumeFlag(volume_handle);
884     _DtHelpProcessLock();
885     if (result == 1)
886         result = _DtHelpCeGetSdlVolTitleChunks(volume_handle, &myUiInfo,
887                                 &titleChunks);
888     else if (result == 0)
889         result = _DtHelpCeGetCcdfVolTitleChunks(
890                                 (_DtHelpVolume) volume_handle,
891                                 &myUiInfo,
892                                 &titleChunks);
893     _DtHelpProcessUnlock();
894     if (result != -1)
895         result = FormatChunksToXmString(pDAS, True, titleChunks,
896                                                 ret_title, ret_list, ret_mod);
897     _DtHelpCeUnlockVolume(lockInfo);
898     return result;
899
900 }  /* End _DtHelpFormatVolumeTitle */
901
902 /******************************************************************************
903  * Function:    int _DtHelpFormatIndexEntries (DtHelpDispAreaStruct *pDAS,
904  *                              _XvhVolume volume,
905  *                              XmString *ret_title, XmFontList *ret_list,
906  *                              Boolean *ret_mod)
907  *
908  * Parameters:
909  *              volume          Specifies the Help Volume the information
910  *                              is associated with.
911  *              ret_cnt         number of valid entries in the array
912  *              ret_words       Returns NULL-termintaed array of 
913  *                                XmStrings containing the words.
914  *              ret_list        Specifies the current font list being used.
915  *                              Returns a new font list if new character
916  *                              sets are added to it.
917  *              ret_mod         Returns True if fonts were added to the
918  *                              font list.
919  *
920  * Returns:     0 if successful, -1 if errors
921  *
922  * errno Values:
923  *
924  * Purpose:     _DtHelpFormatIndexEntries formats index entries and associates
925  *              the correct font with it.
926  *
927  ******************************************************************************/
928 int
929 _DtHelpFormatIndexEntries(
930     XtPointer             client_data,
931     _DtHelpVolumeHdl      volume_handle,
932     int                  *ret_cnt,
933     XmString            **ret_words,
934     XmFontList           *ret_list,
935     Boolean              *ret_mod )
936 {
937     int           i;
938     int           result = -1;
939     void         *titleChunks[4];
940     char         *charSet;
941     char        **keyWords;
942     Boolean       myMod = False;
943     XmFontList    oldList;
944     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
945
946     /*
947      * Check the parameters
948      */
949     if (ret_words == NULL || ret_list == NULL || ret_mod == NULL)
950       {
951         errno = EINVAL;
952         return -1;
953       }
954
955     *ret_mod = False;
956
957     charSet = _DtHelpGetVolumeLocale(volume_handle);
958     if (charSet != NULL)
959       {
960         *ret_cnt = _DtHelpCeGetKeywordList(volume_handle, &keyWords);
961         if (*ret_cnt > 0)
962           {
963
964             *ret_words = (XmString *) malloc (sizeof(XmString) * (*ret_cnt+1));
965             if (*ret_words == NULL)
966                 return -1;
967
968             /* the order of the string ptr and charset ptr in the titleChunks
969                is determined by the order of the if(..) tests on the
970                flags and subsequent processing in FormatChunksToXmString() */
971             titleChunks[0] = (void *) (DT_HELP_CE_STRING | DT_HELP_CE_CHARSET);
972             titleChunks[1] = (void *) charSet;
973             titleChunks[3] = (void *) DT_HELP_CE_END;
974             for (i = 0, result = 0; result == 0 && i < *ret_cnt; i++)
975               {
976                 oldList        = *ret_list;
977                 titleChunks[2] = (void *) keyWords[i];
978                 result = FormatChunksToXmString(pDAS, False, titleChunks,
979                                 &(*ret_words)[i], ret_list, &myMod);
980                 if (myMod == True)
981                   {
982                     /*
983                      * if the list has been modified before,
984                      * free the previously modified list.
985                      */
986                     if (True == *ret_mod)
987                         XmFontListFree(oldList);
988
989                     *ret_mod = True;
990                   }
991               }
992             (*ret_words)[i] = NULL;
993           }
994         free(charSet);
995       }
996
997     return result;
998
999 }  /* End _DtHelpFormatIndexEntries */
1000
1001 /******************************************************************************
1002  * Function:    int _DtHelpFormatTopic (
1003  *                              DtHelpDispAreaStruct *pDAS,
1004  *                              _DtHelpVolumeHdl volume,
1005  *                              char *id_string,
1006  *                              Boolean look_at_id,
1007  *                              XtPointer *ret_handle)
1008  *
1009  * Parameters:
1010  *              pDAS            Specifies the display area to use.
1011  *              volume          Specifies the Help Volume the information
1012  *                              is associated with.
1013  *              id_string       Specifies the location id for the topic.
1014  *                              This location id can be contained in a
1015  *                              topic.
1016  *              look_at_id      Specifies whether or not to start the
1017  *                              display of the topic at the location id.
1018  *              ret_handle      Returns a handle to the topic information
1019  *                              including the number of paragraphs and the
1020  *                              id match segment.
1021  *
1022  * Returns:     0       if successful.
1023  *              -1      if errors.
1024  *              -2      if the id was not found.
1025  *              -3      if unable to format the topic.
1026  *
1027  * errno Values:
1028  *
1029  * Purpose:     _DtHelpParseTopic accesses and parses Help topics.
1030  *
1031  ******************************************************************************/
1032 int
1033 _DtHelpFormatTopic(
1034         XtPointer         client_data,
1035         _DtHelpVolumeHdl  volume,
1036         char             *id_string,
1037         Boolean           look_at_id,
1038         XtPointer        *ret_handle )
1039 {
1040     char  *filename = NULL;
1041     int    offset;
1042     int    result = -2;
1043     _DtHelpCeLockInfo   lockInfo;
1044     _FrmtUiInfo           myUiInfo = defUiInfo;
1045     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
1046     _DtCvTopicInfo      *topic;
1047
1048     if (_DtHelpCeLockVolume(volume, &lockInfo) != 0)
1049         return -1;
1050
1051     if (_DtHelpCeFindId(volume,id_string,lockInfo.fd,&filename,&offset)==True)
1052       {
1053         if (look_at_id == False)
1054             id_string = NULL;
1055
1056         myUiInfo.load_graphic = _DtHelpDALoadGraphic;
1057         myUiInfo.resolve_spc  = _DtHelpDAResolveSpc;
1058         myUiInfo.load_font    = _DtHelpDAResolveFont;
1059         myUiInfo.exec_filter  = pDAS->exec_filter;
1060         myUiInfo.destroy_region = _DtHelpDADestroyRegion;
1061         myUiInfo.client_data  = (_DtCvPointer) pDAS;
1062         myUiInfo.line_width   = pDAS->lineThickness;
1063         myUiInfo.line_height  = pDAS->lineHeight;
1064         myUiInfo.leading      = pDAS->leading;
1065         myUiInfo.avg_char     = (int)(pDAS->charWidth / 10 +
1066                                         ((pDAS->charWidth % 10) ? 1 : 0));
1067         myUiInfo.nl_to_space  = pDAS->nl_to_space;
1068
1069         result = _DtHelpCeGetVolumeFlag(volume);
1070         _DtHelpProcessLock();
1071         if (result == 1)
1072             result = _DtHelpCeParseSdlTopic(volume,
1073                                                 &myUiInfo,
1074                                                 lockInfo.fd, offset,
1075                                                 id_string, True, &topic);
1076         else if (result == 0)
1077             result = _DtHelpCeFrmtCcdfTopic((_DtHelpVolume) volume,
1078                                                 filename, offset,
1079                                                 id_string,
1080                                                 &myUiInfo, &topic);
1081         _DtHelpProcessUnlock();
1082         *ret_handle = (XtPointer) topic;
1083         if (result != 0)
1084             result = -3;
1085
1086         if (filename != NULL)
1087             free(filename);
1088       }
1089
1090     _DtHelpCeUnlockVolume(lockInfo);
1091
1092     return result;
1093
1094 }  /* End _DtHelpFormatTopic */
1095
1096
1097 /******************************************************************************
1098  * Function:    int _DtHelpGetAsciiVolumeTitle (
1099  *
1100  * Parameters:  vol             Specifies the loaded volume.
1101  *              retTitle        Returns the title of the volume. This string is
1102  *                              owned by the caller and must be freed.
1103  *
1104  * Return Value: 0 if successful, -1 if a failure occurs
1105  *
1106  * errno Values:        CEErrorMalloc
1107  *                      EINVAL          'vol' or 'retTitle' is NULL.
1108  *                      CEErrorMissingTitleRes
1109  *                                      'vol' does not contain the resource
1110  *                                      'Title' or 'title' or the resource
1111  *                                      is zero length.
1112  *
1113  * Purpose:     Get the title of a volume.
1114  *
1115  ******************************************************************************/
1116 int 
1117 _DtHelpGetAsciiVolumeTitle (
1118      XtPointer            client_data,
1119     _DtHelpVolumeHdl      volume,
1120     char                **ret_title)
1121 {
1122     int                   result;
1123     _FrmtUiInfo           myUiInfo = defUiInfo;
1124     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
1125
1126     /*
1127      * What type of volume is it?
1128      */
1129     result = _DtHelpCeGetVolumeFlag(volume);
1130     if (1 == result)
1131       {
1132         /*
1133          * set up my UI information
1134          */
1135         myUiInfo.load_graphic = _DtHelpDALoadGraphic;
1136         myUiInfo.resolve_spc  = _DtHelpDAResolveSpc;
1137         myUiInfo.load_font    = _DtHelpDAResolveFont;
1138         myUiInfo.exec_filter  = pDAS->exec_filter;
1139         myUiInfo.destroy_region = _DtHelpDADestroyRegion;
1140         myUiInfo.client_data  = (_DtCvPointer) pDAS;
1141         /* since we're going for a string, set avg_char width to 1 */
1142         myUiInfo.line_width   = 0;
1143         myUiInfo.line_height  = 0;
1144         myUiInfo.leading      = 0;
1145         myUiInfo.avg_char     = 1;
1146         myUiInfo.nl_to_space  = pDAS->nl_to_space;
1147
1148         _DtHelpProcessLock();
1149         result = _DtHelpCeFrmtSDLVolTitleToAscii(volume, &myUiInfo, ret_title);
1150       }
1151     else if (0 == result)
1152       {
1153         _DtHelpProcessLock();
1154         result = _DtHelpCeGetCcdfVolumeTitle(volume, ret_title);
1155       }
1156     _DtHelpProcessUnlock();
1157     return result;
1158 }
1159
1160 /*****************************************************************************
1161  * Function:    int _DtHelpFormatToc (
1162  *                      _DtHelpVolumeHdl volume, id);
1163  *
1164  * Parameters:
1165  *              canvas          Specifies the handle for the canvas.
1166  *
1167  * Returns:     -1 if errors.
1168  *               0 if no errors. 
1169  *               1 if empty path.
1170  *
1171  * Purpose:
1172  *
1173  *****************************************************************************/
1174 int
1175 _DtHelpFormatToc (
1176     DtHelpDispAreaStruct        *pDAS,
1177     _DtHelpVolumeHdl             volume,
1178     char                         *id,
1179     char                        **ret_id,
1180     XtPointer                    *ret_handle)
1181 {
1182     int             result   = 0;
1183     _DtCvTopicPtr    topic;
1184     _DtHelpCeLockInfo lockInfo;
1185
1186     if (volume == NULL || id == NULL)
1187         return -1;
1188
1189     /*
1190      * This becomes my volume; want to ensure that it doesn't
1191      * get closed out from under me, so tell the system that
1192      * i'm using it.
1193      */
1194     if (_DtHelpCeLockVolume(volume, &lockInfo) != 0)
1195         return -1;
1196
1197     result = _DtHelpCeMapTargetToId(volume, id, ret_id);
1198
1199     if (result == 0)
1200       {
1201         _FrmtUiInfo  myUiInfo = defUiInfo;
1202
1203         myUiInfo.client_data  = (XtPointer) pDAS;
1204         myUiInfo.load_graphic = _DtHelpDALoadGraphic;
1205         myUiInfo.resolve_spc  = _DtHelpDAResolveSpc;
1206         myUiInfo.load_font    = _DtHelpDAResolveFont;
1207         myUiInfo.exec_filter  = pDAS->exec_filter;
1208         myUiInfo.destroy_region = _DtHelpDADestroyRegion;
1209         myUiInfo.client_data  = (_DtCvPointer) pDAS;
1210         myUiInfo.line_width   = pDAS->lineThickness;
1211         myUiInfo.line_height  = pDAS->lineHeight;
1212         myUiInfo.leading      = pDAS->leading;
1213         myUiInfo.avg_char     = (int)(pDAS->charWidth / 10 +
1214                                         ((pDAS->charWidth % 10) ? 1 : 0));
1215         myUiInfo.nl_to_space  = pDAS->nl_to_space;
1216
1217         result = _DtHelpCeGetVolumeFlag(volume);
1218         _DtHelpProcessLock();
1219         if (result == 1)
1220             result = _DtHelpCeFrmtSdlPathAndChildren(volume,
1221                                                         &myUiInfo,
1222                                                         lockInfo.fd,
1223                                                         *ret_id, &topic);
1224         else if (result == 0)
1225             result = _DtHelpCeFrmtCcdfPathAndChildren(volume,
1226                                                         *ret_id,
1227                                                         &myUiInfo, &topic);
1228         _DtHelpProcessUnlock();
1229         *ret_handle = (XtPointer) topic;
1230       }
1231     /*
1232      * didn't successfully format a path, so close my copy
1233      * of the volume.
1234      */
1235     else
1236         _DtHelpCloseVolume (volume);
1237
1238     _DtHelpCeUnlockVolume(lockInfo);
1239     return result;
1240
1241 } /* End _DtHelpFormatToc */