2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 /*===================================================================
25 $FILEBEG$: PrintTopics.c
26 $COMPONENT$: dthelpprint
28 $SYSTEM$: HPUX 9.0; AIX 3.2; SunOS 5.3
29 $REVISION$: $TOG: PrintTopics.c /main/12 1998/04/01 17:26:51 mgreess $
31 (c) Copyright 1996 Digital Equipment Corporation.
32 (c) Copyright 1993,1994,1996 Hewlett-Packard Company.
33 (c) Copyright 1993,1994,1996 International Business Machines Corp.
34 (c) Copyright 1993,1994,1996 Sun Microsystems, Inc.
35 (c) Copyright 1993,1994,1996 Novell, Inc.
36 (c) Copyright 1996 FUJITSU LIMITED.
37 (c) Copyright 1996 Hitachi.
38 ==$END$==============================================================*/
45 #include <sys/stat.h> /* for stat() */
46 #if defined(sun) || defined(USL)
56 /* Iconv not defined for linux. Use the EUSCompat stubs instead. */
60 # include <EUSCompat.h>
66 #include "HelpPrintI.h" /* helpprint */
68 #include "HelpTermP.h" /* from libDtHelp */
69 #include "CanvasP.h" /* from libDtHelp */
70 #include "StringFuncsI.h" /* from libDtHelp */
71 #include "LocaleXlate.h" /* from libDtHelp */
72 #include "bufioI.h" /* from libDtHelp; required for AccessI.h */
73 #include "FileUtilsI.h" /* from libDtHelp */
74 #include "GenUtilsP.h" /* from libDtHelp */
76 /*#include "AccessI.h" ** from libDtHelp */
77 /* I can't include AccessI.h because it redefines the Boolean type,
78 which is also defined in Xt/Intrisincs.h. I'm just including the
79 prototypes from AccessI.h here. */
80 extern char * _DtHelpCeGetVolumeLocale(VolumeHandle helpVolumeHandle);
81 extern const char * _DtHelpCeGetVolumeCharSet(VolumeHandle helpVolumeHandle);
83 /*======== platform adjustments ==============*/
85 #define wcswidth(s,n) wscol(s)
86 #define wcslen(s) wslen(s)
89 /*======== boundary values ==============*/
90 #define MAXSECTS 50 /* max number of section nesting */
92 #define MAXVOLTITLEWIDTH 50
93 #define MAXTOPICTITLEWIDTH 50
94 #define MAXPAGENUMWIDTH 3
95 #define MAXSECTNUMWIDTH 8
97 /*======== helper values ===============*/
99 #define EMPTY_STR s_EmptyStr
101 #define PTSET 3 /* message set */
104 /*======== helper variables ===============*/
105 static char s_EmptyStr[1] = { EOS };
108 * check roman 8/Latin 1
109 * check PAGER env variable
113 /*======== data structs ==============*/
115 /* These data structs manage the table of contents (Toc)
116 of a help volume. The Toc uses two organizational mechanisms:
117 a linear table of entries, which gives sequential order
118 and is used to generate the TOC; and a binary tree of entries
119 that is sorted alphabetically by location id, and is used to
120 speed lookup of the page number of a locationId for use in
121 generating the index. */
124 ===================================================================
126 $1LINER$: All data for a single toc entry
129 ========================================================$SKIP$=====*/
132 typedef struct TocEntry
134 struct TocEntry * nextEntry; /* next entry in the linear list */
135 struct TocEntry * leftLoc; /* left location of sorted binary tree */
136 struct TocEntry * rightLoc; /* right location of sorted binary tree */
137 char * locationId; /* locationId of the topic */
138 int pageNumber; /* page the topic located on */
139 int level; /* nesting level */
140 int sectNums[MAXSECTS]; /* section numbers */
141 char * sectStr; /* alternate section string */
146 ===================================================================
148 $1LINER$: Manages the toc entries in a volume
151 ========================================================$SKIP$=====*/
156 TocEntry * linearEntries; /* ptr to head of linear list of entries */
157 TocEntry * lastLinearEntry; /* ptr to tail of linear list of entries */
158 TocEntry * sortedEntries; /* ptr to top of sorted btree of entries */
163 ===================================================================
164 $PTYPEBEG$: HeadFootFormat
165 $1LINER$: All data related to the header/footer formatting
168 ========================================================$SKIP$=====*/
171 typedef struct HeadFootFormat
173 char * formattedEvenHeader; /* formatted even-page header when printing volume */
174 char * formattedOddHeader; /* formatted odd-page header when printing volume */
175 char * formattedEvenFooter; /* formatted even-page footer when printing volume */
176 char * formattedOddFooter; /* formatted odd-page footer when printing volume */
177 int evenHeaderLineCnt; /* num lines in even-page header when printing volume */
178 int oddHeaderLineCnt; /* num lines in odd-page header when printing volume */
179 int evenFooterLineCnt; /* num lines in even-page footer when printing volume */
180 int oddFooterLineCnt; /* num lines in odd-page footer when printing volume */
185 ===================================================================
186 $PTYPEBEG$: HeadFootFormatArgs
187 $1LINER$: Arguments used in head/foot formatting
190 ========================================================$SKIP$=====*/
193 typedef struct HeadFootFormatArgs
196 int volumeTitleColsWidth;
198 int topicTitleColsWidth;
200 int volumeDateColsWidth;
202 int todaysDateColsWidth;
203 int sectNumColsWidth;
204 int pageNumColsWidth;
210 ===================================================================
211 $PTYPEBEG$: PrintState
212 $1LINER$: All data related to the on-going printing operation
215 ========================================================$SKIP$=====*/
218 typedef struct PrintState
220 char * currentLocId; /* current loc Id in volume */
221 char * outputFromLocId; /* start output at this location */
222 HeadFootFormatArgs hffArgs; /* arguments used in head/foot formatting */
223 HeadFootFormat tocHFF; /* HF formatting info for TOC */
224 HeadFootFormat bodyHFF; /* HF formatting info for body */
225 HeadFootFormat indexHFF; /* HF formatting info for index */
226 Boolean inhibitOutput; /* inhibit output */
227 int curPageNumber; /* page number of current output */
228 int curLineNumber; /* line number of current page of output */
229 VolumeHandle volHandle; /* volume handle of volume being printed */
230 CanvasHandle canvasHandle; /*canvas handle of terminal format canvas*/
231 int sectNums[MAXSECTS]; /* current section number */
232 char * sectStr; /* current section string value */
233 int level; /* level of section nesting */
237 /*======== static variables ===============*/
240 ===================================================================
242 $1LINER$: Maps a symbolic string to a printf-format string.
245 ========================================================$SKIP$=====*/
248 typedef struct SymValue
254 /* List of symbols that can be used in header/footer strings
255 and the printf args that are used to access the data. */
256 /* NOTE: ***IT IS CRITICAL THAT THE SYMBOL STRING HAVE THE
257 SAME OR LONGER LENGTH THAN THE ARGUMENT STRING. ***/
258 /* NOTE: ***ALWAYS UPDATE THE UNUSED_ARGREF AND THE sprintf() CALL
259 IN PrintHeadFootStr() WHEN ADDING NEW SYMBOLS***/
260 /* NOTE: The replacement values use a trick to get around the limitations
261 of printf(), which only allows args numbered 1 to 9. The strategy
262 is to do two printfs, and to use the %% construct in the first string
263 to generate a % construct in the second string. */
264 SymValue g_HeadFootSymsList[] =
266 { "$VOLUMEFILL", "%%2$*1$c" }, /* filler for fixed sized volume name */
267 { "$TOPICFILL", "%%4$*3$c" }, /* filler for fixed sized current topic title */
268 { "$PAGENUMFILL", "%%6$*5$c" }, /* filler for fixed sized page number */
269 { "$SECTNUMFILL", "%%8$*7$c" }, /* filler for fixed sized section number or name */
270 { "$TODAY", "%1$s" }, /* today's date */
271 { "$VOLUME", "%2$s" }, /* volume name */
272 { "$TOPIC", "%3$s" }, /* current topic title */
273 { "$PAGENUM", "%4$d" }, /* page number */
274 { "$VOLDATE", "%5$s" }, /* date on the help volume file */
275 { "$SECTNUM", "%6$s" }, /* section number or name */
276 { "$LMARGIN", "%8$*7$c" }, /* left margin blanks; args 7 & 8 */
279 #define UNUSED_ARGREF "%%9$n" /* arg to hold the num of unused args */
283 /*======== functions ==============*/
286 ===================================================================
287 $PFUNBEG$: TocNextEntry()
288 $1LINER$: Get next entry in the toc
293 NULL: no more entires
294 ========================================================$SKIP$=====*/
298 TocEntry * TocNextEntry(
302 if (NULL == entry) return toc->linearEntries;
303 return entry->nextEntry;
308 ===================================================================
309 $PFUNBEG$: TocFindSortedEntry()
310 $1LINER$: Finds an entry using the sorted btree of entries
316 ========================================================$SKIP$=====*/
320 int TocFindSortedEntry(
323 TocEntry * * ret_parent,
324 TocEntry * * ret_entry)
330 if (NULL == ret_parent) ret_parent = &tmp;
331 if (NULL == ret_entry) ret_entry = &tmp;
336 prev = toc->sortedEntries;
338 while ( NULL != cur )
341 cmp = _DtHelpCeStrCaseCmp(locationId,cur->locationId);
343 prev = cur, cur = cur->leftLoc;
345 prev = cur, cur = cur->rightLoc;
348 *ret_parent = prev, *ret_entry = cur;
349 return 0; /* RETURN: found */
353 return -1; /* RETURN: not found */
358 ===================================================================
359 $PFUNBEG$: TocNewEntry()
360 $1LINER$: Add a Toc entry to the Toc
365 -1: memory allocation error
366 ========================================================$SKIP$=====*/
380 new = calloc(1,sizeof(TocEntry));
381 if (NULL == new) return -1; /* RETURN: mem alloc err */
384 new->locationId = strdup(locationId);
385 new->pageNumber = pageNumber;
387 new->sectStr = sectStr;
388 memcpy(new->sectNums, sectNums, sizeof(new->sectNums));
390 if (NULL == new->locationId)
391 { free(new); return -1; } /* RETURN: mem alloc err */
393 /*** insert into toc ***/
395 /* if first in list */
396 if (NULL == toc->linearEntries)
398 toc->linearEntries = new;
399 toc->lastLinearEntry = new;
400 toc->sortedEntries = new;
402 else /* not first in list */
404 TocEntry * parent, * entry;
406 if ( TocFindSortedEntry(toc,locationId,&parent,&entry) == 0 )
407 return -2; /* RETURN: duplicate entry */
408 /* insert into the btree (not balanced) */
409 if( _DtHelpCeStrCaseCmp(locationId,parent->locationId) < 0 )
410 parent->leftLoc = new;
412 parent->rightLoc = new;
413 /* insert into the linear list */
414 toc->lastLinearEntry->nextEntry = new;
415 toc->lastLinearEntry = new;
417 return 0; /* RETURN: ok */
422 ===================================================================
423 $PFUNBEG$: IconvFile()
424 $1LINER$: Compares cur env and volume and iconv file if necessary
427 0: no conversion needed or not possible to determine if needed
428 1: conversion needed & successful
429 -1: conversion needed and failed
431 ========================================================$SKIP$=====*/
436 _DtHPrOptions * options,
437 VolumeHandle helpVolumeHandle,
441 #define CUR_CODESET 1
443 #define VOL_CODESET 3
444 #define FROM_CODESET 4
451 char * destFile = NULL;
455 for (i=0; i<NUMSTRS; i++) loc[i] = NULL;
457 /* get the normalized current codeset */
458 _DtHelpCeXlateOpToStdLocale (
459 DtLCX_OPER_SETLOCALE, setlocale(LC_CTYPE,NULL),
460 &loc[CUR_LOCALE], NULL, &loc[CUR_CODESET]);
462 /* get the normalized volume codeset */
463 loc[VOL_LOCALE] = _DtHelpCeGetVolumeLocale(helpVolumeHandle);
465 /* codeset begins after the '.'; find it */
468 && _DtHelpCeStrchr(loc[VOL_LOCALE], ".", 1, &codeset) == 0)
472 loc[VOL_CODESET] = (NULL != codeset ? strdup(codeset) : NULL);
474 /* if either locale is NULL or if they are the same string
475 then don't iconv the file */
476 if ( NULL == loc[CUR_CODESET]
477 || NULL == loc[VOL_CODESET]
478 || strcmp(loc[CUR_CODESET],loc[VOL_CODESET]) == 0 )
480 ret = 0; /* RETURN: no iconv needed/possible */
484 /* get the source codeset */
485 _DtHelpCeXlateStdToOpLocale (
486 DtLCX_OPER_ICONV1, loc[VOL_LOCALE],
487 "iso8859_1", &loc[FROM_CODESET]);
489 /* get the target codeset */
490 _DtHelpCeXlateStdToOpLocale (
491 DtLCX_OPER_ICONV1, loc[CUR_LOCALE],
492 "iso8859_1", &loc[TO_CODESET]);
494 /* construct the command line */
495 destFile = _DtHPrCreateTmpFile(TMPFILE_PREFIX,TMPFILE_SUFFIX);
496 if (NULL == destFile)
498 ret = -1; /* error */
502 sprintf(buf,options->iconvCmdAndArgs,
503 loc[FROM_CODESET],loc[TO_CODESET],*srcFile, destFile);
505 /* do the conversion */
506 if(options->debugHelpPrint) printf("%s\n",buf);
508 ret = (ret == 0 ? 1 : -1); /* 1: success; -1: failure */
510 /* if successful conversion, change the src file */
524 for (i=0; i<NUMSTRS; i++) if (loc[i]) free(loc[i]);
529 #ifdef ICONV_INBUF_CONST
530 # define ICONV_INBUF_TYPE const char **
532 # define ICONV_INBUF_TYPE char **
535 #define WORKSIZE 1024*10 /* 10k */
538 * _i18nwork1[] is used to convert the passed string with CD iconv.
542 static void *_i18nwork1 = NULL;
543 static unsigned long _i18nsize1 = 0;
544 static int shouldAlloc1 = ~0;
547 static void _converter_( iconv_t CD,
548 void *from, unsigned long from_len,
554 size_t OutBytesLeft = 0;
555 size_t _OutBytesLeft = 0;
557 size_t converted_num = 0;
558 unsigned long to_len;
564 if ( shouldAlloc1 ) {
565 /* Obtain work area */
566 _i18nwork1 = (size_t *)malloc( WORKSIZE );
571 _i18nsize1 = WORKSIZE;
575 InBuf = (char *)from;
576 InBytesLeft = from_len;
577 OutBytesLeft = _i18nsize1;
578 OutBuf = (char *)_i18nwork1;
581 * Need to place iconv state to the initial one by
582 * setting inbuf to NULL of iconv().
584 iconv( CD, (ICONV_INBUF_TYPE)NULL, 0, NULL, 0 );
589 * +----------------------------+
591 * +----------------------------+
592 * <-------------------------->
601 * +----------------------------+
603 * +----------------------------+
604 * <-------------------------->
608 iconv_ret = iconv( CD, (ICONV_INBUF_TYPE)&InBuf, &InBytesLeft,
609 &OutBuf, &OutBytesLeft );
610 if ( iconv_ret == 0 ) {
614 * +----------------------------+
615 * |XXXXXXXXXXXXXXXXXXXXXXXXXXXX|
616 * +----------------------------+
623 * +----------------------------+
624 * |XXXXXXXXXXXXXXXXX| | | |
625 * +----------------------------+
626 * <---------------> <-------->
627 * converted_num OutBytesLeft
629 converted_num = (unsigned long)((char *)OutBuf-(char *)_i18nwork1);
630 *to = (void *)_i18nwork1;
631 to_len = (unsigned long)converted_num;
634 if ( errno == E2BIG ) {
635 /* Overflow. still data is left.
638 * +----------------------------+
639 * |XXXXXXXXXXXXXX| | | |
640 * +----------------------------+
647 * +----------------------------+
648 * |XXXXXXXXXXXXXXXXXXXXXXXXXXX |
649 * +----------------------------+
650 * <------------------------->
651 * converted_num OutBytesLeft=?
655 /* Check how many converted already. */
657 (unsigned long)((char *)OutBuf - (char *)_i18nwork1);
658 _i18nsize1 += WORKSIZE;
659 _p = realloc( _i18nwork1, _i18nsize1 );
670 OutBuf = (char *)((char*)_i18nwork1 + converted_num);
671 OutBytesLeft += WORKSIZE;
686 if ( _i18nsize1 >= to_len + 1 ) {
687 ((char *)_i18nwork1)[to_len] = '\0';
692 _p = realloc( _i18nwork1, _i18nsize1 );
702 ((char *)_i18nwork1)[to_len] = '\0';
713 VolumeHandle helpVolumeHandle,
718 #define CUR_CODESET 1
720 #define VOL_CODESET 3
721 #define FROM_CODESET 4
730 static int isFirst = ~0;
731 static iconv_t CD = (iconv_t)-1;
733 for (i=0; i<NUMSTRS; i++) loc[i] = NULL;
735 /* get the normalized current codeset */
736 _DtHelpCeXlateOpToStdLocale (
737 DtLCX_OPER_SETLOCALE, setlocale(LC_CTYPE,NULL),
738 &loc[CUR_LOCALE], NULL, &loc[CUR_CODESET]);
740 /* get the normalized volume codeset */
741 loc[VOL_LOCALE] = _DtHelpCeGetVolumeLocale(helpVolumeHandle);
743 /* codeset begins after the '.'; find it */
746 && _DtHelpCeStrchr(loc[VOL_LOCALE], ".", 1, &codeset) == 0)
750 loc[VOL_CODESET] = (NULL != codeset ? strdup(codeset) : NULL);
752 /* if either locale is NULL or if they are the same string
753 then don't iconv the file */
754 if ( NULL == loc[CUR_CODESET]
755 || NULL == loc[VOL_CODESET]
756 || strcmp(loc[CUR_CODESET],loc[VOL_CODESET]) == 0 )
758 ret = 0; /* RETURN: no iconv needed/possible */
762 /* get the source codeset */
763 _DtHelpCeXlateStdToOpLocale (
764 DtLCX_OPER_ICONV1, loc[VOL_LOCALE],
765 "iso8859_1", &loc[FROM_CODESET]);
767 /* get the target codeset */
768 _DtHelpCeXlateStdToOpLocale (
769 DtLCX_OPER_ICONV1, loc[CUR_LOCALE],
770 "iso8859_1", &loc[TO_CODESET]);
773 CD = iconv_open( loc[TO_CODESET], loc[FROM_CODESET] );
776 if ( CD == (iconv_t)-1 ) {
780 _converter_( CD, (void *)src, (unsigned long)strlen( src ),
787 for (i=0; i<NUMSTRS; i++) if (loc[i]) free(loc[i]);
795 ===================================================================
796 $PFUNBEG$: OpenTmpFile()
797 $1LINER$: Opens temporary file
799 opens a temporary file
802 ========================================================$SKIP$=====*/
807 _DtHPrOptions * options,
808 char * * ret_tmpFile)
812 /* Put in $HOME/.dt/tmp so that if the printer operation is running
813 of a remote system, it can get to the (local) temp file.
814 This would not be possible if the file were put in /tmp */
815 *ret_tmpFile = _DtHPrCreateTmpFile(TMPFILE_PREFIX,TMPFILE_SUFFIX);
816 if (NULL == *ret_tmpFile) return NULL; /* RETURN: error */
818 fp = fopen(*ret_tmpFile,"w");
821 fprintf(stderr,_DTGETMESSAGE(PTSET,6,
822 "%s Error: unable to open temporary file %s\n"),
823 options->programName, *ret_tmpFile);
827 } /* open tmp file */
831 ===================================================================
832 $PFUNBEG$: CountLines()
833 $1LINER$: counters number of CRs in a string
835 counters number of CRs in a string
838 ========================================================$SKIP$=====*/
847 static char * newLine = "\n";
850 while( _DtHelpCeStrchr(substr,newLine,MB_CUR_MAX,&substr) == 0 )
855 /* return line count to caller */
862 ===================================================================
863 $PFUNBEG$: AvailContentLines()
864 $1LINER$: count number of lines available between top of page & footer
866 Count number of lines available between top of page & footer
869 ========================================================$SKIP$=====*/
872 int AvailContentLines(
873 _DtHPrOptions * options,
875 HeadFootFormat * hff)
877 return options->rowsTextHeight -
878 ( (state->curPageNumber % 2) == 0
879 ? hff->evenFooterLineCnt
880 : hff->oddFooterLineCnt);
886 ===================================================================
887 $PFUNBEG$: SectNumStr()
888 $1LINER$: generates string ver of section number
890 generates string ver of section number
893 buf: must be at least 4 * MAXSECTS chars long
894 ========================================================$SKIP$=====*/
905 /* recall: if sectNums[0] == 0, then no section number is defined
906 and none should be printed; try sectStr as alternate. */
908 /* generate the section number */
910 if (sectNums && sectNums[0] != 0 )
913 for ( sect = 1; sectNums[sect] != 0; sect++ )
915 sprintf(partial, "%d.", sectNums[sect]);
919 else /* if no section number, take the section string, if avail */
921 if (sectStr) strcpy(buf,sectStr);
930 ===================================================================
931 $PFUNBEG$: OutputBlankSpaces()
932 $1LINER$: Outputs blank Spaces
937 topicsFP: pointer to output stream. If NULL, do nothing
938 ========================================================$SKIP$=====*/
942 void OutputBlankSpaces(
946 if (NULL == topicsFP || spaceCount < 0) return;
947 while (spaceCount--) fprintf(topicsFP," ");
952 ===================================================================
953 $PFUNBEG$: OutputBlankLines()
954 $1LINER$: Outputs blank lines
959 topicsFP: pointer to output stream. If NULL, do nothing
960 ========================================================$SKIP$=====*/
964 void OutputBlankLines(
969 if (lineCount < 0) return; /* RETURN */
970 state->curLineNumber += lineCount;
971 if (NULL == topicsFP) return; /* RETURN */
972 while (lineCount--) fprintf(topicsFP,"\n");
977 ===================================================================
978 $PFUNBEG$: DoStrColsWidth()
979 $1LINER$: Calculates number of cols used by a string; truncate if needed
981 Calculates the number of cols used by the string and truncates
982 the string to the specified maxWidth if this is exceeded.
985 The number of columns this string requires for printing.
987 ========================================================$SKIP$=====*/
1001 /* alloc memory for the wchar_t string */
1003 wcstr = malloc(sizeof(wchar_t) * (len+1));
1005 /* convert str to wchar_t and get width in chars */
1006 mbstowcs(wcstr,str,len+1);
1007 wclen = wcslen(wcstr);
1009 /* get col width of the string and truncate if necessary */
1010 while ( (width = wcswidth(wcstr,wclen+1)) > maxWidth
1011 && truncateStr == True)
1012 wcstr[--wclen] = EOS;
1013 wcstombs(str,wcstr,len+1);
1023 ===================================================================
1024 $PFUNBEG$: GenHeadFootFormatArgs()
1025 $1LINER$: Generates args used by a header/footer format string
1027 Generates args used by a header/footer format string
1031 ========================================================$SKIP$=====*/
1035 void GenHeadFootFormatArgs(
1036 _DtHPrOptions * options,
1038 Boolean updateTopicTitle,
1040 Boolean updatePageNum)
1048 /* get the volume title and its size */
1049 if (NULL == state->hffArgs.volumeTitle)
1051 /* get the volume title */
1053 _DtHelpCeGetVolumeTitle(state->canvasHandle,state->volHandle,&str);
1054 if (NULL == str) str = strdup("");
1056 width = DoStrColsWidth(str,MAXVOLTITLEWIDTH,True);
1058 /* put into state data */
1059 state->hffArgs.volumeTitle = str;
1060 state->hffArgs.volumeTitleColsWidth = width;
1063 /* get the volume's date */
1064 if (NULL == state->hffArgs.volumeDate)
1066 char * locDocId = NULL;
1067 char * locDateStamp = NULL;
1070 /* locDocId & locDateStamp will point to private memory; do not modify */
1071 _DtHelpCeGetDocStamp(state->volHandle,&locDocId, &locDateStamp);
1072 if ( NULL != locDateStamp
1073 && sscanf(locDateStamp, "%ld", &long_date) != 1 )
1074 locDateStamp = NULL; /* make invalid */
1076 date = (time_t)long_date;
1078 /* if no vol date, try getting from the help volume file */
1079 if ( NULL == locDateStamp )
1083 if ( stat(options->helpVolume,&stats) == 0 )
1084 date = stats.st_mtime;
1087 /* convert the int into a string */
1088 pTm = localtime(&date);
1089 strftime(buf,sizeof(buf),"%x",pTm);
1091 width = DoStrColsWidth(buf,0,False);
1093 /* put into state data */
1094 state->hffArgs.volumeDate = strdup(buf);
1095 state->hffArgs.volumeDateColsWidth = width;
1101 /* get today's date */
1102 if (NULL == state->hffArgs.todaysDate)
1104 /* convert the int into a string */
1106 pTm = localtime(&date);
1107 strftime(buf,sizeof(buf),"%x",pTm);
1109 width = DoStrColsWidth(buf,0,False);
1111 /* put into state data */
1112 state->hffArgs.todaysDate = strdup(buf);
1113 state->hffArgs.todaysDateColsWidth = width;
1116 /* get the topic title and its size */
1117 if (updateTopicTitle)
1119 /* get the topic title */
1121 _DtHelpCeGetTopicTitle(state->canvasHandle, state->volHandle,
1122 state->currentLocId, &str);
1123 if (NULL == str) str = strdup("");
1125 width = DoStrColsWidth(str,MAXTOPICTITLEWIDTH,True);
1127 /* put into state data */
1128 if (state->hffArgs.topicTitle) free(state->hffArgs.topicTitle);
1129 state->hffArgs.topicTitle = str;
1130 state->hffArgs.topicTitleColsWidth = width;
1133 /* get the size of the section number */
1136 width = DoStrColsWidth(sectNumStr,0,False);
1137 state->hffArgs.sectNumColsWidth = width;
1140 /* get the size of the page number */
1144 for ( width = 1, num = state->curPageNumber;
1145 (num >= 0) && ((num / 10) > 0);
1146 num /= 10, width++ )
1147 { /* do nothing */ }
1148 state->hffArgs.pageNumColsWidth = width;
1154 ===================================================================
1155 $PFUNBEG$: GenHeadFootFormatStr()
1156 $1LINER$: Generates a printf-ready format string for the header/footer
1158 Generates a printf-ready format string for the header/footer
1160 This function generates a string that uses the "%n$" prefix
1161 supported by printf(3S) to allow a footer/header string to
1162 ref any argument out of order. This functionality requires
1163 that a ref to *every* argument be part of the format string.
1164 Because not all args may be part of the user-specified format
1165 string, this function appends the unused strings to the end
1166 of the format string for purposes of sprintf(), then truncates
1167 the unused portion before output.
1170 ========================================================$SKIP$=====*/
1174 void GenHeadFootFormatStr(
1176 char * * io_formattedStr,
1179 char * lowLevelFormatStr;
1182 char unusedSyms[60];
1184 if (NULL == specStr)
1186 *io_formattedStr = NULL;
1188 return; /* RETURN */
1191 /*** create the formatted string ***/
1193 /* Make a working copy of the string; I assume that the
1194 values of 'argref' string always be shorter than 'symbol'. */
1195 lowLevelFormatStr = malloc(strlen(specStr) + sizeof(unusedSyms) + 10);
1196 if (NULL == lowLevelFormatStr) return;
1197 strcpy(lowLevelFormatStr,specStr);
1199 /* replace the symbolic names with printf argument refs */
1200 strcpy(unusedSyms,UNUSED_ARGREF);
1201 for ( sym = g_HeadFootSymsList; sym->symbol != NULL; sym++ )
1203 Boolean unused = True;
1205 /* look for the symbol string */
1206 while ( (substr = strstr(lowLevelFormatStr,sym->symbol)) != NULL )
1207 { /* and replace it with the argref */
1209 strcpy(substr, sym->argref);
1210 strcpy(substr + strlen(sym->argref), substr + strlen(sym->symbol));
1212 /* if unused, add to unused list */
1213 if (unused) strcat(unusedSyms,sym->argref);
1216 /* append unused syms to end of format str */
1217 strcat(lowLevelFormatStr,unusedSyms);
1219 /* store in caller's location */
1220 *io_formattedStr = lowLevelFormatStr;
1221 *io_lineCnt = CountLines(lowLevelFormatStr);
1226 ===================================================================
1227 $PFUNBEG$: GenAllHeadFootFormatStrs()
1228 $1LINER$: Generates printf-ready format strings for all headers/footers
1230 Generates printf-ready format strings for all headers/footers
1234 ========================================================$SKIP$=====*/
1238 void GenAllHeadFootFormatStrs(
1239 _DtHPrOptions * options,
1243 GenHeadFootFormatStr(options->tocHF.evenHeader,
1244 &state->tocHFF.formattedEvenHeader, &state->tocHFF.evenHeaderLineCnt);
1245 GenHeadFootFormatStr(options->tocHF.oddHeader,
1246 &state->tocHFF.formattedOddHeader, &state->tocHFF.oddHeaderLineCnt);
1247 GenHeadFootFormatStr(options->tocHF.evenFooter,
1248 &state->tocHFF.formattedEvenFooter, &state->tocHFF.evenFooterLineCnt);
1249 GenHeadFootFormatStr(options->tocHF.oddFooter,
1250 &state->tocHFF.formattedOddFooter, &state->tocHFF.oddFooterLineCnt);
1252 GenHeadFootFormatStr(options->bodyHF.evenHeader,
1253 &state->bodyHFF.formattedEvenHeader, &state->bodyHFF.evenHeaderLineCnt);
1254 GenHeadFootFormatStr(options->bodyHF.oddHeader,
1255 &state->bodyHFF.formattedOddHeader, &state->bodyHFF.oddHeaderLineCnt);
1256 GenHeadFootFormatStr(options->bodyHF.evenFooter,
1257 &state->bodyHFF.formattedEvenFooter, &state->bodyHFF.evenFooterLineCnt);
1258 GenHeadFootFormatStr(options->bodyHF.oddFooter,
1259 &state->bodyHFF.formattedOddFooter, &state->bodyHFF.oddFooterLineCnt);
1261 GenHeadFootFormatStr(options->indexHF.evenHeader,
1262 &state->indexHFF.formattedEvenHeader, &state->indexHFF.evenHeaderLineCnt);
1263 GenHeadFootFormatStr(options->indexHF.oddHeader,
1264 &state->indexHFF.formattedOddHeader, &state->indexHFF.oddHeaderLineCnt);
1265 GenHeadFootFormatStr(options->indexHF.evenFooter,
1266 &state->indexHFF.formattedEvenFooter, &state->indexHFF.evenFooterLineCnt);
1267 GenHeadFootFormatStr(options->indexHF.oddFooter,
1268 &state->indexHFF.formattedOddFooter, &state->indexHFF.oddFooterLineCnt);
1274 ===================================================================
1275 $PFUNBEG$: PrintHeadFootStr()
1276 $1LINER$: Formats and prints the header/footer string
1278 Takes a format string, replaces the place holders with actual values,
1279 and prints the output to topicsFP.
1281 This function uses the "%n$" prefix supported by printf(3S)
1282 to allow a footer/header string to ref any argument out of
1283 order. This functionality requires that a ref to *every*
1284 argument be part of the format string. Because not all args
1285 may be part of the user-specified format string, this function
1286 appends the unused strings to the end of the format string
1287 for purposes of sprintf(), then truncates the unused portion
1290 number of lines in the header or footer
1292 topicsFP: pointer to output stream. If NULL, increment
1293 page and reset line number), but do not output;
1294 If not NULL, request new page as well
1295 ========================================================$SKIP$=====*/
1299 int PrintHeadFootStr(
1300 _DtHPrOptions * options,
1303 char * formattedStr,
1306 char * newLine = "\n";
1308 char sectNumStr[MAXSECTS * 4 + 5]; /* $SECTNUM */
1311 if (NULL == formattedStr) return 0; /* RETURN */
1312 if (NULL == topicsFP) return lineCnt; /* RETURN */
1314 /*** generate dynamic data ***/
1316 /* get the section number */
1317 SectNumStr(state->sectNums,state->sectStr,sectNumStr);
1319 /* update args; FIX: impove efficiency by processing topic title only when needed */
1320 GenHeadFootFormatArgs(options,state,True,sectNumStr,True);
1322 /* guidelines on string size and construction:
1323 The objective is to allow one set of headers & footers to apply
1324 to many different volumes and topics. This is made possible by
1325 allowing for fixed length strings. To get fixed length strings,
1326 the header/footer spec should include not only the string but
1327 also the fill for that string.
1329 The fill size is calculated based on the following widths:
1330 volTitle : 50 printing chars e.g. "title "
1331 topicTitle : 50 printing chars e.g. "title "
1332 sectNumStr : 8 printing chars e.g. " 3.10.4"
1333 pageNum : 3 printing chars e.g. " 3"
1334 volDate : constant by locale--no fill needed e.g. "Mon, Jul 4, 1988"
1335 dateStr : constant by locale--no fill needed e.g. "Mon, Jul 4, 1988"
1338 /*** generate the str ***/
1339 /* IMPT: the order of these arguments MUST match the argument numbers
1340 given in the definition of the g_HeadFootSymsList variable. */
1341 /* print the first set */
1342 sprintf(buf, formattedStr,
1343 state->hffArgs.todaysDate,state->hffArgs.volumeTitle,
1344 state->hffArgs.topicTitle, (int) state->curPageNumber,
1345 state->hffArgs.volumeDate, sectNumStr,
1346 (int) options->colsAdjLeftMargin,(int) ' ' );
1348 /* move the format string for the second set into new memory */
1349 formattedStr = strdup(buf);
1350 if(NULL == formattedStr) return 0; /* RETURN */
1352 /* print the second set */
1353 sprintf(buf, formattedStr,
1354 MAXVOLTITLEWIDTH - state->hffArgs.volumeTitleColsWidth, (int) ' ',
1355 MAXTOPICTITLEWIDTH - state->hffArgs.topicTitleColsWidth, (int) ' ',
1356 MAXPAGENUMWIDTH - state->hffArgs.pageNumColsWidth, (int) ' ',
1357 MAXSECTNUMWIDTH - state->hffArgs.sectNumColsWidth, (int) ' ',
1359 buf[lastValid] = EOS; /* truncate unused args */
1362 /*** output the str ***/
1363 fprintf(topicsFP, "%s", buf);
1371 ===================================================================
1372 $PFUNBEG$: PrintFooter()
1373 $1LINER$: Print footer and use right form for odd/even pages
1375 Print footer and use right form for odd/even pages
1378 topicsFP: pointer to output stream. If NULL, increment
1379 lines), but do not output;
1380 ========================================================$SKIP$=====*/
1385 _DtHPrOptions * options,
1388 _DtHPrHeadFoot * headFootInfo,
1389 HeadFootFormat * headFootFormatting)
1391 /* fill to bottom of page */
1392 OutputBlankLines(topicsFP,state,
1393 (options->rowsTextHeight - state->curLineNumber) -
1394 ( (state->curPageNumber % 2) == 0
1395 ? headFootFormatting->evenFooterLineCnt
1396 : headFootFormatting->oddFooterLineCnt));
1398 if ( (state->curPageNumber % 2) == 0) /* Even page */
1399 state->curLineNumber += PrintHeadFootStr(options,topicsFP,state,
1400 headFootFormatting->formattedEvenFooter,
1401 headFootFormatting->evenFooterLineCnt);
1403 state->curLineNumber += PrintHeadFootStr(options,topicsFP,state,
1404 headFootFormatting->formattedOddFooter,
1405 headFootFormatting->oddFooterLineCnt);
1411 ===================================================================
1412 $PFUNBEG$: PrintHeader()
1413 $1LINER$: Print footer and use right form for odd/even pages
1415 Print footer and use right form for odd/even pages
1418 topicsFP: pointer to output stream. If NULL, increment
1419 lines), but do not output;
1420 ========================================================$SKIP$=====*/
1425 _DtHPrOptions * options,
1428 _DtHPrHeadFoot * headFootInfo,
1429 HeadFootFormat * headFootFormatting)
1432 if ( (state->curPageNumber % 2) == 0) /* Even page */
1433 state->curLineNumber += PrintHeadFootStr(options,topicsFP,state,
1434 headFootFormatting->formattedEvenHeader,
1435 headFootFormatting->evenHeaderLineCnt);
1437 state->curLineNumber += PrintHeadFootStr(options,topicsFP,state,
1438 headFootFormatting->formattedOddHeader,
1439 headFootFormatting->oddHeaderLineCnt);
1444 ===================================================================
1445 $PFUNBEG$: NewPage()
1446 $1LINER$: Outputs paper form feed, increments page count, resets line cnt
1448 Outputs paper form feed, increments page count, resets line cnt
1451 topicsFP: pointer to output stream. If NULL, increment
1452 page and reset line number), but do not output;
1453 If not NULL, request new page as well
1454 ========================================================$SKIP$=====*/
1459 _DtHPrOptions * options,
1462 Boolean advancePage)
1464 /* start new page: form feed */
1467 if (advancePage) fprintf(topicsFP,"
\f\n");
1469 /* print top margin but don't add it to line count because the rowsTextHeight
1470 value is calculated post-topMargin */
1471 OutputBlankLines(topicsFP,state,options->rowsAdjTopMargin);
1474 /* adjust page and line numbers */
1475 if (advancePage) state->curPageNumber++;
1476 state->curLineNumber = 1;
1481 ===================================================================
1482 $PFUNBEG$: ProcessOneTopic()
1483 $1LINER$: Recovers and formats help text for one topic
1485 Recovers and formats help text for one topic
1487 0: The number of lines output.
1488 -2: could not get topic information
1490 topicsFP: pointer to output stream. If NULL, process topic
1491 (e.g. count lines and inc page numbers), but do not output;
1492 If not NULL, output lines and page headers
1493 ========================================================$SKIP$=====*/
1497 int ProcessOneTopic(
1498 _DtHPrOptions * options,
1501 Boolean printHeaderFooter)
1503 char * * helpList = NULL;
1507 char sectNumStr[MAXSECTS * 4 + 5];
1509 /* retrieve the text (but not the hyperlinks) from the volume */
1510 if ( _DtHelpTermGetTopicData(state->canvasHandle, state->volHandle,
1511 state->currentLocId, &helpList, NULL) != 0 )
1513 fprintf(stderr,_DTGETMESSAGE(PTSET,5,
1514 "%s Error: unable to get topic information:\n"
1515 "volume %s, locationId %s\n"),
1516 options->programName, options->helpVolume, options->locationId);
1517 return -2; /* RETURN error */
1520 /* output topic section number */
1521 /* this operates on the assumption that topic title is first line */
1522 ptrToLst = helpList;
1523 SectNumStr(state->sectNums,state->sectStr,sectNumStr);
1524 if (sectNumStr[0] != EOS)
1526 /* NOTE: if allow the sect num string to be resource-defined,
1527 then count the number of \n chars in it; don't assume how many. */
1528 if (topicsFP) fprintf(topicsFP,"\n");
1529 OutputBlankSpaces(topicsFP,options->colsAdjLeftMargin);
1530 if (topicsFP) fprintf(topicsFP,"%s ", sectNumStr);
1531 state->curLineNumber++;
1533 /* and put the title (must be on first two lines) on the same line */
1534 if ( (*helpList && (*helpList)[0] != EOS)
1535 || (*(++helpList) && (*helpList)[0] != EOS) )
1541 ret = IconvBuffer( state->volHandle, *helpList, &_p );
1543 fprintf(topicsFP,"%s\n", _p); /* output title */
1545 fprintf(topicsFP,"%s\n", *helpList); /* output title */
1548 state->curLineNumber += CountLines(*helpList) + 1; /* 1=the known \n */
1553 /* calc number of available lines from top of page to footer */
1554 availLines = AvailContentLines(options,state,&state->bodyHFF);
1556 /* cycle through the lines; add new pages where necessary */
1557 for ( ; *helpList != NULL; helpList++ )
1559 /* NOTE: it's impt to calc the final line before outputting it,
1560 as the line may contain embedded newlines */
1561 int linesCnt = CountLines(*helpList) + 1; /* 1=the known \n */
1563 /* calc what line that will leave us on */
1564 state->curLineNumber += linesCnt;
1566 /* if at the end of a page, print footer, eject, and print header */
1567 if (state->curLineNumber >= availLines)
1569 /* output any filler blank lines */
1570 OutputBlankLines(topicsFP,state,
1571 availLines - (state->curLineNumber - linesCnt) );
1572 if (printHeaderFooter)
1573 PrintFooter(options,topicsFP,state,&options->bodyHF,&state->bodyHFF);
1574 NewPage(options,topicsFP,state,True);
1575 if (printHeaderFooter)
1576 PrintHeader(options,topicsFP,state,&options->bodyHF,&state->bodyHFF);
1578 /* recalc the line we're on */
1579 state->curLineNumber += linesCnt;
1581 /* calc number of available lines from top of page to footer */
1582 availLines = AvailContentLines(options,state,&state->bodyHFF);
1585 /* output the lines */
1588 OutputBlankSpaces(topicsFP,options->colsAdjLeftMargin);
1593 ret = IconvBuffer( state->volHandle, *helpList, &_p );
1595 fprintf(topicsFP,"%s\n", _p );
1597 fprintf(topicsFP,"%s\n",*helpList);
1603 /* free the memory of helpList */
1604 _DtHelpFreeTopicData(ptrToLst,NULL);
1612 ===================================================================
1613 $PFUNBEG$: ProcessSubTopics()
1614 $1LINER$: Recovers and formats help text for current & sub topics
1616 ond none should be printed. */
1618 Subsections are numbered according to the legal method (e.g. 1.5.4.3)
1620 Recovers and formats help text for current & sub topics
1623 -1: could not create or open a temp file
1624 -2: could not get help topic info
1625 INHIBIT_OUTPUT: stop outputting children; we printed all we need to
1627 level: may range from 1 to (MAXSECTS-1)
1628 ========================================================$SKIP$=====*/
1631 int ProcessSubTopics(
1632 _DtHPrOptions * options,
1638 char * * children = NULL;
1640 int firstSubSectNum;
1641 int subSectNumIndex;
1644 #define INHIBIT_OUTPUT (-3)
1645 /* remember, don't turn inhibitOutput on if there's no match */
1646 if ( _DtHelpCeStrCaseCmp(state->outputFromLocId,state->currentLocId) == 0 )
1650 /* toggle the flag and set ret value */
1651 state->inhibitOutput = False;
1652 ret = INHIBIT_OUTPUT; /* stop printing after this topic & its children */
1654 curPos = state->curLineNumber; /* save off the current line position */
1656 /* start new page but don't eject; output header;
1657 output right number of blank lines to get to where topic starts */
1658 NewPage(options,topicsFP,state,False);
1659 PrintHeader(options,topicsFP,state,&options->bodyHF,&state->bodyHFF);
1660 OutputBlankLines(topicsFP,state,curPos - state->curLineNumber);
1664 curFP = (state->inhibitOutput ? (FILE *) NULL : topicsFP);
1666 /* init according to level */
1667 if(level == 0) /* the top topic? */
1668 { /* put top topic at same level as children */
1669 firstSubSectNum = 2;
1670 subSectNumIndex = 1;
1672 /* no prior instance of ProcessSubTopics() set this */
1673 state->sectNums[subSectNumIndex] = 1;
1675 else /* not the top topic */
1677 firstSubSectNum = 1;
1678 subSectNumIndex = level;
1679 state->level = level;
1682 /* add this topic to the toc */
1683 TocNewEntry(toc,state->currentLocId,state->curPageNumber,
1684 state->level,state->sectNums,state->sectStr);
1686 /* retrieve and possibly output the current topic */
1687 ProcessOneTopic(options,curFP,state,True);
1689 /* output the sub topics */
1690 if (_DtHelpCeGetTopicChildren(state->volHandle,
1691 state->currentLocId,&children) > 0)
1694 Boolean initSubSect = True;
1696 /* cycle through the topics and output each one */
1697 for (topic = children; *topic != NULL && (*topic)[0]; topic++ )
1699 /* start level 0 & 1 topics on a new page */
1700 if ( subSectNumIndex < 2 )
1702 PrintFooter(options,curFP,state,&options->bodyHF,&state->bodyHFF);
1703 NewPage(options,curFP,state,True);
1704 PrintHeader(options,curFP,state,&options->bodyHF,&state->bodyHFF);
1707 /* avoid orphans (i.e. require more than 4 lines left on page) */
1708 if ( (AvailContentLines(options,state,&state->bodyHFF)
1709 - state->curLineNumber) < 4 )
1711 PrintFooter(options,curFP,state,&options->bodyHF,&state->bodyHFF);
1712 NewPage(options,curFP,state,True);
1713 PrintHeader(options,curFP,state,&options->bodyHF,&state->bodyHFF);
1716 /* init new sub sect, if haven't yet done so */
1719 /* start new subsection; -1: make up for ++ later */
1720 state->sectNums[subSectNumIndex] = firstSubSectNum - 1;
1721 initSubSect = False;
1724 /* make this the current topic */
1725 state->currentLocId = *topic;
1726 /* use subSectNumIndex, not level, so that the top topic and its
1727 immediate children are at the same level */
1728 /* inc the sect num before the call so that the
1729 sect used below in the INHIBIT_OUTPUT wrapup is correct. */
1730 /* pass in topicsFP, not curFP */
1731 state->sectNums[subSectNumIndex]++; /* next subsection */
1732 /* even though ProcessSubTopics() can return 'INHIBIT_OUTPUT',
1733 don't stop processing, as this would cause the Toc to
1735 ProcessSubTopics(options,topicsFP,toc, subSectNumIndex+1,state);
1736 /* ProcessSubTopics(options,topicsFP,toc, state->level+1,state); */
1740 /* if this is the last topic to be output, then finish up */
1741 if (ret == INHIBIT_OUTPUT)
1743 /* save off line num */
1744 int curLine = state->curLineNumber;
1747 PrintFooter(options,curFP,state,&options->bodyHF,&state->bodyHFF);
1748 state->inhibitOutput = True; /* inhibit again */
1750 /* restore line num */
1751 state->curLineNumber = curLine;
1754 /* if processing subtopics, reset subsection number */
1755 if(subSectNumIndex > 1) state->sectNums[subSectNumIndex] = 0;
1756 state->level = level; /* state->level was modified by the FOR loop */
1764 ===================================================================
1765 $PFUNBEG$: ProcessFrontMatter()
1766 $1LINER$: Process the help volume to generate a file of front matter
1768 Process the help volume to generate a file of front matter
1771 -1: could not create or open a temp file
1772 -2: could not get help topic info
1774 ========================================================$SKIP$=====*/
1778 int ProcessFrontMatter(
1779 _DtHPrOptions * options,
1780 char * * ret_resultsFile,
1787 fp = OpenTmpFile(options,ret_resultsFile);
1788 if (NULL == fp) return -1; /* RETURN: error */
1790 /*** process text ***/
1791 /* setup the state */
1792 state->inhibitOutput = False;
1793 state->curPageNumber = 1;
1794 state->curLineNumber = 1;
1795 state->sectNums[0] = 0; /* inhibit section num printing */
1796 state->sectStr = NULL; /* inhibit section string printing */
1798 OutputBlankLines(fp,state, options->rowsTextHeight / 3);
1800 /* NOTE: the code below causes the memory allocated for currentLocId
1801 to be lost. I didn't fix this to save a few bytes of code space. */
1803 /* generate volume title */
1804 state->currentLocId = strdup("_TITLE");
1805 state->outputFromLocId = state->currentLocId;
1806 ret = ProcessOneTopic(options,fp,state,False);
1807 /*free(state->currentLocId);*/
1809 NewPage(options,fp,state,True);
1811 /* generate abstract */
1812 state->currentLocId = strdup("_ABSTRACT");
1813 state->outputFromLocId = state->currentLocId;
1814 ret = ProcessOneTopic(options,fp,state,False);
1815 /*free(state->currentLocId);*/
1817 /* Make a space between abstract and copyright */
1818 if ( AvailContentLines(options,state,&state->indexHFF) > 3 )
1819 OutputBlankLines(fp,state, 3);
1821 NewPage(options,fp,state,True);
1823 /* generate copyright */
1824 state->currentLocId = strdup("_COPYRIGHT");
1825 state->outputFromLocId = state->currentLocId;
1826 ret = ProcessOneTopic(options,fp,state,False);
1827 /*free(state->currentLocId);*/
1828 /*state->currentLocId = NULL;*/
1838 ===================================================================
1839 $PFUNBEG$: ProcessIndex()
1840 $1LINER$: Process the TOC data to generate an index file
1842 Process the TOC data to generate an index file
1844 This function uses state->pageNumber+1 as the first page
1848 -1: could not create or open a temp file
1849 -2: could not get help topic info
1851 ========================================================$SKIP$=====*/
1856 _DtHPrOptions * options,
1857 char * * ret_resultsFile,
1864 char * * indexEntriesList;
1868 *ret_resultsFile = NULL;
1870 /* Get the index. Recall that the array and strings pointed to by
1871 the indexEntriesList is owned by the open volume */
1872 entriesCnt = _DtHelpCeGetKeywordList(state->volHandle,&indexEntriesList);
1873 if (entriesCnt <= 0) return 0;
1876 fp = OpenTmpFile(options,ret_resultsFile);
1877 if (NULL == fp) return -1; /* RETURN: error */
1879 /*** process index ***/
1881 /* setup the state */
1882 state->curPageNumber++; /* inc page number from prev. value */
1883 state->inhibitOutput = False;
1884 state->curLineNumber = 1;
1885 state->sectNums[0] = 0; /* inhibit section num printing */
1886 state->sectStr = _DTGETMESSAGE(PTSET,10,"Index"); /* $SECTNUM name */
1888 /* add an index entry to the TOC */
1889 TocNewEntry(toc,_DTGETMESSAGE(PTSET,30,"__GENERATED-INDEX"),
1890 state->curPageNumber, 1,state->sectNums,state->sectStr);
1892 /* start new page (but don't eject) and output header */
1893 NewPage(options,fp,state,False);
1894 PrintHeader(options,fp,state,&options->indexHF,&state->indexHFF);
1896 /* calc number of available lines from top of page to footer */
1897 availLines = AvailContentLines(options,state,&state->indexHFF);
1899 /*** loop through the entries ***/
1900 for ( entryStr = *indexEntriesList++;
1902 entryStr = *indexEntriesList++ )
1904 char * * topicIdsList;
1907 TocEntry * tocEntry;
1909 /* get the topics associated with this entry */
1910 /* topicIdsList is set but not allocated & need not be freed */
1911 topicCnt = _DtHelpCeFindKeyword(state->volHandle,
1912 entryStr,&topicIdsList);
1913 if (topicCnt <= 0) continue; /* CONTINUE */
1915 /*** if only one topic, just put page number after the entry ***/
1918 /* find the toc entry of the topic */
1919 ret = TocFindSortedEntry(toc, *topicIdsList, NULL, &tocEntry);
1920 if (ret < 0) continue; /* CONTINUE */
1922 /* output the entry */
1923 OutputBlankSpaces(fp,options->colsAdjLeftMargin);
1928 ret = IconvBuffer( state->volHandle, entryStr, &_p );
1930 fprintf(fp, _DTGETMESSAGE(PTSET,20,"%s, %d\n"),
1931 _p, tocEntry->pageNumber);
1933 fprintf(fp, _DTGETMESSAGE(PTSET,20,"%s, %d\n"),
1934 entryStr, tocEntry->pageNumber);
1937 state->curLineNumber++;
1939 /* if at the end of a page, print footer, eject, and print header */
1940 if (state->curLineNumber >= availLines)
1942 PrintFooter(options,fp,state,&options->indexHF,&state->indexHFF);
1943 NewPage(options,fp,state,True);
1944 PrintHeader(options,fp,state,&options->indexHF,&state->indexHFF);
1945 /* calc number of available lines from top of page to footer */
1946 availLines = AvailContentLines(options,state,&state->indexHFF);
1949 continue; /* CONTINUE */
1952 /*** if more than one topic, list topic title & page number under the entry ***/
1954 /* do we need a new page to start this entry? */
1955 if ( (availLines - state->curLineNumber) < 3 )
1957 PrintFooter(options,fp,state,&options->indexHF,&state->indexHFF);
1958 NewPage(options,fp,state,True);
1959 PrintHeader(options,fp,state,&options->indexHF,&state->indexHFF);
1960 /* calc number of available lines from top of page to footer */
1961 availLines = AvailContentLines(options,state,&state->indexHFF);
1964 OutputBlankSpaces(fp,options->colsAdjLeftMargin);
1969 ret = IconvBuffer( state->volHandle, entryStr, &_p );
1971 fprintf(fp,"%s\n", _p );
1973 fprintf(fp,"%s\n", entryStr);
1976 state->curLineNumber++;
1978 /* for all topics in an index entry */
1981 i++, topicIdsList++ )
1985 if (NULL == *topicIdsList) continue; /* CONTINUE */
1987 /* find the toc entry of the topic */
1988 ret = TocFindSortedEntry(toc, *topicIdsList, NULL, &tocEntry);
1989 if (ret < 0) continue; /* CONTINUE */
1991 /* get the topic title */
1992 _DtHelpCeGetTopicTitle(state->canvasHandle, state->volHandle,
1993 tocEntry->locationId, &topicTitle);
1994 if (NULL == topicTitle)
1995 topicTitle = _DTGETMESSAGE(PTSET,31,EMPTY_STR);
1997 /* output the entry */
1998 OutputBlankSpaces(fp,options->colsAdjLeftMargin);
2003 ret = IconvBuffer( state->volHandle, topicTitle, &_p );
2005 fprintf(fp,_DTGETMESSAGE(PTSET,21," %s, %d\n"),
2006 _p, tocEntry->pageNumber);
2008 fprintf(fp,_DTGETMESSAGE(PTSET,21," %s, %d\n"),
2009 topicTitle, tocEntry->pageNumber);
2012 state->curLineNumber++;
2014 /* if at the end of a page, print footer, eject, and print header */
2015 if (state->curLineNumber >= availLines)
2017 PrintFooter(options,fp,state,&options->indexHF,&state->indexHFF);
2018 NewPage(options,fp,state,True);
2019 PrintHeader(options,fp,state,&options->indexHF,&state->indexHFF);
2020 /* calc number of available lines from top of page to footer */
2021 availLines = AvailContentLines(options,state,&state->indexHFF);
2023 } /* for all topics in an index entry */
2025 } /* for all index entries */
2028 PrintFooter(options,fp,state,&options->indexHF,&state->indexHFF);
2038 ===================================================================
2039 $PFUNBEG$: ProcessToc()
2040 $1LINER$: Process the TOC data to generate a toc file
2042 Process the TOC data to generate a toc file
2045 -1: could not create or open a temp file
2046 -2: could not get help topic info
2048 ========================================================$SKIP$=====*/
2053 _DtHPrOptions * options,
2054 char * * ret_resultsFile,
2063 fp = OpenTmpFile(options,ret_resultsFile);
2064 if (NULL == fp) return -1; /* RETURN: error */
2066 /*** process toc ***/
2068 /* setup the state */
2069 state->inhibitOutput = False;
2070 state->curPageNumber = 1;
2071 state->curLineNumber = 1;
2072 state->sectNums[0] = 0; /* inhibit section num printing */
2073 state->sectStr = _DTGETMESSAGE(PTSET,11,"Table of Contents"); /* $SECTNUM name */
2075 /* start new page and output header */
2076 NewPage(options,fp,state,False);
2077 PrintHeader(options,fp,state,&options->tocHF,&state->tocHFF);
2079 /* calc number of available lines from top of page to footer */
2080 availLines = AvailContentLines(options,state,&state->tocHFF);
2082 /* walk through the toc; output the label, title string, and page num */
2083 for ( entry = TocNextEntry(toc,NULL);
2085 entry = TocNextEntry(toc,entry) )
2087 char sectNumStr[MAXSECTS * 4 + 5]; /* $SECTNUM */
2088 char * title = NULL;
2095 /* get the data to print */
2096 SectNumStr(entry->sectNums,entry->sectStr,sectNumStr);
2097 _DtHelpCeGetTopicTitle(state->canvasHandle, state->volHandle,
2098 entry->locationId, &title);
2099 if (NULL == title) title = EMPTY_STR;
2101 /* set max length of title and calc num blanks needed */
2102 lhsWidth = strlen(sectNumStr) + 1; /* 1=blank after sect num */
2103 titlelen = strlen(title);
2104 wctitle = malloc(sizeof(wchar_t) * (titlelen+1));
2105 /* truncate the title using wchar_t */
2108 /* convert title to wchar_t and get num chars */
2109 mbstowcs(wctitle,title,titlelen+1);
2110 titlelen = wcslen(wctitle);
2111 /* truncate the title to fit on the line */
2112 if (titlelen > options->colsTextWidth - lhsWidth)
2114 wctitle[options->colsTextWidth - lhsWidth - 1] = EOS;
2115 titlelen = wcslen(wctitle);
2117 wcstombs(title,wctitle,titlelen+1);
2120 /* truncate the title assuming single-byte */
2121 else if (titlelen > options->colsTextWidth - lhsWidth)
2123 title[options->colsTextWidth - lhsWidth - 1] = EOS;
2124 titlelen = strlen(title);
2126 lhsWidth += titlelen;
2128 /* add a blank line before a major section */
2129 if ( 0 == entry->sectNums[2] )
2132 state->curLineNumber++;
2134 /* do we need a new page to start this section? */
2135 if ( (availLines - state->curLineNumber) < 3 )
2137 PrintFooter(options,fp,state,&options->tocHF,&state->tocHFF);
2138 NewPage(options,fp,state,True);
2139 PrintHeader(options,fp,state,&options->tocHF,&state->tocHFF);
2140 /* calc number of available lines from top of page to footer */
2141 availLines = AvailContentLines(options,state,&state->tocHFF);
2145 /* output the beginning of the line */
2146 if ( sectNumStr[0] == EOS ) /* no section number */
2148 /* space between title and page num */
2149 /* 1: no sect num so no space betw sect num & title */
2150 /* -3: reserve 3 spaces for the page number */
2151 blanksCnt = ((options->colsTextWidth - lhsWidth) - 3) + 1;
2157 ret = IconvBuffer( state->volHandle, title, &_p );
2159 fprintf(fp,"%*c%s", options->colsAdjLeftMargin, ' ', _p );
2161 fprintf(fp,"%*c%s", options->colsAdjLeftMargin, ' ', title);
2166 else /* valid section number */
2168 /* space between title and page num */
2169 /* -3: reserve 3 spaces for the page number */
2170 blanksCnt = (options->colsTextWidth - lhsWidth) - 3;
2176 ret = IconvBuffer( state->volHandle, title, &_p );
2178 fprintf(fp,"%*c%s %s",
2179 options->colsAdjLeftMargin, ' ', sectNumStr, _p );
2181 fprintf(fp,"%*c%s %s",
2182 options->colsAdjLeftMargin, ' ', sectNumStr, title);
2187 /* output the filler and page number */
2188 if ( (blanksCnt % 2) != 0) { fputc(' ',fp); blanksCnt--; }
2189 for( ;blanksCnt > 0; blanksCnt -= 2) fprintf(fp," .");
2190 fprintf(fp,"%3d\n", entry->pageNumber);
2192 state->curLineNumber++;
2194 /* if at the end of a page, print footer, eject, and print header */
2195 if (state->curLineNumber >= availLines)
2197 PrintFooter(options,fp,state,&options->tocHF,&state->tocHFF);
2198 NewPage(options,fp,state,True);
2199 PrintHeader(options,fp,state,&options->tocHF,&state->tocHFF);
2200 /* calc number of available lines from top of page to footer */
2201 availLines = AvailContentLines(options,state,&state->tocHFF);
2203 } /* for all entries */
2206 PrintFooter(options,fp,state,&options->tocHF,&state->tocHFF);
2215 ===================================================================
2216 $PFUNBEG$: ProcessTopics()
2217 $1LINER$: Process the help volume to generate a topics file
2219 Process the TOC data to generate a toc file
2222 -1: could not create or open a temp file
2223 -2: could not get help topic info
2225 outputFromLocId: output of topics occurs for this topic and all its
2226 subtopics. This topic Id is strcasecmp()ed against the
2227 current Id to determine a match. If NULL, the volume
2229 inhibitTopicsOutput: if true, output only starts when outputFromLocId is found
2231 outputFromLocId inhibitOutput action
2232 --------------- ------------- -------------------------------------
2233 NULL True no output is generated
2234 NULL False output begins with the top topic
2235 != NULL True output begins with outputFromLocId
2236 and stops after last subtopic of
2238 != NULL False output begins with the top topic
2239 and stops after last subtopic of
2241 ========================================================$SKIP$=====*/
2246 _DtHPrOptions * options,
2247 char * * ret_resultsFile,
2250 Boolean processSubTopics,
2251 char * outputFromLocId,
2252 Boolean inhibitTopicsOutput)
2257 /* don't print a single topic with no locId */
2258 if ( processSubTopics == False
2259 && (outputFromLocId == NULL || *outputFromLocId == EOS) )
2260 return 0; /* RETURN: ok */
2262 /* if no output is desired, set ptr to NULL */
2263 if ( NULL == outputFromLocId && inhibitTopicsOutput )
2266 { /* output is desired...open file */
2267 fp = OpenTmpFile(options,ret_resultsFile);
2268 if (NULL == fp) return -1; /* RETURN: error */
2271 /*** process text ***/
2273 /* if processing subtopics, start processing at the top */
2274 if ( processSubTopics )
2278 /* get the top topic of the volume */
2279 ret = _DtHelpCeGetTopTopicId(state->volHandle, &state->currentLocId);
2280 if (ret != True) state->currentLocId = strdup("_HOMETOPIC");
2283 { /* otherwise, process only where needed */
2284 state->currentLocId = strdup(outputFromLocId);
2287 /* set the other state values */
2288 if ( NULL != outputFromLocId
2289 && (ret = _DtHelpCeIsTopTopic(state->volHandle,outputFromLocId)) != 0 )
2290 state->outputFromLocId = outputFromLocId;
2292 state->outputFromLocId = state->currentLocId;
2293 state->inhibitOutput = inhibitTopicsOutput;
2294 state->curPageNumber = 1;
2295 state->curLineNumber = 1;
2297 /* output topics but dont inhibit */
2298 if ( processSubTopics )
2300 state->sectNums[0] = 1; /* support section num printing */
2301 /* 0: level of the top topic; note tha this is diff from the
2302 level of the top topic in an SDL volume, which is 1. This
2303 is merely for convenience, to make addressing into the
2304 sectNums array directly rather than subtracting 1 or 2 to
2305 get the array index from the level. */
2306 ret = ProcessSubTopics(options,fp,toc,0,state);
2310 /* start new page but don't eject; output header;
2311 output right number of blank lines to get to where topic starts */
2313 state->sectNums[0] = 0; /* inhibit section num printing */
2314 NewPage(options,fp,state,False); /* for top margin */
2315 PrintHeader(options,fp,state,&options->bodyHF,&state->bodyHFF);
2317 ret = ProcessOneTopic(options,fp,state,True);
2320 PrintFooter(options,fp,state,&options->bodyHF,&state->bodyHFF);
2323 /* if the file was opened, close & check if anything written to it */
2324 /* if empty, pretend the file wasn't created. */
2327 Boolean empty = False;
2330 if (pos <= 0) empty = True;
2334 unlink(*ret_resultsFile);
2335 free(*ret_resultsFile);
2336 *ret_resultsFile = NULL;
2345 ===================================================================
2346 $PFUNBEG$: MakePageBreakFile()
2347 $1LINER$: Creates a file with only a page break char in it
2349 Creates a file with only a page break char in it.
2350 If fails, file ptr is NULL
2353 ========================================================$SKIP$=====*/
2357 void MakePageBreakFile(
2358 _DtHPrOptions * options,
2359 char * * ret_resultsFile)
2363 fp = OpenTmpFile(options,ret_resultsFile);
2366 free(*ret_resultsFile);
2367 *ret_resultsFile = NULL;
2376 ===================================================================
2377 $PFUNBEG$: DoHelpTopicsProcessing()
2378 $1LINER$: Passes through entire volume and generates toc and topic output
2380 Passes through entire volume and generates toc and topic output
2383 -1: could not create or open a temp file
2384 -2: could not get help topic info
2385 -3: could not alloc memory
2387 ========================================================$SKIP$=====*/
2391 int DoHelpTopicsProcessing(
2392 _DtHPrOptions * options,
2393 char * * ret_resultsFile,
2395 Boolean processIndex,
2396 Boolean processFrontMatter,
2397 Boolean processSubTopics,
2398 char * outputFromLocId,
2399 Boolean inhibitTopicsOutput)
2414 char * pgbrkFile = NULL;
2415 char * partFiles[NUMPARTS];
2416 Boolean validFile = False;
2418 /* init larger vars to 0 */
2419 memset(&toc,0,sizeof(Toc));
2420 memset(&state,0,sizeof(state));
2421 memset(partFiles,0,sizeof(partFiles));
2423 /* create terminal-based canvas for text retrieval */
2424 ret = _DtHelpTermCreateCanvas(options->colsTextWidth,&state.canvasHandle);
2425 if ( ret != 0 ) return ret; /* RETURN: error */
2427 /* open volume and get state.volHandle */
2428 ret = _DtHelpCeOpenVolume(state.canvasHandle,
2429 options->helpVolume, &state.volHandle);
2430 if ( ret != 0 ) return ret; /* RETURN: error */
2432 /* do some prepatory format string generation */
2433 GenAllHeadFootFormatStrs(options,&state);
2435 /* after this point, if we get an error, we don't return--we do the best we can */
2436 /* so don't monitor the return values. */
2438 /*** process a help volume; maybe create a topics file ***/
2439 /* always do this, as all other processing (except FM) needs the data */
2440 ret=ProcessTopics(options,&partFiles[TOPICS],&state,&toc,
2441 processSubTopics,outputFromLocId,inhibitTopicsOutput);
2443 /*** process toc to create an index and add an index entry to toc ***/
2444 /* Do this right after processing topics so that page number info is right */
2446 ret=ProcessIndex(options,&partFiles[INDEX],&state,&toc);
2448 /*** process volume to create front matter ***/
2449 if (processFrontMatter)
2450 ret=ProcessFrontMatter(options,&partFiles[FM],&state);
2452 /*** process toc to create a toc; do this last to get all entries ***/
2454 ret=ProcessToc(options,&partFiles[TOC],&state,&toc);
2456 /*** create the final output file ***/
2458 MakePageBreakFile(options,&pgbrkFile);
2460 /* create a temporary file in $HOME/.dt/tmp to hold everything */
2461 /* Put in $HOME/.dt/tmp so that if the printer operation is running
2462 of a remote system, it can get to the (local) temp file.
2463 This would not be possible if the file were put in /tmp */
2464 *ret_resultsFile = _DtHPrCreateTmpFile(TMPFILE_PREFIX,TMPFILE_SUFFIX);
2465 if (NULL == *ret_resultsFile) { ret = -1; goto cleanup; } /* RETURN: error */
2467 buf = malloc(3000 * sizeof(char));
2468 if (NULL == buf) { ret = -3; goto cleanup; } /* RETURN: error */
2470 /* cat together the part files that got created in the array order */
2471 /* separate them with a file containing only a page break */
2473 start = buf + strlen(buf);
2475 for (i=0; i<NUMPARTS; i++)
2479 /* if at least one file in cat list, separate from it with a pgbrk */
2480 if (start != next && pgbrkFile)
2482 sprintf(next,"%s ", pgbrkFile);
2483 next += strlen(next);
2485 sprintf(next,"%s ", partFiles[i]);
2486 next += strlen(next);
2490 /* only do the operation if there are valid files */
2494 sprintf(next,"> %s", *ret_resultsFile);
2495 if(options->debugHelpPrint) printf("%s\n",buf);
2501 /* if needed, iconv file and change filenames */
2503 /* close the volume when done */
2504 _DtHelpCeCloseVolume(state.canvasHandle,state.volHandle);
2508 /* delete all part files */
2509 for (i=0; i<NUMPARTS; i++)
2512 unlink(partFiles[i]);
2520 /* NOTE: should free Toc here if interested in no leaks */
2527 ===================================================================
2528 $PFUNBEG$: GenerateTopicsFile()
2529 $1LINER$: Recovers and formats help topic text and then sends to printer
2531 Recovers and formats help topic text and then sends to printer
2534 ========================================================$SKIP$=====*/
2538 int GenerateTopicsFile(
2540 _DtHPrOptions * options,
2541 char * * ret_resultsFile)
2544 Boolean allTopics = (options->allTopics != NULL);
2545 Boolean subTopics = (options->subTopics != NULL);
2546 Boolean toc = (options->toc != NULL);
2547 Boolean index = (options->index != NULL);
2548 Boolean frontMatter = (options->frontMatter != NULL);
2549 Boolean oneTopic = (options->oneTopic != NULL);
2550 Boolean dfltOneTopic;
2551 char * locationId = options->locationId;
2553 /* one topic is selected if other options aren't selected */
2554 dfltOneTopic = !(allTopics || subTopics || toc || index);
2556 /* This is sort of a kludge, but since we don't require the -One flag,
2557 this keeps the _Hometopic from being printed along with
2558 the front matter, when only front matter was specified */
2559 if (frontMatter && !oneTopic && dfltOneTopic)
2560 locationId = NULL; /* prevent printing the hometopic */
2562 /* to generate a toc or index, we need to process all topics; if
2563 processing all or subtopics wasn't requested, request it;
2564 and set a locationId that will never match (an empty string) */
2565 if ( (toc || index) && !allTopics )
2567 if (!subTopics) locationId = "";
2571 /* check the flags and do right thing */
2572 if (oneTopic || dfltOneTopic)
2573 /* False: no subtopics--output only locationId; False: don't inhibit output */
2574 ret = DoHelpTopicsProcessing(
2575 options, ret_resultsFile,
2576 False, False, frontMatter,
2577 False, locationId, False);
2579 /* start at root and don't inhibit output */
2580 ret = DoHelpTopicsProcessing(
2581 options, ret_resultsFile,
2585 ret = DoHelpTopicsProcessing(
2586 options, ret_resultsFile,
2587 toc, index, frontMatter,
2588 subTopics, locationId,True);
2596 ===================================================================
2597 $FUNBEG$: _DtHPrPrintHelpTopic()
2598 $1LINER$: Recovers and formats help topic text and then sends to printer
2600 Recovers and formats help topic text and then sends to printer
2603 ========================================================$SKIP$=====*/
2606 int _DtHPrPrintHelpTopic(
2608 _DtHPrOptions * options)
2610 char * printCommand;
2611 char cmdFormat[100];
2612 char prOffsetArg[30];
2618 if ( NULL == options->helpVolume )
2620 fprintf(stderr, _DTGETMESSAGE(PTSET,1,
2621 "%s: Error: helpType is topic, "
2622 "but no helpVolume specified.\n"),
2623 options->programName);
2625 return 1; /* RETURN error */
2628 /* try to locate the volume */
2629 path = _DtHelpFileLocate(DtHelpVOLUME_TYPE, options->helpVolume,
2630 _DtHelpFileSuffixList,False,R_OK);
2633 fprintf(stderr, _DTGETMESSAGE(PTSET,2,
2634 "%s Error: unable to locate help volume '%s'\n"),
2635 options->programName, options->helpVolume);
2637 return 1; /* RETURN error */
2639 options->helpVolume = path; /* don't free old helpVolume: owned by Xrm */
2641 /* generate a file containing the help topic */
2642 status = GenerateTopicsFile(dpy,options,&tmpFile);
2645 fprintf(stderr, _DTGETMESSAGE(PTSET,3,
2646 "%s Error: problem processing help volume '%s'\n"),
2647 options->programName, options->helpVolume);
2649 return 1; /* RETURN error */
2652 /* Alloc max shell command line len */
2653 printCommand = malloc(MAX_COMMAND_LENGTH*sizeof(char));
2654 if (printCommand == NULL)
2656 fprintf(stderr, _DTGETMESSAGE(PTSET,4,
2657 "%s Error: memory allocation failed\n"),
2658 options->programName);
2660 return 1; /* RETURN error */
2664 /** generate the file **/
2665 sprintf(printCommand,"cat %s",tmpFile);
2667 status = _DtHPrGenFileOrPrint(options,"Help Topic(s)",printCommand);
2676 #if 0 /* This is left-over code that used to deal with printing
2677 raster images. We don't need it for printing text-only.
2678 I left it here for future reference. */
2680 ===================================================================
2681 $FUNBEG$: _DtHPrPrintHelpTopicWithXvp()
2682 $1LINER$: Recovers and formats help topic text and then sends to printer
2684 Recovers and formats help topic text and then sends to printer
2686 Code left over from VUE 3.0 help print
2687 Has not been updated.
2690 ========================================================$SKIP$=====*/
2693 int _DtHPrPrintHelpTopicWithXvp(
2695 VolumeHandle volHandle,
2698 extern _DtHelpDisplayAreaStruct *Spoof();
2704 XFontStruct *defaultFont;
2705 XFontStruct *pageNumberFont;
2706 _DtHelpDisplayAreaStruct *pDAS;
2712 Window main_windowX;
2717 XFontStruct *defaultFontX;
2720 #define MY_WIDTH 400
2721 #define MY_HEIGHT 400
2722 #define DEFAULT_FONT "-agfa-courier-normal-r-normal-93950-0-120-300-300-m-0-hp-roman8"
2725 /* set color to bitonal */
2726 value.addr = RN_bitonal;
2727 value.size = strlen(RN_BITONAL) + 1;
2728 XrmPutResource(&XvpDB, STAR_RN_helpColorUse, *str_type, &value);
2732 /********************/
2733 /* Get display name */
2734 /********************/
2736 strcpy(resource_name, name_prefix);
2737 strcat(resource_name, RN_display);
2738 strcpy(resource_class, class_prefix);
2739 strcat(resource_class, RC_display);
2740 if (XrmGetResource(appDB, resource_name,
2742 str_type, &value) == True)
2743 displayNameX = value.addr;
2744 else displayNameX = EMPTY_STR;
2747 strcpy(resource_name, name_prefix);
2748 strcat(resource_name, RN_jobTitle);
2749 strcpy(resource_class, class_prefix);
2750 strcat(resource_class, RC_jobTitle);
2751 if (XrmGetResource(appDB, resource_name,
2753 str_type, &value) == True)
2754 lpDocName = (char *)value.addr;
2756 lpDocName = DFLT_JOB_TITLE_STR;
2758 status = XvpEscape(dpy, STARTDOC, strlen(lpDocName), lpDocName, NULL);
2759 screen = DefaultScreen(dpy);
2761 /* Calculate application page size */
2763 _DtHPrCalculatePageSize(dpy, &x, &y, &width, &height);
2765 /* create a window; x, y, width, and height are recorded */
2766 main_window = XCreateSimpleWindow(dpy, XRootWindow(dpy, screen),
2770 10, 0, XWhitePixel (dpy, screen));
2771 /* 0, 0, MY_WIDTH, MY_HEIGHT, 10, 0, XWhitePixel (dpy, screen)); */
2773 XSelectInput (dpy, main_window, ExposureMask);
2774 XMapWindow (dpy, main_window);
2775 XvpEscape(dpy, SET_IMAGE_RESOLUTION, 4, 100, NULL);
2777 defaultFont = XLoadQueryFont (dpy, DEFAULT_FONT);
2778 if (defaultFont == NULL)
2780 printf ("Unable to get a font\n");
2784 gc = DefaultGC(dpy, screen);
2785 XSetForeground (dpy, gc, XBlackPixel (dpy, screen));
2786 XSetBackground (dpy, gc, XWhitePixel (dpy, screen));
2787 XSetFont(dpy, gc, defaultFont->fid);
2788 XSetLineAttributes(dpy, gc, 2, LineSolid, CapButt, JoinMiter);
2790 #ifndef RASTER_PRINT
2792 XLoadQueryFont (dpy,
2793 "-agfa-univers-normal-r-normal-94021-0-100-300-300-p-0-iso8859-1");
2794 if (pageNumberFont == NULL)
2796 printf ("Unable to get a font\n");
2800 pageNumberGC = XCreateGC(dpy, RootWindow(dpy, screen), NULL, NULL);
2801 XSetForeground (dpy, pageNumberGC, XBlackPixel (dpy, screen));
2802 XSetBackground (dpy, pageNumberGC, XWhitePixel (dpy, screen));
2803 XSetFont(dpy, pageNumberGC, pageNumberFont->fid);
2804 XSetLineAttributes(dpy, pageNumberGC, 2, LineSolid, CapButt, JoinMiter);
2808 widthX = width/3; /* hard coded for 300 dpi printers */
2810 status = CreateRealXObjects(displayNameX, widthX, heightX,
2811 &dpyX, &main_windowX, &gcX,
2812 &invert_gcX, &defaultFontX);
2813 dpyX->db = dpy->db; /* carry over data base */
2815 pDAS = Spoof (dpyX, gcX, invert_gcX, defaultFontX, widthX, heightX, lineLeading);
2817 pDAS = Spoof (dpy, gc, gc, defaultFont, width, height, lineLeading);
2821 fprintf(stderr, "%s: Internal error.\n");
2825 if (helpType == DtHELP_TYPE_TOPIC)
2827 status = printTopicAndChildrenX(helpVolume, locationId, allTopics, pDAS,
2828 dpy, main_window, gc,
2829 dpyX, main_windowX, gcX,
2832 status = printTopicAndChildren(helpVolume, locationId, allTopics, pDAS,
2833 dpy, main_window, gc, pageNumberGC );
2836 pDAS = (_DtHelpDisplayAreaStruct *) SetUp (pDAS, dpy, main_window, gc, defaultFont,
2842 else if (helpType == DtHELP_TYPE_DYNAMIC_STRING)
2847 pDAS = (_DtHelpDisplayAreaStruct *) SetUpDynamicString (pDAS, dpy, gc,
2852 RenderLinesX (dpyX, main_windowX, pDAS, widthX, heightX, &image);
2853 XvpPutImage(dpy, main_window, gcX, image, 0, 0, 0, 0,
2854 (image->width)*3, (image->height*3) );
2855 status = XvpEscape(dpy, NEWFRAME, NULL, NULL, NULL);
2857 else if (status < 0)
2858 fprintf (stdout, "XvpEscape(NEWFRAME) not implemented.\n");
2859 else fprintf(stdout, "XvpEscape(NEWFRAME) not successful.\n");
2861 pDAS = (_DtHelpDisplayAreaStruct *) SetUpDynamicString (pDAS, dpy, gc,
2866 RenderLines (dpy, main_window, pDAS);
2871 fprintf(stderr, "%s Error: Illegal helpType %d.\n",
2878 fprintf (stdout, "Error occurred in XvpEscape(STARTDOC)\n");
2882 status = XvpEscape(dpy, ENDDOC, NULL, NULL, NULL);
2885 fprintf (stdout, "Error occurred in XvpEscape(ENDDOC)\n");
2891 #endif /* #if 0 at function start */