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() */
62 #include "HelpPrintI.h" /* helpprint */
64 #include "DtI/HelpTermP.h" /* from libDtHelp */
65 #include "Dt/CanvasP.h" /* from libDtHelp */
66 #include "StringFuncsI.h" /* from libDtHelp */
67 #include "Dt/LocaleXlate.h" /* from libDtHelp */
68 #include "DtI/bufioI.h" /* from libDtHelp; required for AccessI.h */
69 #include "DtI/FileUtilsI.h" /* from libDtHelp */
70 #include "GenUtilsP.h" /* from libDtHelp */
71 #include "HelpXlate.h" /* from libDtHelp */
73 /*#include "AccessI.h" ** from libDtHelp */
74 /* I can't include AccessI.h because it redefines the Boolean type,
75 which is also defined in Xt/Intrisincs.h. I'm just including the
76 prototypes from AccessI.h here. */
77 extern char * _DtHelpCeGetVolumeLocale(VolumeHandle helpVolumeHandle);
78 extern const char * _DtHelpCeGetVolumeCharSet(VolumeHandle helpVolumeHandle);
80 /*======== platform adjustments ==============*/
82 #define wcswidth(s,n) wscol(s)
83 #define wcslen(s) wslen(s)
86 /*======== boundary values ==============*/
87 #define MAXSECTS 50 /* max number of section nesting */
89 #define MAXVOLTITLEWIDTH 50
90 #define MAXTOPICTITLEWIDTH 50
91 #define MAXPAGENUMWIDTH 3
92 #define MAXSECTNUMWIDTH 8
94 /*======== helper values ===============*/
96 #define EMPTY_STR s_EmptyStr
98 #define PTSET 3 /* message set */
101 /*======== helper variables ===============*/
102 static char s_EmptyStr[1] = { EOS };
105 * check roman 8/Latin 1
106 * check PAGER env variable
110 /*======== data structs ==============*/
112 /* These data structs manage the table of contents (Toc)
113 of a help volume. The Toc uses two organizational mechanisms:
114 a linear table of entries, which gives sequential order
115 and is used to generate the TOC; and a binary tree of entries
116 that is sorted alphabetically by location id, and is used to
117 speed lookup of the page number of a locationId for use in
118 generating the index. */
121 ===================================================================
123 $1LINER$: All data for a single toc entry
126 ========================================================$SKIP$=====*/
129 typedef struct TocEntry
131 struct TocEntry * nextEntry; /* next entry in the linear list */
132 struct TocEntry * leftLoc; /* left location of sorted binary tree */
133 struct TocEntry * rightLoc; /* right location of sorted binary tree */
134 char * locationId; /* locationId of the topic */
135 int pageNumber; /* page the topic located on */
136 int level; /* nesting level */
137 int sectNums[MAXSECTS]; /* section numbers */
138 char * sectStr; /* alternate section string */
143 ===================================================================
145 $1LINER$: Manages the toc entries in a volume
148 ========================================================$SKIP$=====*/
153 TocEntry * linearEntries; /* ptr to head of linear list of entries */
154 TocEntry * lastLinearEntry; /* ptr to tail of linear list of entries */
155 TocEntry * sortedEntries; /* ptr to top of sorted btree of entries */
160 ===================================================================
161 $PTYPEBEG$: HeadFootFormat
162 $1LINER$: All data related to the header/footer formatting
165 ========================================================$SKIP$=====*/
168 typedef struct HeadFootFormat
170 char * formattedEvenHeader; /* formatted even-page header when printing volume */
171 char * formattedOddHeader; /* formatted odd-page header when printing volume */
172 char * formattedEvenFooter; /* formatted even-page footer when printing volume */
173 char * formattedOddFooter; /* formatted odd-page footer when printing volume */
174 int evenHeaderLineCnt; /* num lines in even-page header when printing volume */
175 int oddHeaderLineCnt; /* num lines in odd-page header when printing volume */
176 int evenFooterLineCnt; /* num lines in even-page footer when printing volume */
177 int oddFooterLineCnt; /* num lines in odd-page footer when printing volume */
182 ===================================================================
183 $PTYPEBEG$: HeadFootFormatArgs
184 $1LINER$: Arguments used in head/foot formatting
187 ========================================================$SKIP$=====*/
190 typedef struct HeadFootFormatArgs
193 int volumeTitleColsWidth;
195 int topicTitleColsWidth;
197 int volumeDateColsWidth;
199 int todaysDateColsWidth;
200 int sectNumColsWidth;
201 int pageNumColsWidth;
207 ===================================================================
208 $PTYPEBEG$: PrintState
209 $1LINER$: All data related to the on-going printing operation
212 ========================================================$SKIP$=====*/
215 typedef struct PrintState
217 char * currentLocId; /* current loc Id in volume */
218 char * outputFromLocId; /* start output at this location */
219 HeadFootFormatArgs hffArgs; /* arguments used in head/foot formatting */
220 HeadFootFormat tocHFF; /* HF formatting info for TOC */
221 HeadFootFormat bodyHFF; /* HF formatting info for body */
222 HeadFootFormat indexHFF; /* HF formatting info for index */
223 Boolean inhibitOutput; /* inhibit output */
224 int curPageNumber; /* page number of current output */
225 int curLineNumber; /* line number of current page of output */
226 VolumeHandle volHandle; /* volume handle of volume being printed */
227 CanvasHandle canvasHandle; /*canvas handle of terminal format canvas*/
228 int sectNums[MAXSECTS]; /* current section number */
229 char * sectStr; /* current section string value */
230 int level; /* level of section nesting */
234 /*======== static variables ===============*/
237 ===================================================================
239 $1LINER$: Maps a symbolic string to a printf-format string.
242 ========================================================$SKIP$=====*/
245 typedef struct SymValue
251 /* List of symbols that can be used in header/footer strings
252 and the printf args that are used to access the data. */
253 /* NOTE: ***IT IS CRITICAL THAT THE SYMBOL STRING HAVE THE
254 SAME OR LONGER LENGTH THAN THE ARGUMENT STRING. ***/
255 /* NOTE: ***ALWAYS UPDATE THE UNUSED_ARGREF AND THE sprintf() CALL
256 IN PrintHeadFootStr() WHEN ADDING NEW SYMBOLS***/
257 /* NOTE: The replacement values use a trick to get around the limitations
258 of printf(), which only allows args numbered 1 to 9. The strategy
259 is to do two printfs, and to use the %% construct in the first string
260 to generate a % construct in the second string. */
261 SymValue g_HeadFootSymsList[] =
263 { "$VOLUMEFILL", "%%2$*1$c" }, /* filler for fixed sized volume name */
264 { "$TOPICFILL", "%%4$*3$c" }, /* filler for fixed sized current topic title */
265 { "$PAGENUMFILL", "%%6$*5$c" }, /* filler for fixed sized page number */
266 { "$SECTNUMFILL", "%%8$*7$c" }, /* filler for fixed sized section number or name */
267 { "$TODAY", "%1$s" }, /* today's date */
268 { "$VOLUME", "%2$s" }, /* volume name */
269 { "$TOPIC", "%3$s" }, /* current topic title */
270 { "$PAGENUM", "%4$d" }, /* page number */
271 { "$VOLDATE", "%5$s" }, /* date on the help volume file */
272 { "$SECTNUM", "%6$s" }, /* section number or name */
273 { "$LMARGIN", "%8$*7$c" }, /* left margin blanks; args 7 & 8 */
276 #define UNUSED_ARGREF "%%9$n" /* arg to hold the num of unused args */
280 /*======== functions ==============*/
283 ===================================================================
284 $PFUNBEG$: TocNextEntry()
285 $1LINER$: Get next entry in the toc
290 NULL: no more entires
291 ========================================================$SKIP$=====*/
295 TocEntry * TocNextEntry(
299 if (NULL == entry) return toc->linearEntries;
300 return entry->nextEntry;
305 ===================================================================
306 $PFUNBEG$: TocFindSortedEntry()
307 $1LINER$: Finds an entry using the sorted btree of entries
313 ========================================================$SKIP$=====*/
317 int TocFindSortedEntry(
320 TocEntry * * ret_parent,
321 TocEntry * * ret_entry)
327 if (NULL == ret_parent) ret_parent = &tmp;
328 if (NULL == ret_entry) ret_entry = &tmp;
333 prev = toc->sortedEntries;
335 while ( NULL != cur )
338 cmp = _DtHelpCeStrCaseCmp(locationId,cur->locationId);
340 prev = cur, cur = cur->leftLoc;
342 prev = cur, cur = cur->rightLoc;
345 *ret_parent = prev, *ret_entry = cur;
346 return 0; /* RETURN: found */
350 return -1; /* RETURN: not found */
355 ===================================================================
356 $PFUNBEG$: TocNewEntry()
357 $1LINER$: Add a Toc entry to the Toc
362 -1: memory allocation error
363 ========================================================$SKIP$=====*/
377 new = calloc(1,sizeof(TocEntry));
378 if (NULL == new) return -1; /* RETURN: mem alloc err */
381 new->locationId = strdup(locationId);
382 new->pageNumber = pageNumber;
384 new->sectStr = sectStr;
385 memcpy(new->sectNums, sectNums, sizeof(new->sectNums));
387 if (NULL == new->locationId)
388 { free(new); return -1; } /* RETURN: mem alloc err */
390 /*** insert into toc ***/
392 /* if first in list */
393 if (NULL == toc->linearEntries)
395 toc->linearEntries = new;
396 toc->lastLinearEntry = new;
397 toc->sortedEntries = new;
399 else /* not first in list */
401 TocEntry * parent, * entry;
403 if ( TocFindSortedEntry(toc,locationId,&parent,&entry) == 0 )
404 return -2; /* RETURN: duplicate entry */
405 /* insert into the btree (not balanced) */
406 if( _DtHelpCeStrCaseCmp(locationId,parent->locationId) < 0 )
407 parent->leftLoc = new;
409 parent->rightLoc = new;
410 /* insert into the linear list */
411 toc->lastLinearEntry->nextEntry = new;
412 toc->lastLinearEntry = new;
414 return 0; /* RETURN: ok */
419 ===================================================================
420 $PFUNBEG$: IconvFile()
421 $1LINER$: Compares cur env and volume and iconv file if necessary
424 0: no conversion needed or not possible to determine if needed
425 1: conversion needed & successful
426 -1: conversion needed and failed
428 ========================================================$SKIP$=====*/
433 _DtHPrOptions * options,
434 VolumeHandle helpVolumeHandle,
438 #define CUR_CODESET 1
440 #define VOL_CODESET 3
441 #define FROM_CODESET 4
448 char * destFile = NULL;
452 for (i=0; i<NUMSTRS; i++) loc[i] = NULL;
454 /* get the normalized current codeset */
455 _DtHelpCeXlateOpToStdLocale (
456 DtLCX_OPER_SETLOCALE, setlocale(LC_CTYPE,NULL),
457 &loc[CUR_LOCALE], NULL, &loc[CUR_CODESET]);
459 /* get the normalized volume codeset */
460 loc[VOL_LOCALE] = _DtHelpCeGetVolumeLocale(helpVolumeHandle);
462 /* codeset begins after the '.'; find it */
465 && _DtHelpCeStrchr(loc[VOL_LOCALE], ".", 1, &codeset) == 0)
469 loc[VOL_CODESET] = (NULL != codeset ? strdup(codeset) : NULL);
471 /* if either locale is NULL or if they are the same string
472 then don't iconv the file */
473 if ( NULL == loc[CUR_CODESET]
474 || NULL == loc[VOL_CODESET]
475 || strcmp(loc[CUR_CODESET],loc[VOL_CODESET]) == 0 )
477 ret = 0; /* RETURN: no iconv needed/possible */
481 /* get the source codeset */
482 _DtHelpCeXlateStdToOpLocale (
483 DtLCX_OPER_ICONV1, loc[VOL_LOCALE],
484 "iso8859_1", &loc[FROM_CODESET]);
486 /* get the target codeset */
487 _DtHelpCeXlateStdToOpLocale (
488 DtLCX_OPER_ICONV1, loc[CUR_LOCALE],
489 "iso8859_1", &loc[TO_CODESET]);
491 /* construct the command line */
492 destFile = _DtHPrCreateTmpFile(TMPFILE_PREFIX,TMPFILE_SUFFIX);
493 if (NULL == destFile)
495 ret = -1; /* error */
499 sprintf(buf,options->iconvCmdAndArgs,
500 loc[FROM_CODESET],loc[TO_CODESET],*srcFile, destFile);
502 /* do the conversion */
503 if(options->debugHelpPrint) printf("%s\n",buf);
505 ret = (ret == 0 ? 1 : -1); /* 1: success; -1: failure */
507 /* if successful conversion, change the src file */
521 for (i=0; i<NUMSTRS; i++) if (loc[i]) free(loc[i]);
526 #ifdef ICONV_INBUF_CONST
527 # define ICONV_INBUF_TYPE const char **
529 # define ICONV_INBUF_TYPE char **
532 #define WORKSIZE 1024*10 /* 10k */
535 * _i18nwork1[] is used to convert the passed string with CD iconv.
539 static void *_i18nwork1 = NULL;
540 static unsigned long _i18nsize1 = 0;
541 static int shouldAlloc1 = ~0;
544 static void _converter_( iconv_t CD,
545 void *from, unsigned long from_len,
551 size_t OutBytesLeft = 0;
552 size_t _OutBytesLeft = 0;
554 size_t converted_num = 0;
555 unsigned long to_len;
561 if ( shouldAlloc1 ) {
562 /* Obtain work area */
563 _i18nwork1 = (size_t *)malloc( WORKSIZE );
568 _i18nsize1 = WORKSIZE;
572 InBuf = (char *)from;
573 InBytesLeft = from_len;
574 OutBytesLeft = _i18nsize1;
575 OutBuf = (char *)_i18nwork1;
578 * Need to place iconv state to the initial one by
579 * setting inbuf to NULL of iconv().
581 iconv( CD, (ICONV_INBUF_TYPE)NULL, 0, NULL, 0 );
586 * +----------------------------+
588 * +----------------------------+
589 * <-------------------------->
598 * +----------------------------+
600 * +----------------------------+
601 * <-------------------------->
605 iconv_ret = iconv( CD, (ICONV_INBUF_TYPE)&InBuf, &InBytesLeft,
606 &OutBuf, &OutBytesLeft );
607 if ( iconv_ret == 0 ) {
611 * +----------------------------+
612 * |XXXXXXXXXXXXXXXXXXXXXXXXXXXX|
613 * +----------------------------+
620 * +----------------------------+
621 * |XXXXXXXXXXXXXXXXX| | | |
622 * +----------------------------+
623 * <---------------> <-------->
624 * converted_num OutBytesLeft
626 converted_num = (unsigned long)((char *)OutBuf-(char *)_i18nwork1);
627 *to = (void *)_i18nwork1;
628 to_len = (unsigned long)converted_num;
631 if ( errno == E2BIG ) {
632 /* Overflow. still data is left.
635 * +----------------------------+
636 * |XXXXXXXXXXXXXX| | | |
637 * +----------------------------+
644 * +----------------------------+
645 * |XXXXXXXXXXXXXXXXXXXXXXXXXXX |
646 * +----------------------------+
647 * <------------------------->
648 * converted_num OutBytesLeft=?
652 /* Check how many converted already. */
654 (unsigned long)((char *)OutBuf - (char *)_i18nwork1);
655 _i18nsize1 += WORKSIZE;
656 _p = realloc( _i18nwork1, _i18nsize1 );
667 OutBuf = (char *)((char*)_i18nwork1 + converted_num);
668 OutBytesLeft += WORKSIZE;
683 if ( _i18nsize1 >= to_len + 1 ) {
684 ((char *)_i18nwork1)[to_len] = '\0';
689 _p = realloc( _i18nwork1, _i18nsize1 );
699 ((char *)_i18nwork1)[to_len] = '\0';
710 VolumeHandle helpVolumeHandle,
715 #define CUR_CODESET 1
717 #define VOL_CODESET 3
718 #define FROM_CODESET 4
727 static int isFirst = ~0;
728 static iconv_t CD = (iconv_t)-1;
730 for (i=0; i<NUMSTRS; i++) loc[i] = NULL;
732 /* get the normalized current codeset */
733 _DtHelpCeXlateOpToStdLocale (
734 DtLCX_OPER_SETLOCALE, setlocale(LC_CTYPE,NULL),
735 &loc[CUR_LOCALE], NULL, &loc[CUR_CODESET]);
737 /* get the normalized volume codeset */
738 loc[VOL_LOCALE] = _DtHelpCeGetVolumeLocale(helpVolumeHandle);
740 /* codeset begins after the '.'; find it */
743 && _DtHelpCeStrchr(loc[VOL_LOCALE], ".", 1, &codeset) == 0)
747 loc[VOL_CODESET] = (NULL != codeset ? strdup(codeset) : NULL);
749 /* if either locale is NULL or if they are the same string
750 then don't iconv the file */
751 if ( NULL == loc[CUR_CODESET]
752 || NULL == loc[VOL_CODESET]
753 || strcmp(loc[CUR_CODESET],loc[VOL_CODESET]) == 0 )
755 ret = 0; /* RETURN: no iconv needed/possible */
759 /* get the source codeset */
760 _DtHelpCeXlateStdToOpLocale (
761 DtLCX_OPER_ICONV1, loc[VOL_LOCALE],
762 "iso8859_1", &loc[FROM_CODESET]);
764 /* get the target codeset */
765 _DtHelpCeXlateStdToOpLocale (
766 DtLCX_OPER_ICONV1, loc[CUR_LOCALE],
767 "iso8859_1", &loc[TO_CODESET]);
770 CD = iconv_open( loc[TO_CODESET], loc[FROM_CODESET] );
773 if ( CD == (iconv_t)-1 ) {
777 _converter_( CD, (void *)src, (unsigned long)strlen( src ),
784 for (i=0; i<NUMSTRS; i++) if (loc[i]) free(loc[i]);
792 ===================================================================
793 $PFUNBEG$: OpenTmpFile()
794 $1LINER$: Opens temporary file
796 opens a temporary file
799 ========================================================$SKIP$=====*/
804 _DtHPrOptions * options,
805 char * * ret_tmpFile)
809 /* Put in $HOME/.dt/tmp so that if the printer operation is running
810 of a remote system, it can get to the (local) temp file.
811 This would not be possible if the file were put in /tmp */
812 *ret_tmpFile = _DtHPrCreateTmpFile(TMPFILE_PREFIX,TMPFILE_SUFFIX);
813 if (NULL == *ret_tmpFile) return NULL; /* RETURN: error */
815 fp = fopen(*ret_tmpFile,"w");
818 fprintf(stderr,_DTGETMESSAGE(PTSET,6,
819 "%s Error: unable to open temporary file %s\n"),
820 options->programName, *ret_tmpFile);
824 } /* open tmp file */
828 ===================================================================
829 $PFUNBEG$: CountLines()
830 $1LINER$: counters number of CRs in a string
832 counters number of CRs in a string
835 ========================================================$SKIP$=====*/
844 static char * newLine = "\n";
847 while( _DtHelpCeStrchr(substr,newLine,MB_CUR_MAX,&substr) == 0 )
852 /* return line count to caller */
859 ===================================================================
860 $PFUNBEG$: AvailContentLines()
861 $1LINER$: count number of lines available between top of page & footer
863 Count number of lines available between top of page & footer
866 ========================================================$SKIP$=====*/
869 int AvailContentLines(
870 _DtHPrOptions * options,
872 HeadFootFormat * hff)
874 return options->rowsTextHeight -
875 ( (state->curPageNumber % 2) == 0
876 ? hff->evenFooterLineCnt
877 : hff->oddFooterLineCnt);
883 ===================================================================
884 $PFUNBEG$: SectNumStr()
885 $1LINER$: generates string ver of section number
887 generates string ver of section number
890 buf: must be at least 4 * MAXSECTS chars long
891 ========================================================$SKIP$=====*/
902 /* recall: if sectNums[0] == 0, then no section number is defined
903 and none should be printed; try sectStr as alternate. */
905 /* generate the section number */
907 if (sectNums && sectNums[0] != 0 )
910 for ( sect = 1; sectNums[sect] != 0; sect++ )
912 sprintf(partial, "%d.", sectNums[sect]);
916 else /* if no section number, take the section string, if avail */
918 if (sectStr) strcpy(buf,sectStr);
927 ===================================================================
928 $PFUNBEG$: OutputBlankSpaces()
929 $1LINER$: Outputs blank Spaces
934 topicsFP: pointer to output stream. If NULL, do nothing
935 ========================================================$SKIP$=====*/
939 void OutputBlankSpaces(
943 if (NULL == topicsFP || spaceCount < 0) return;
944 while (spaceCount--) fprintf(topicsFP," ");
949 ===================================================================
950 $PFUNBEG$: OutputBlankLines()
951 $1LINER$: Outputs blank lines
956 topicsFP: pointer to output stream. If NULL, do nothing
957 ========================================================$SKIP$=====*/
961 void OutputBlankLines(
966 if (lineCount < 0) return; /* RETURN */
967 state->curLineNumber += lineCount;
968 if (NULL == topicsFP) return; /* RETURN */
969 while (lineCount--) fprintf(topicsFP,"\n");
974 ===================================================================
975 $PFUNBEG$: DoStrColsWidth()
976 $1LINER$: Calculates number of cols used by a string; truncate if needed
978 Calculates the number of cols used by the string and truncates
979 the string to the specified maxWidth if this is exceeded.
982 The number of columns this string requires for printing.
984 ========================================================$SKIP$=====*/
998 /* alloc memory for the wchar_t string */
1000 wcstr = malloc(sizeof(wchar_t) * (len+1));
1002 /* convert str to wchar_t and get width in chars */
1003 mbstowcs(wcstr,str,len+1);
1004 wclen = wcslen(wcstr);
1006 /* get col width of the string and truncate if necessary */
1007 while ( (width = wcswidth(wcstr,wclen+1)) > maxWidth
1008 && truncateStr == True)
1009 wcstr[--wclen] = EOS;
1010 wcstombs(str,wcstr,len+1);
1020 ===================================================================
1021 $PFUNBEG$: GenHeadFootFormatArgs()
1022 $1LINER$: Generates args used by a header/footer format string
1024 Generates args used by a header/footer format string
1028 ========================================================$SKIP$=====*/
1032 void GenHeadFootFormatArgs(
1033 _DtHPrOptions * options,
1035 Boolean updateTopicTitle,
1037 Boolean updatePageNum)
1045 /* get the volume title and its size */
1046 if (NULL == state->hffArgs.volumeTitle)
1048 /* get the volume title */
1050 _DtHelpCeGetVolumeTitle(state->canvasHandle,state->volHandle,&str);
1051 if (NULL == str) str = strdup("");
1053 width = DoStrColsWidth(str,MAXVOLTITLEWIDTH,True);
1055 /* put into state data */
1056 state->hffArgs.volumeTitle = str;
1057 state->hffArgs.volumeTitleColsWidth = width;
1060 /* get the volume's date */
1061 if (NULL == state->hffArgs.volumeDate)
1063 char * locDocId = NULL;
1064 char * locDateStamp = NULL;
1067 /* locDocId & locDateStamp will point to private memory; do not modify */
1068 _DtHelpCeGetDocStamp(state->volHandle,&locDocId, &locDateStamp);
1069 if ( NULL != locDateStamp
1070 && sscanf(locDateStamp, "%ld", &long_date) != 1 )
1071 locDateStamp = NULL; /* make invalid */
1073 date = (time_t)long_date;
1075 /* if no vol date, try getting from the help volume file */
1076 if ( NULL == locDateStamp )
1080 if ( stat(options->helpVolume,&stats) == 0 )
1081 date = stats.st_mtime;
1084 /* convert the int into a string */
1085 pTm = localtime(&date);
1086 strftime(buf,sizeof(buf),"%x",pTm);
1088 width = DoStrColsWidth(buf,0,False);
1090 /* put into state data */
1091 state->hffArgs.volumeDate = strdup(buf);
1092 state->hffArgs.volumeDateColsWidth = width;
1098 /* get today's date */
1099 if (NULL == state->hffArgs.todaysDate)
1101 /* convert the int into a string */
1103 pTm = localtime(&date);
1104 strftime(buf,sizeof(buf),"%x",pTm);
1106 width = DoStrColsWidth(buf,0,False);
1108 /* put into state data */
1109 state->hffArgs.todaysDate = strdup(buf);
1110 state->hffArgs.todaysDateColsWidth = width;
1113 /* get the topic title and its size */
1114 if (updateTopicTitle)
1116 /* get the topic title */
1118 _DtHelpCeGetTopicTitle(state->canvasHandle, state->volHandle,
1119 state->currentLocId, &str);
1120 if (NULL == str) str = strdup("");
1122 width = DoStrColsWidth(str,MAXTOPICTITLEWIDTH,True);
1124 /* put into state data */
1125 if (state->hffArgs.topicTitle) free(state->hffArgs.topicTitle);
1126 state->hffArgs.topicTitle = str;
1127 state->hffArgs.topicTitleColsWidth = width;
1130 /* get the size of the section number */
1133 width = DoStrColsWidth(sectNumStr,0,False);
1134 state->hffArgs.sectNumColsWidth = width;
1137 /* get the size of the page number */
1141 for ( width = 1, num = state->curPageNumber;
1142 (num >= 0) && ((num / 10) > 0);
1143 num /= 10, width++ )
1144 { /* do nothing */ }
1145 state->hffArgs.pageNumColsWidth = width;
1151 ===================================================================
1152 $PFUNBEG$: GenHeadFootFormatStr()
1153 $1LINER$: Generates a printf-ready format string for the header/footer
1155 Generates a printf-ready format string for the header/footer
1157 This function generates a string that uses the "%n$" prefix
1158 supported by printf(3S) to allow a footer/header string to
1159 ref any argument out of order. This functionality requires
1160 that a ref to *every* argument be part of the format string.
1161 Because not all args may be part of the user-specified format
1162 string, this function appends the unused strings to the end
1163 of the format string for purposes of sprintf(), then truncates
1164 the unused portion before output.
1167 ========================================================$SKIP$=====*/
1171 void GenHeadFootFormatStr(
1173 char * * io_formattedStr,
1176 char * lowLevelFormatStr;
1179 char unusedSyms[60];
1181 if (NULL == specStr)
1183 *io_formattedStr = NULL;
1185 return; /* RETURN */
1188 /*** create the formatted string ***/
1190 /* Make a working copy of the string; I assume that the
1191 values of 'argref' string always be shorter than 'symbol'. */
1192 lowLevelFormatStr = malloc(strlen(specStr) + sizeof(unusedSyms) + 10);
1193 if (NULL == lowLevelFormatStr) return;
1194 strcpy(lowLevelFormatStr,specStr);
1196 /* replace the symbolic names with printf argument refs */
1197 strcpy(unusedSyms,UNUSED_ARGREF);
1198 for ( sym = g_HeadFootSymsList; sym->symbol != NULL; sym++ )
1200 Boolean unused = True;
1202 /* look for the symbol string */
1203 while ( (substr = strstr(lowLevelFormatStr,sym->symbol)) != NULL )
1204 { /* and replace it with the argref */
1206 strcpy(substr, sym->argref);
1207 strcpy(substr + strlen(sym->argref), substr + strlen(sym->symbol));
1209 /* if unused, add to unused list */
1210 if (unused) strcat(unusedSyms,sym->argref);
1213 /* append unused syms to end of format str */
1214 strcat(lowLevelFormatStr,unusedSyms);
1216 /* store in caller's location */
1217 *io_formattedStr = lowLevelFormatStr;
1218 *io_lineCnt = CountLines(lowLevelFormatStr);
1223 ===================================================================
1224 $PFUNBEG$: GenAllHeadFootFormatStrs()
1225 $1LINER$: Generates printf-ready format strings for all headers/footers
1227 Generates printf-ready format strings for all headers/footers
1231 ========================================================$SKIP$=====*/
1235 void GenAllHeadFootFormatStrs(
1236 _DtHPrOptions * options,
1240 GenHeadFootFormatStr(options->tocHF.evenHeader,
1241 &state->tocHFF.formattedEvenHeader, &state->tocHFF.evenHeaderLineCnt);
1242 GenHeadFootFormatStr(options->tocHF.oddHeader,
1243 &state->tocHFF.formattedOddHeader, &state->tocHFF.oddHeaderLineCnt);
1244 GenHeadFootFormatStr(options->tocHF.evenFooter,
1245 &state->tocHFF.formattedEvenFooter, &state->tocHFF.evenFooterLineCnt);
1246 GenHeadFootFormatStr(options->tocHF.oddFooter,
1247 &state->tocHFF.formattedOddFooter, &state->tocHFF.oddFooterLineCnt);
1249 GenHeadFootFormatStr(options->bodyHF.evenHeader,
1250 &state->bodyHFF.formattedEvenHeader, &state->bodyHFF.evenHeaderLineCnt);
1251 GenHeadFootFormatStr(options->bodyHF.oddHeader,
1252 &state->bodyHFF.formattedOddHeader, &state->bodyHFF.oddHeaderLineCnt);
1253 GenHeadFootFormatStr(options->bodyHF.evenFooter,
1254 &state->bodyHFF.formattedEvenFooter, &state->bodyHFF.evenFooterLineCnt);
1255 GenHeadFootFormatStr(options->bodyHF.oddFooter,
1256 &state->bodyHFF.formattedOddFooter, &state->bodyHFF.oddFooterLineCnt);
1258 GenHeadFootFormatStr(options->indexHF.evenHeader,
1259 &state->indexHFF.formattedEvenHeader, &state->indexHFF.evenHeaderLineCnt);
1260 GenHeadFootFormatStr(options->indexHF.oddHeader,
1261 &state->indexHFF.formattedOddHeader, &state->indexHFF.oddHeaderLineCnt);
1262 GenHeadFootFormatStr(options->indexHF.evenFooter,
1263 &state->indexHFF.formattedEvenFooter, &state->indexHFF.evenFooterLineCnt);
1264 GenHeadFootFormatStr(options->indexHF.oddFooter,
1265 &state->indexHFF.formattedOddFooter, &state->indexHFF.oddFooterLineCnt);
1271 ===================================================================
1272 $PFUNBEG$: PrintHeadFootStr()
1273 $1LINER$: Formats and prints the header/footer string
1275 Takes a format string, replaces the place holders with actual values,
1276 and prints the output to topicsFP.
1278 This function uses the "%n$" prefix supported by printf(3S)
1279 to allow a footer/header string to ref any argument out of
1280 order. This functionality requires that a ref to *every*
1281 argument be part of the format string. Because not all args
1282 may be part of the user-specified format string, this function
1283 appends the unused strings to the end of the format string
1284 for purposes of sprintf(), then truncates the unused portion
1287 number of lines in the header or footer
1289 topicsFP: pointer to output stream. If NULL, increment
1290 page and reset line number), but do not output;
1291 If not NULL, request new page as well
1292 ========================================================$SKIP$=====*/
1296 int PrintHeadFootStr(
1297 _DtHPrOptions * options,
1300 char * formattedStr,
1303 char * newLine = "\n";
1305 char sectNumStr[MAXSECTS * 4 + 5]; /* $SECTNUM */
1308 if (NULL == formattedStr) return 0; /* RETURN */
1309 if (NULL == topicsFP) return lineCnt; /* RETURN */
1311 /*** generate dynamic data ***/
1313 /* get the section number */
1314 SectNumStr(state->sectNums,state->sectStr,sectNumStr);
1316 /* update args; FIX: impove efficiency by processing topic title only when needed */
1317 GenHeadFootFormatArgs(options,state,True,sectNumStr,True);
1319 /* guidelines on string size and construction:
1320 The objective is to allow one set of headers & footers to apply
1321 to many different volumes and topics. This is made possible by
1322 allowing for fixed length strings. To get fixed length strings,
1323 the header/footer spec should include not only the string but
1324 also the fill for that string.
1326 The fill size is calculated based on the following widths:
1327 volTitle : 50 printing chars e.g. "title "
1328 topicTitle : 50 printing chars e.g. "title "
1329 sectNumStr : 8 printing chars e.g. " 3.10.4"
1330 pageNum : 3 printing chars e.g. " 3"
1331 volDate : constant by locale--no fill needed e.g. "Mon, Jul 4, 1988"
1332 dateStr : constant by locale--no fill needed e.g. "Mon, Jul 4, 1988"
1335 /*** generate the str ***/
1336 /* IMPT: the order of these arguments MUST match the argument numbers
1337 given in the definition of the g_HeadFootSymsList variable. */
1338 /* print the first set */
1339 sprintf(buf, formattedStr,
1340 state->hffArgs.todaysDate,state->hffArgs.volumeTitle,
1341 state->hffArgs.topicTitle, (int) state->curPageNumber,
1342 state->hffArgs.volumeDate, sectNumStr,
1343 (int) options->colsAdjLeftMargin,(int) ' ' );
1345 /* move the format string for the second set into new memory */
1346 formattedStr = strdup(buf);
1347 if(NULL == formattedStr) return 0; /* RETURN */
1349 /* print the second set */
1350 sprintf(buf, formattedStr,
1351 MAXVOLTITLEWIDTH - state->hffArgs.volumeTitleColsWidth, (int) ' ',
1352 MAXTOPICTITLEWIDTH - state->hffArgs.topicTitleColsWidth, (int) ' ',
1353 MAXPAGENUMWIDTH - state->hffArgs.pageNumColsWidth, (int) ' ',
1354 MAXSECTNUMWIDTH - state->hffArgs.sectNumColsWidth, (int) ' ',
1356 buf[lastValid] = EOS; /* truncate unused args */
1359 /*** output the str ***/
1360 fprintf(topicsFP, "%s", buf);
1368 ===================================================================
1369 $PFUNBEG$: PrintFooter()
1370 $1LINER$: Print footer and use right form for odd/even pages
1372 Print footer and use right form for odd/even pages
1375 topicsFP: pointer to output stream. If NULL, increment
1376 lines), but do not output;
1377 ========================================================$SKIP$=====*/
1382 _DtHPrOptions * options,
1385 _DtHPrHeadFoot * headFootInfo,
1386 HeadFootFormat * headFootFormatting)
1388 /* fill to bottom of page */
1389 OutputBlankLines(topicsFP,state,
1390 (options->rowsTextHeight - state->curLineNumber) -
1391 ( (state->curPageNumber % 2) == 0
1392 ? headFootFormatting->evenFooterLineCnt
1393 : headFootFormatting->oddFooterLineCnt));
1395 if ( (state->curPageNumber % 2) == 0) /* Even page */
1396 state->curLineNumber += PrintHeadFootStr(options,topicsFP,state,
1397 headFootFormatting->formattedEvenFooter,
1398 headFootFormatting->evenFooterLineCnt);
1400 state->curLineNumber += PrintHeadFootStr(options,topicsFP,state,
1401 headFootFormatting->formattedOddFooter,
1402 headFootFormatting->oddFooterLineCnt);
1408 ===================================================================
1409 $PFUNBEG$: PrintHeader()
1410 $1LINER$: Print footer and use right form for odd/even pages
1412 Print footer and use right form for odd/even pages
1415 topicsFP: pointer to output stream. If NULL, increment
1416 lines), but do not output;
1417 ========================================================$SKIP$=====*/
1422 _DtHPrOptions * options,
1425 _DtHPrHeadFoot * headFootInfo,
1426 HeadFootFormat * headFootFormatting)
1429 if ( (state->curPageNumber % 2) == 0) /* Even page */
1430 state->curLineNumber += PrintHeadFootStr(options,topicsFP,state,
1431 headFootFormatting->formattedEvenHeader,
1432 headFootFormatting->evenHeaderLineCnt);
1434 state->curLineNumber += PrintHeadFootStr(options,topicsFP,state,
1435 headFootFormatting->formattedOddHeader,
1436 headFootFormatting->oddHeaderLineCnt);
1441 ===================================================================
1442 $PFUNBEG$: NewPage()
1443 $1LINER$: Outputs paper form feed, increments page count, resets line cnt
1445 Outputs paper form feed, increments page count, resets line cnt
1448 topicsFP: pointer to output stream. If NULL, increment
1449 page and reset line number), but do not output;
1450 If not NULL, request new page as well
1451 ========================================================$SKIP$=====*/
1456 _DtHPrOptions * options,
1459 Boolean advancePage)
1461 /* start new page: form feed */
1464 if (advancePage) fprintf(topicsFP,"
\f\n");
1466 /* print top margin but don't add it to line count because the rowsTextHeight
1467 value is calculated post-topMargin */
1468 OutputBlankLines(topicsFP,state,options->rowsAdjTopMargin);
1471 /* adjust page and line numbers */
1472 if (advancePage) state->curPageNumber++;
1473 state->curLineNumber = 1;
1478 ===================================================================
1479 $PFUNBEG$: ProcessOneTopic()
1480 $1LINER$: Recovers and formats help text for one topic
1482 Recovers and formats help text for one topic
1484 0: The number of lines output.
1485 -2: could not get topic information
1487 topicsFP: pointer to output stream. If NULL, process topic
1488 (e.g. count lines and inc page numbers), but do not output;
1489 If not NULL, output lines and page headers
1490 ========================================================$SKIP$=====*/
1494 int ProcessOneTopic(
1495 _DtHPrOptions * options,
1498 Boolean printHeaderFooter)
1500 char * * helpList = NULL;
1504 char sectNumStr[MAXSECTS * 4 + 5];
1506 /* retrieve the text (but not the hyperlinks) from the volume */
1507 if ( _DtHelpTermGetTopicData(state->canvasHandle, state->volHandle,
1508 state->currentLocId, &helpList, NULL) != 0 )
1510 fprintf(stderr,_DTGETMESSAGE(PTSET,5,
1511 "%s Error: unable to get topic information:\n"
1512 "volume %s, locationId %s\n"),
1513 options->programName, options->helpVolume, options->locationId);
1514 return -2; /* RETURN error */
1517 /* output topic section number */
1518 /* this operates on the assumption that topic title is first line */
1519 ptrToLst = helpList;
1520 SectNumStr(state->sectNums,state->sectStr,sectNumStr);
1521 if (sectNumStr[0] != EOS)
1523 /* NOTE: if allow the sect num string to be resource-defined,
1524 then count the number of \n chars in it; don't assume how many. */
1525 if (topicsFP) fprintf(topicsFP,"\n");
1526 OutputBlankSpaces(topicsFP,options->colsAdjLeftMargin);
1527 if (topicsFP) fprintf(topicsFP,"%s ", sectNumStr);
1528 state->curLineNumber++;
1530 /* and put the title (must be on first two lines) on the same line */
1531 if ( (*helpList && (*helpList)[0] != EOS)
1532 || (*(++helpList) && (*helpList)[0] != EOS) )
1538 ret = IconvBuffer( state->volHandle, *helpList, &_p );
1540 fprintf(topicsFP,"%s\n", _p); /* output title */
1542 fprintf(topicsFP,"%s\n", *helpList); /* output title */
1545 state->curLineNumber += CountLines(*helpList) + 1; /* 1=the known \n */
1550 /* calc number of available lines from top of page to footer */
1551 availLines = AvailContentLines(options,state,&state->bodyHFF);
1553 /* cycle through the lines; add new pages where necessary */
1554 for ( ; *helpList != NULL; helpList++ )
1556 /* NOTE: it's impt to calc the final line before outputting it,
1557 as the line may contain embedded newlines */
1558 int linesCnt = CountLines(*helpList) + 1; /* 1=the known \n */
1560 /* calc what line that will leave us on */
1561 state->curLineNumber += linesCnt;
1563 /* if at the end of a page, print footer, eject, and print header */
1564 if (state->curLineNumber >= availLines)
1566 /* output any filler blank lines */
1567 OutputBlankLines(topicsFP,state,
1568 availLines - (state->curLineNumber - linesCnt) );
1569 if (printHeaderFooter)
1570 PrintFooter(options,topicsFP,state,&options->bodyHF,&state->bodyHFF);
1571 NewPage(options,topicsFP,state,True);
1572 if (printHeaderFooter)
1573 PrintHeader(options,topicsFP,state,&options->bodyHF,&state->bodyHFF);
1575 /* recalc the line we're on */
1576 state->curLineNumber += linesCnt;
1578 /* calc number of available lines from top of page to footer */
1579 availLines = AvailContentLines(options,state,&state->bodyHFF);
1582 /* output the lines */
1585 OutputBlankSpaces(topicsFP,options->colsAdjLeftMargin);
1590 ret = IconvBuffer( state->volHandle, *helpList, &_p );
1592 fprintf(topicsFP,"%s\n", _p );
1594 fprintf(topicsFP,"%s\n",*helpList);
1600 /* free the memory of helpList */
1601 _DtHelpFreeTopicData(ptrToLst,NULL);
1609 ===================================================================
1610 $PFUNBEG$: ProcessSubTopics()
1611 $1LINER$: Recovers and formats help text for current & sub topics
1613 ond none should be printed. */
1615 Subsections are numbered according to the legal method (e.g. 1.5.4.3)
1617 Recovers and formats help text for current & sub topics
1620 -1: could not create or open a temp file
1621 -2: could not get help topic info
1622 INHIBIT_OUTPUT: stop outputting children; we printed all we need to
1624 level: may range from 1 to (MAXSECTS-1)
1625 ========================================================$SKIP$=====*/
1628 int ProcessSubTopics(
1629 _DtHPrOptions * options,
1635 char * * children = NULL;
1637 int firstSubSectNum;
1638 int subSectNumIndex;
1641 #define INHIBIT_OUTPUT (-3)
1642 /* remember, don't turn inhibitOutput on if there's no match */
1643 if ( _DtHelpCeStrCaseCmp(state->outputFromLocId,state->currentLocId) == 0 )
1647 /* toggle the flag and set ret value */
1648 state->inhibitOutput = False;
1649 ret = INHIBIT_OUTPUT; /* stop printing after this topic & its children */
1651 curPos = state->curLineNumber; /* save off the current line position */
1653 /* start new page but don't eject; output header;
1654 output right number of blank lines to get to where topic starts */
1655 NewPage(options,topicsFP,state,False);
1656 PrintHeader(options,topicsFP,state,&options->bodyHF,&state->bodyHFF);
1657 OutputBlankLines(topicsFP,state,curPos - state->curLineNumber);
1661 curFP = (state->inhibitOutput ? (FILE *) NULL : topicsFP);
1663 /* init according to level */
1664 if(level == 0) /* the top topic? */
1665 { /* put top topic at same level as children */
1666 firstSubSectNum = 2;
1667 subSectNumIndex = 1;
1669 /* no prior instance of ProcessSubTopics() set this */
1670 state->sectNums[subSectNumIndex] = 1;
1672 else /* not the top topic */
1674 firstSubSectNum = 1;
1675 subSectNumIndex = level;
1676 state->level = level;
1679 /* add this topic to the toc */
1680 TocNewEntry(toc,state->currentLocId,state->curPageNumber,
1681 state->level,state->sectNums,state->sectStr);
1683 /* retrieve and possibly output the current topic */
1684 ProcessOneTopic(options,curFP,state,True);
1686 /* output the sub topics */
1687 if (_DtHelpCeGetTopicChildren(state->volHandle,
1688 state->currentLocId,&children) > 0)
1691 Boolean initSubSect = True;
1693 /* cycle through the topics and output each one */
1694 for (topic = children; *topic != NULL && (*topic)[0]; topic++ )
1696 /* start level 0 & 1 topics on a new page */
1697 if ( subSectNumIndex < 2 )
1699 PrintFooter(options,curFP,state,&options->bodyHF,&state->bodyHFF);
1700 NewPage(options,curFP,state,True);
1701 PrintHeader(options,curFP,state,&options->bodyHF,&state->bodyHFF);
1704 /* avoid orphans (i.e. require more than 4 lines left on page) */
1705 if ( (AvailContentLines(options,state,&state->bodyHFF)
1706 - state->curLineNumber) < 4 )
1708 PrintFooter(options,curFP,state,&options->bodyHF,&state->bodyHFF);
1709 NewPage(options,curFP,state,True);
1710 PrintHeader(options,curFP,state,&options->bodyHF,&state->bodyHFF);
1713 /* init new sub sect, if haven't yet done so */
1716 /* start new subsection; -1: make up for ++ later */
1717 state->sectNums[subSectNumIndex] = firstSubSectNum - 1;
1718 initSubSect = False;
1721 /* make this the current topic */
1722 state->currentLocId = *topic;
1723 /* use subSectNumIndex, not level, so that the top topic and its
1724 immediate children are at the same level */
1725 /* inc the sect num before the call so that the
1726 sect used below in the INHIBIT_OUTPUT wrapup is correct. */
1727 /* pass in topicsFP, not curFP */
1728 state->sectNums[subSectNumIndex]++; /* next subsection */
1729 /* even though ProcessSubTopics() can return 'INHIBIT_OUTPUT',
1730 don't stop processing, as this would cause the Toc to
1732 ProcessSubTopics(options,topicsFP,toc, subSectNumIndex+1,state);
1733 /* ProcessSubTopics(options,topicsFP,toc, state->level+1,state); */
1737 /* if this is the last topic to be output, then finish up */
1738 if (ret == INHIBIT_OUTPUT)
1740 /* save off line num */
1741 int curLine = state->curLineNumber;
1744 PrintFooter(options,curFP,state,&options->bodyHF,&state->bodyHFF);
1745 state->inhibitOutput = True; /* inhibit again */
1747 /* restore line num */
1748 state->curLineNumber = curLine;
1751 /* if processing subtopics, reset subsection number */
1752 if(subSectNumIndex > 1) state->sectNums[subSectNumIndex] = 0;
1753 state->level = level; /* state->level was modified by the FOR loop */
1761 ===================================================================
1762 $PFUNBEG$: ProcessFrontMatter()
1763 $1LINER$: Process the help volume to generate a file of front matter
1765 Process the help volume to generate a file of front matter
1768 -1: could not create or open a temp file
1769 -2: could not get help topic info
1771 ========================================================$SKIP$=====*/
1775 int ProcessFrontMatter(
1776 _DtHPrOptions * options,
1777 char * * ret_resultsFile,
1784 fp = OpenTmpFile(options,ret_resultsFile);
1785 if (NULL == fp) return -1; /* RETURN: error */
1787 /*** process text ***/
1788 /* setup the state */
1789 state->inhibitOutput = False;
1790 state->curPageNumber = 1;
1791 state->curLineNumber = 1;
1792 state->sectNums[0] = 0; /* inhibit section num printing */
1793 state->sectStr = NULL; /* inhibit section string printing */
1795 OutputBlankLines(fp,state, options->rowsTextHeight / 3);
1797 /* NOTE: the code below causes the memory allocated for currentLocId
1798 to be lost. I didn't fix this to save a few bytes of code space. */
1800 /* generate volume title */
1801 state->currentLocId = strdup("_TITLE");
1802 state->outputFromLocId = state->currentLocId;
1803 ret = ProcessOneTopic(options,fp,state,False);
1804 /*free(state->currentLocId);*/
1806 NewPage(options,fp,state,True);
1808 /* generate abstract */
1809 state->currentLocId = strdup("_ABSTRACT");
1810 state->outputFromLocId = state->currentLocId;
1811 ret = ProcessOneTopic(options,fp,state,False);
1812 /*free(state->currentLocId);*/
1814 /* Make a space between abstract and copyright */
1815 if ( AvailContentLines(options,state,&state->indexHFF) > 3 )
1816 OutputBlankLines(fp,state, 3);
1818 NewPage(options,fp,state,True);
1820 /* generate copyright */
1821 state->currentLocId = strdup("_COPYRIGHT");
1822 state->outputFromLocId = state->currentLocId;
1823 ret = ProcessOneTopic(options,fp,state,False);
1824 /*free(state->currentLocId);*/
1825 /*state->currentLocId = NULL;*/
1835 ===================================================================
1836 $PFUNBEG$: ProcessIndex()
1837 $1LINER$: Process the TOC data to generate an index file
1839 Process the TOC data to generate an index file
1841 This function uses state->pageNumber+1 as the first page
1845 -1: could not create or open a temp file
1846 -2: could not get help topic info
1848 ========================================================$SKIP$=====*/
1853 _DtHPrOptions * options,
1854 char * * ret_resultsFile,
1861 char * * indexEntriesList;
1865 *ret_resultsFile = NULL;
1867 /* Get the index. Recall that the array and strings pointed to by
1868 the indexEntriesList is owned by the open volume */
1869 entriesCnt = _DtHelpCeGetKeywordList(state->volHandle,&indexEntriesList);
1870 if (entriesCnt <= 0) return 0;
1873 fp = OpenTmpFile(options,ret_resultsFile);
1874 if (NULL == fp) return -1; /* RETURN: error */
1876 /*** process index ***/
1878 /* setup the state */
1879 state->curPageNumber++; /* inc page number from prev. value */
1880 state->inhibitOutput = False;
1881 state->curLineNumber = 1;
1882 state->sectNums[0] = 0; /* inhibit section num printing */
1883 state->sectStr = _DTGETMESSAGE(PTSET,10,"Index"); /* $SECTNUM name */
1885 /* add an index entry to the TOC */
1886 TocNewEntry(toc,_DTGETMESSAGE(PTSET,30,"__GENERATED-INDEX"),
1887 state->curPageNumber, 1,state->sectNums,state->sectStr);
1889 /* start new page (but don't eject) and output header */
1890 NewPage(options,fp,state,False);
1891 PrintHeader(options,fp,state,&options->indexHF,&state->indexHFF);
1893 /* calc number of available lines from top of page to footer */
1894 availLines = AvailContentLines(options,state,&state->indexHFF);
1896 /*** loop through the entries ***/
1897 for ( entryStr = *indexEntriesList++;
1899 entryStr = *indexEntriesList++ )
1901 char * * topicIdsList;
1904 TocEntry * tocEntry;
1906 /* get the topics associated with this entry */
1907 /* topicIdsList is set but not allocated & need not be freed */
1908 topicCnt = _DtHelpCeFindKeyword(state->volHandle,
1909 entryStr,&topicIdsList);
1910 if (topicCnt <= 0) continue; /* CONTINUE */
1912 /*** if only one topic, just put page number after the entry ***/
1915 /* find the toc entry of the topic */
1916 ret = TocFindSortedEntry(toc, *topicIdsList, NULL, &tocEntry);
1917 if (ret < 0) continue; /* CONTINUE */
1919 /* output the entry */
1920 OutputBlankSpaces(fp,options->colsAdjLeftMargin);
1925 ret = IconvBuffer( state->volHandle, entryStr, &_p );
1927 fprintf(fp, _DTGETMESSAGE(PTSET,20,"%s, %d\n"),
1928 _p, tocEntry->pageNumber);
1930 fprintf(fp, _DTGETMESSAGE(PTSET,20,"%s, %d\n"),
1931 entryStr, tocEntry->pageNumber);
1934 state->curLineNumber++;
1936 /* if at the end of a page, print footer, eject, and print header */
1937 if (state->curLineNumber >= availLines)
1939 PrintFooter(options,fp,state,&options->indexHF,&state->indexHFF);
1940 NewPage(options,fp,state,True);
1941 PrintHeader(options,fp,state,&options->indexHF,&state->indexHFF);
1942 /* calc number of available lines from top of page to footer */
1943 availLines = AvailContentLines(options,state,&state->indexHFF);
1946 continue; /* CONTINUE */
1949 /*** if more than one topic, list topic title & page number under the entry ***/
1951 /* do we need a new page to start this entry? */
1952 if ( (availLines - state->curLineNumber) < 3 )
1954 PrintFooter(options,fp,state,&options->indexHF,&state->indexHFF);
1955 NewPage(options,fp,state,True);
1956 PrintHeader(options,fp,state,&options->indexHF,&state->indexHFF);
1957 /* calc number of available lines from top of page to footer */
1958 availLines = AvailContentLines(options,state,&state->indexHFF);
1961 OutputBlankSpaces(fp,options->colsAdjLeftMargin);
1966 ret = IconvBuffer( state->volHandle, entryStr, &_p );
1968 fprintf(fp,"%s\n", _p );
1970 fprintf(fp,"%s\n", entryStr);
1973 state->curLineNumber++;
1975 /* for all topics in an index entry */
1978 i++, topicIdsList++ )
1982 if (NULL == *topicIdsList) continue; /* CONTINUE */
1984 /* find the toc entry of the topic */
1985 ret = TocFindSortedEntry(toc, *topicIdsList, NULL, &tocEntry);
1986 if (ret < 0) continue; /* CONTINUE */
1988 /* get the topic title */
1989 _DtHelpCeGetTopicTitle(state->canvasHandle, state->volHandle,
1990 tocEntry->locationId, &topicTitle);
1991 if (NULL == topicTitle)
1992 topicTitle = _DTGETMESSAGE(PTSET,31,EMPTY_STR);
1994 /* output the entry */
1995 OutputBlankSpaces(fp,options->colsAdjLeftMargin);
2000 ret = IconvBuffer( state->volHandle, topicTitle, &_p );
2002 fprintf(fp,_DTGETMESSAGE(PTSET,21," %s, %d\n"),
2003 _p, tocEntry->pageNumber);
2005 fprintf(fp,_DTGETMESSAGE(PTSET,21," %s, %d\n"),
2006 topicTitle, tocEntry->pageNumber);
2009 state->curLineNumber++;
2011 /* if at the end of a page, print footer, eject, and print header */
2012 if (state->curLineNumber >= availLines)
2014 PrintFooter(options,fp,state,&options->indexHF,&state->indexHFF);
2015 NewPage(options,fp,state,True);
2016 PrintHeader(options,fp,state,&options->indexHF,&state->indexHFF);
2017 /* calc number of available lines from top of page to footer */
2018 availLines = AvailContentLines(options,state,&state->indexHFF);
2020 } /* for all topics in an index entry */
2022 } /* for all index entries */
2025 PrintFooter(options,fp,state,&options->indexHF,&state->indexHFF);
2035 ===================================================================
2036 $PFUNBEG$: ProcessToc()
2037 $1LINER$: Process the TOC data to generate a toc file
2039 Process the TOC data to generate a toc file
2042 -1: could not create or open a temp file
2043 -2: could not get help topic info
2045 ========================================================$SKIP$=====*/
2050 _DtHPrOptions * options,
2051 char * * ret_resultsFile,
2060 fp = OpenTmpFile(options,ret_resultsFile);
2061 if (NULL == fp) return -1; /* RETURN: error */
2063 /*** process toc ***/
2065 /* setup the state */
2066 state->inhibitOutput = False;
2067 state->curPageNumber = 1;
2068 state->curLineNumber = 1;
2069 state->sectNums[0] = 0; /* inhibit section num printing */
2070 state->sectStr = _DTGETMESSAGE(PTSET,11,"Table of Contents"); /* $SECTNUM name */
2072 /* start new page and output header */
2073 NewPage(options,fp,state,False);
2074 PrintHeader(options,fp,state,&options->tocHF,&state->tocHFF);
2076 /* calc number of available lines from top of page to footer */
2077 availLines = AvailContentLines(options,state,&state->tocHFF);
2079 /* walk through the toc; output the label, title string, and page num */
2080 for ( entry = TocNextEntry(toc,NULL);
2082 entry = TocNextEntry(toc,entry) )
2084 char sectNumStr[MAXSECTS * 4 + 5]; /* $SECTNUM */
2085 char * title = NULL;
2092 /* get the data to print */
2093 SectNumStr(entry->sectNums,entry->sectStr,sectNumStr);
2094 _DtHelpCeGetTopicTitle(state->canvasHandle, state->volHandle,
2095 entry->locationId, &title);
2096 if (NULL == title) title = EMPTY_STR;
2098 /* set max length of title and calc num blanks needed */
2099 lhsWidth = strlen(sectNumStr) + 1; /* 1=blank after sect num */
2100 titlelen = strlen(title);
2101 wctitle = malloc(sizeof(wchar_t) * (titlelen+1));
2102 /* truncate the title using wchar_t */
2105 /* convert title to wchar_t and get num chars */
2106 mbstowcs(wctitle,title,titlelen+1);
2107 titlelen = wcslen(wctitle);
2108 /* truncate the title to fit on the line */
2109 if (titlelen > options->colsTextWidth - lhsWidth)
2111 wctitle[options->colsTextWidth - lhsWidth - 1] = EOS;
2112 titlelen = wcslen(wctitle);
2114 wcstombs(title,wctitle,titlelen+1);
2117 /* truncate the title assuming single-byte */
2118 else if (titlelen > options->colsTextWidth - lhsWidth)
2120 title[options->colsTextWidth - lhsWidth - 1] = EOS;
2121 titlelen = strlen(title);
2123 lhsWidth += titlelen;
2125 /* add a blank line before a major section */
2126 if ( 0 == entry->sectNums[2] )
2129 state->curLineNumber++;
2131 /* do we need a new page to start this section? */
2132 if ( (availLines - state->curLineNumber) < 3 )
2134 PrintFooter(options,fp,state,&options->tocHF,&state->tocHFF);
2135 NewPage(options,fp,state,True);
2136 PrintHeader(options,fp,state,&options->tocHF,&state->tocHFF);
2137 /* calc number of available lines from top of page to footer */
2138 availLines = AvailContentLines(options,state,&state->tocHFF);
2142 /* output the beginning of the line */
2143 if ( sectNumStr[0] == EOS ) /* no section number */
2145 /* space between title and page num */
2146 /* 1: no sect num so no space betw sect num & title */
2147 /* -3: reserve 3 spaces for the page number */
2148 blanksCnt = ((options->colsTextWidth - lhsWidth) - 3) + 1;
2154 ret = IconvBuffer( state->volHandle, title, &_p );
2156 fprintf(fp,"%*c%s", options->colsAdjLeftMargin, ' ', _p );
2158 fprintf(fp,"%*c%s", options->colsAdjLeftMargin, ' ', title);
2163 else /* valid section number */
2165 /* space between title and page num */
2166 /* -3: reserve 3 spaces for the page number */
2167 blanksCnt = (options->colsTextWidth - lhsWidth) - 3;
2173 ret = IconvBuffer( state->volHandle, title, &_p );
2175 fprintf(fp,"%*c%s %s",
2176 options->colsAdjLeftMargin, ' ', sectNumStr, _p );
2178 fprintf(fp,"%*c%s %s",
2179 options->colsAdjLeftMargin, ' ', sectNumStr, title);
2184 /* output the filler and page number */
2185 if ( (blanksCnt % 2) != 0) { fputc(' ',fp); blanksCnt--; }
2186 for( ;blanksCnt > 0; blanksCnt -= 2) fprintf(fp," .");
2187 fprintf(fp,"%3d\n", entry->pageNumber);
2189 state->curLineNumber++;
2191 /* if at the end of a page, print footer, eject, and print header */
2192 if (state->curLineNumber >= availLines)
2194 PrintFooter(options,fp,state,&options->tocHF,&state->tocHFF);
2195 NewPage(options,fp,state,True);
2196 PrintHeader(options,fp,state,&options->tocHF,&state->tocHFF);
2197 /* calc number of available lines from top of page to footer */
2198 availLines = AvailContentLines(options,state,&state->tocHFF);
2200 } /* for all entries */
2203 PrintFooter(options,fp,state,&options->tocHF,&state->tocHFF);
2212 ===================================================================
2213 $PFUNBEG$: ProcessTopics()
2214 $1LINER$: Process the help volume to generate a topics file
2216 Process the TOC data to generate a toc file
2219 -1: could not create or open a temp file
2220 -2: could not get help topic info
2222 outputFromLocId: output of topics occurs for this topic and all its
2223 subtopics. This topic Id is strcasecmp()ed against the
2224 current Id to determine a match. If NULL, the volume
2226 inhibitTopicsOutput: if true, output only starts when outputFromLocId is found
2228 outputFromLocId inhibitOutput action
2229 --------------- ------------- -------------------------------------
2230 NULL True no output is generated
2231 NULL False output begins with the top topic
2232 != NULL True output begins with outputFromLocId
2233 and stops after last subtopic of
2235 != NULL False output begins with the top topic
2236 and stops after last subtopic of
2238 ========================================================$SKIP$=====*/
2243 _DtHPrOptions * options,
2244 char * * ret_resultsFile,
2247 Boolean processSubTopics,
2248 char * outputFromLocId,
2249 Boolean inhibitTopicsOutput)
2254 /* don't print a single topic with no locId */
2255 if ( processSubTopics == False
2256 && (outputFromLocId == NULL || *outputFromLocId == EOS) )
2257 return 0; /* RETURN: ok */
2259 /* if no output is desired, set ptr to NULL */
2260 if ( NULL == outputFromLocId && inhibitTopicsOutput )
2263 { /* output is desired...open file */
2264 fp = OpenTmpFile(options,ret_resultsFile);
2265 if (NULL == fp) return -1; /* RETURN: error */
2268 /*** process text ***/
2270 /* if processing subtopics, start processing at the top */
2271 if ( processSubTopics )
2275 /* get the top topic of the volume */
2276 ret = _DtHelpCeGetTopTopicId(state->volHandle, &state->currentLocId);
2277 if (ret != True) state->currentLocId = strdup("_HOMETOPIC");
2280 { /* otherwise, process only where needed */
2281 state->currentLocId = strdup(outputFromLocId);
2284 /* set the other state values */
2285 if ( NULL != outputFromLocId
2286 && (ret = _DtHelpCeIsTopTopic(state->volHandle,outputFromLocId)) != 0 )
2287 state->outputFromLocId = outputFromLocId;
2289 state->outputFromLocId = state->currentLocId;
2290 state->inhibitOutput = inhibitTopicsOutput;
2291 state->curPageNumber = 1;
2292 state->curLineNumber = 1;
2294 /* output topics but don't inhibit */
2295 if ( processSubTopics )
2297 state->sectNums[0] = 1; /* support section num printing */
2298 /* 0: level of the top topic; note tha this is diff from the
2299 level of the top topic in an SDL volume, which is 1. This
2300 is merely for convenience, to make addressing into the
2301 sectNums array directly rather than subtracting 1 or 2 to
2302 get the array index from the level. */
2303 ret = ProcessSubTopics(options,fp,toc,0,state);
2307 /* start new page but don't eject; output header;
2308 output right number of blank lines to get to where topic starts */
2310 state->sectNums[0] = 0; /* inhibit section num printing */
2311 NewPage(options,fp,state,False); /* for top margin */
2312 PrintHeader(options,fp,state,&options->bodyHF,&state->bodyHFF);
2314 ret = ProcessOneTopic(options,fp,state,True);
2317 PrintFooter(options,fp,state,&options->bodyHF,&state->bodyHFF);
2320 /* if the file was opened, close & check if anything written to it */
2321 /* if empty, pretend the file wasn't created. */
2324 Boolean empty = False;
2327 if (pos <= 0) empty = True;
2331 unlink(*ret_resultsFile);
2332 free(*ret_resultsFile);
2333 *ret_resultsFile = NULL;
2342 ===================================================================
2343 $PFUNBEG$: MakePageBreakFile()
2344 $1LINER$: Creates a file with only a page break char in it
2346 Creates a file with only a page break char in it.
2347 If fails, file ptr is NULL
2350 ========================================================$SKIP$=====*/
2354 void MakePageBreakFile(
2355 _DtHPrOptions * options,
2356 char * * ret_resultsFile)
2360 fp = OpenTmpFile(options,ret_resultsFile);
2363 free(*ret_resultsFile);
2364 *ret_resultsFile = NULL;
2373 ===================================================================
2374 $PFUNBEG$: DoHelpTopicsProcessing()
2375 $1LINER$: Passes through entire volume and generates toc and topic output
2377 Passes through entire volume and generates toc and topic output
2380 -1: could not create or open a temp file
2381 -2: could not get help topic info
2382 -3: could not alloc memory
2384 ========================================================$SKIP$=====*/
2388 int DoHelpTopicsProcessing(
2389 _DtHPrOptions * options,
2390 char * * ret_resultsFile,
2392 Boolean processIndex,
2393 Boolean processFrontMatter,
2394 Boolean processSubTopics,
2395 char * outputFromLocId,
2396 Boolean inhibitTopicsOutput)
2411 char * pgbrkFile = NULL;
2412 char * partFiles[NUMPARTS];
2413 Boolean validFile = False;
2415 /* init larger vars to 0 */
2416 memset(&toc,0,sizeof(Toc));
2417 memset(&state,0,sizeof(state));
2418 memset(partFiles,0,sizeof(partFiles));
2420 /* create terminal-based canvas for text retrieval */
2421 ret = _DtHelpTermCreateCanvas(options->colsTextWidth,&state.canvasHandle);
2422 if ( ret != 0 ) return ret; /* RETURN: error */
2424 /* open volume and get state.volHandle */
2425 ret = _DtHelpCeOpenVolume(state.canvasHandle,
2426 options->helpVolume, &state.volHandle);
2427 if ( ret != 0 ) return ret; /* RETURN: error */
2429 /* do some prepatory format string generation */
2430 GenAllHeadFootFormatStrs(options,&state);
2432 /* after this point, if we get an error, we don't return--we do the best we can */
2433 /* so don't monitor the return values. */
2435 /*** process a help volume; maybe create a topics file ***/
2436 /* always do this, as all other processing (except FM) needs the data */
2437 ret=ProcessTopics(options,&partFiles[TOPICS],&state,&toc,
2438 processSubTopics,outputFromLocId,inhibitTopicsOutput);
2440 /*** process toc to create an index and add an index entry to toc ***/
2441 /* Do this right after processing topics so that page number info is right */
2443 ret=ProcessIndex(options,&partFiles[INDEX],&state,&toc);
2445 /*** process volume to create front matter ***/
2446 if (processFrontMatter)
2447 ret=ProcessFrontMatter(options,&partFiles[FM],&state);
2449 /*** process toc to create a toc; do this last to get all entries ***/
2451 ret=ProcessToc(options,&partFiles[TOC],&state,&toc);
2453 /*** create the final output file ***/
2455 MakePageBreakFile(options,&pgbrkFile);
2457 /* create a temporary file in $HOME/.dt/tmp to hold everything */
2458 /* Put in $HOME/.dt/tmp so that if the printer operation is running
2459 of a remote system, it can get to the (local) temp file.
2460 This would not be possible if the file were put in /tmp */
2461 *ret_resultsFile = _DtHPrCreateTmpFile(TMPFILE_PREFIX,TMPFILE_SUFFIX);
2462 if (NULL == *ret_resultsFile) { ret = -1; goto cleanup; } /* RETURN: error */
2464 buf = malloc(3000 * sizeof(char));
2465 if (NULL == buf) { ret = -3; goto cleanup; } /* RETURN: error */
2467 /* cat together the part files that got created in the array order */
2468 /* separate them with a file containing only a page break */
2470 start = buf + strlen(buf);
2472 for (i=0; i<NUMPARTS; i++)
2476 /* if at least one file in cat list, separate from it with a pgbrk */
2477 if (start != next && pgbrkFile)
2479 sprintf(next,"%s ", pgbrkFile);
2480 next += strlen(next);
2482 sprintf(next,"%s ", partFiles[i]);
2483 next += strlen(next);
2487 /* only do the operation if there are valid files */
2491 sprintf(next,"> %s", *ret_resultsFile);
2492 if(options->debugHelpPrint) printf("%s\n",buf);
2498 /* if needed, iconv file and change filenames */
2500 /* close the volume when done */
2501 _DtHelpCeCloseVolume(state.canvasHandle,state.volHandle);
2505 /* delete all part files */
2506 for (i=0; i<NUMPARTS; i++)
2509 unlink(partFiles[i]);
2517 /* NOTE: should free Toc here if interested in no leaks */
2524 ===================================================================
2525 $PFUNBEG$: GenerateTopicsFile()
2526 $1LINER$: Recovers and formats help topic text and then sends to printer
2528 Recovers and formats help topic text and then sends to printer
2531 ========================================================$SKIP$=====*/
2535 int GenerateTopicsFile(
2537 _DtHPrOptions * options,
2538 char * * ret_resultsFile)
2541 Boolean allTopics = (options->allTopics != NULL);
2542 Boolean subTopics = (options->subTopics != NULL);
2543 Boolean toc = (options->toc != NULL);
2544 Boolean index = (options->index != NULL);
2545 Boolean frontMatter = (options->frontMatter != NULL);
2546 Boolean oneTopic = (options->oneTopic != NULL);
2547 Boolean dfltOneTopic;
2548 char * locationId = options->locationId;
2550 /* one topic is selected if other options aren't selected */
2551 dfltOneTopic = !(allTopics || subTopics || toc || index);
2553 /* This is sort of a kludge, but since we don't require the -One flag,
2554 this keeps the _Hometopic from being printed along with
2555 the front matter, when only front matter was specified */
2556 if (frontMatter && !oneTopic && dfltOneTopic)
2557 locationId = NULL; /* prevent printing the hometopic */
2559 /* to generate a toc or index, we need to process all topics; if
2560 processing all or subtopics wasn't requested, request it;
2561 and set a locationId that will never match (an empty string) */
2562 if ( (toc || index) && !allTopics )
2564 if (!subTopics) locationId = "";
2568 /* check the flags and do right thing */
2569 if (oneTopic || dfltOneTopic)
2570 /* False: no subtopics--output only locationId; False: don't inhibit output */
2571 ret = DoHelpTopicsProcessing(
2572 options, ret_resultsFile,
2573 False, False, frontMatter,
2574 False, locationId, False);
2576 /* start at root and don't inhibit output */
2577 ret = DoHelpTopicsProcessing(
2578 options, ret_resultsFile,
2582 ret = DoHelpTopicsProcessing(
2583 options, ret_resultsFile,
2584 toc, index, frontMatter,
2585 subTopics, locationId,True);
2593 ===================================================================
2594 $FUNBEG$: _DtHPrPrintHelpTopic()
2595 $1LINER$: Recovers and formats help topic text and then sends to printer
2597 Recovers and formats help topic text and then sends to printer
2600 ========================================================$SKIP$=====*/
2603 int _DtHPrPrintHelpTopic(
2605 _DtHPrOptions * options)
2607 char * printCommand;
2608 char cmdFormat[100];
2609 char prOffsetArg[30];
2615 if ( NULL == options->helpVolume )
2617 fprintf(stderr, _DTGETMESSAGE(PTSET,1,
2618 "%s: Error: helpType is topic, "
2619 "but no helpVolume specified.\n"),
2620 options->programName);
2622 return 1; /* RETURN error */
2625 /* try to locate the volume */
2626 path = _DtHelpFileLocate(DtHelpVOLUME_TYPE, options->helpVolume,
2627 _DtHelpFileSuffixList,False,R_OK);
2630 fprintf(stderr, _DTGETMESSAGE(PTSET,2,
2631 "%s Error: unable to locate help volume '%s'\n"),
2632 options->programName, options->helpVolume);
2634 return 1; /* RETURN error */
2636 options->helpVolume = path; /* don't free old helpVolume: owned by Xrm */
2638 /* generate a file containing the help topic */
2639 status = GenerateTopicsFile(dpy,options,&tmpFile);
2642 fprintf(stderr, _DTGETMESSAGE(PTSET,3,
2643 "%s Error: problem processing help volume '%s'\n"),
2644 options->programName, options->helpVolume);
2646 return 1; /* RETURN error */
2649 /* Alloc max shell command line len */
2650 printCommand = malloc(MAX_COMMAND_LENGTH*sizeof(char));
2651 if (printCommand == NULL)
2653 fprintf(stderr, _DTGETMESSAGE(PTSET,4,
2654 "%s Error: memory allocation failed\n"),
2655 options->programName);
2657 return 1; /* RETURN error */
2661 /** generate the file **/
2662 sprintf(printCommand,"cat %s",tmpFile);
2664 status = _DtHPrGenFileOrPrint(options,"Help Topic(s)",printCommand);
2673 #if 0 /* This is left-over code that used to deal with printing
2674 raster images. We don't need it for printing text-only.
2675 I left it here for future reference. */
2677 ===================================================================
2678 $FUNBEG$: _DtHPrPrintHelpTopicWithXvp()
2679 $1LINER$: Recovers and formats help topic text and then sends to printer
2681 Recovers and formats help topic text and then sends to printer
2683 Code left over from VUE 3.0 help print
2684 Has not been updated.
2687 ========================================================$SKIP$=====*/
2690 int _DtHPrPrintHelpTopicWithXvp(
2692 VolumeHandle volHandle,
2695 extern _DtHelpDisplayAreaStruct *Spoof();
2701 XFontStruct *defaultFont;
2702 XFontStruct *pageNumberFont;
2703 _DtHelpDisplayAreaStruct *pDAS;
2709 Window main_windowX;
2714 XFontStruct *defaultFontX;
2717 #define MY_WIDTH 400
2718 #define MY_HEIGHT 400
2719 #define DEFAULT_FONT "-agfa-courier-normal-r-normal-93950-0-120-300-300-m-0-hp-roman8"
2722 /* set color to bitonal */
2723 value.addr = RN_bitonal;
2724 value.size = strlen(RN_BITONAL) + 1;
2725 XrmPutResource(&XvpDB, STAR_RN_helpColorUse, *str_type, &value);
2729 /********************/
2730 /* Get display name */
2731 /********************/
2733 strcpy(resource_name, name_prefix);
2734 strcat(resource_name, RN_display);
2735 strcpy(resource_class, class_prefix);
2736 strcat(resource_class, RC_display);
2737 if (XrmGetResource(appDB, resource_name,
2739 str_type, &value) == True)
2740 displayNameX = value.addr;
2741 else displayNameX = EMPTY_STR;
2744 strcpy(resource_name, name_prefix);
2745 strcat(resource_name, RN_jobTitle);
2746 strcpy(resource_class, class_prefix);
2747 strcat(resource_class, RC_jobTitle);
2748 if (XrmGetResource(appDB, resource_name,
2750 str_type, &value) == True)
2751 lpDocName = (char *)value.addr;
2753 lpDocName = DFLT_JOB_TITLE_STR;
2755 status = XvpEscape(dpy, STARTDOC, strlen(lpDocName), lpDocName, NULL);
2756 screen = DefaultScreen(dpy);
2758 /* Calculate application page size */
2760 _DtHPrCalculatePageSize(dpy, &x, &y, &width, &height);
2762 /* create a window; x, y, width, and height are recorded */
2763 main_window = XCreateSimpleWindow(dpy, XRootWindow(dpy, screen),
2767 10, 0, XWhitePixel (dpy, screen));
2768 /* 0, 0, MY_WIDTH, MY_HEIGHT, 10, 0, XWhitePixel (dpy, screen)); */
2770 XSelectInput (dpy, main_window, ExposureMask);
2771 XMapWindow (dpy, main_window);
2772 XvpEscape(dpy, SET_IMAGE_RESOLUTION, 4, 100, NULL);
2774 defaultFont = XLoadQueryFont (dpy, DEFAULT_FONT);
2775 if (defaultFont == NULL)
2777 printf ("Unable to get a font\n");
2781 gc = DefaultGC(dpy, screen);
2782 XSetForeground (dpy, gc, XBlackPixel (dpy, screen));
2783 XSetBackground (dpy, gc, XWhitePixel (dpy, screen));
2784 XSetFont(dpy, gc, defaultFont->fid);
2785 XSetLineAttributes(dpy, gc, 2, LineSolid, CapButt, JoinMiter);
2787 #ifndef RASTER_PRINT
2789 XLoadQueryFont (dpy,
2790 "-agfa-univers-normal-r-normal-94021-0-100-300-300-p-0-iso8859-1");
2791 if (pageNumberFont == NULL)
2793 printf ("Unable to get a font\n");
2797 pageNumberGC = XCreateGC(dpy, RootWindow(dpy, screen), NULL, NULL);
2798 XSetForeground (dpy, pageNumberGC, XBlackPixel (dpy, screen));
2799 XSetBackground (dpy, pageNumberGC, XWhitePixel (dpy, screen));
2800 XSetFont(dpy, pageNumberGC, pageNumberFont->fid);
2801 XSetLineAttributes(dpy, pageNumberGC, 2, LineSolid, CapButt, JoinMiter);
2805 widthX = width/3; /* hard coded for 300 dpi printers */
2807 status = CreateRealXObjects(displayNameX, widthX, heightX,
2808 &dpyX, &main_windowX, &gcX,
2809 &invert_gcX, &defaultFontX);
2810 dpyX->db = dpy->db; /* carry over data base */
2812 pDAS = Spoof (dpyX, gcX, invert_gcX, defaultFontX, widthX, heightX, lineLeading);
2814 pDAS = Spoof (dpy, gc, gc, defaultFont, width, height, lineLeading);
2818 fprintf(stderr, "%s: Internal error.\n");
2822 if (helpType == DtHELP_TYPE_TOPIC)
2824 status = printTopicAndChildrenX(helpVolume, locationId, allTopics, pDAS,
2825 dpy, main_window, gc,
2826 dpyX, main_windowX, gcX,
2829 status = printTopicAndChildren(helpVolume, locationId, allTopics, pDAS,
2830 dpy, main_window, gc, pageNumberGC );
2833 pDAS = (_DtHelpDisplayAreaStruct *) SetUp (pDAS, dpy, main_window, gc, defaultFont,
2839 else if (helpType == DtHELP_TYPE_DYNAMIC_STRING)
2844 pDAS = (_DtHelpDisplayAreaStruct *) SetUpDynamicString (pDAS, dpy, gc,
2849 RenderLinesX (dpyX, main_windowX, pDAS, widthX, heightX, &image);
2850 XvpPutImage(dpy, main_window, gcX, image, 0, 0, 0, 0,
2851 (image->width)*3, (image->height*3) );
2852 status = XvpEscape(dpy, NEWFRAME, NULL, NULL, NULL);
2854 else if (status < 0)
2855 fprintf (stdout, "XvpEscape(NEWFRAME) not implemented.\n");
2856 else fprintf(stdout, "XvpEscape(NEWFRAME) not successful.\n");
2858 pDAS = (_DtHelpDisplayAreaStruct *) SetUpDynamicString (pDAS, dpy, gc,
2863 RenderLines (dpy, main_window, pDAS);
2868 fprintf(stderr, "%s Error: Illegal helpType %d.\n",
2875 fprintf (stdout, "Error occurred in XvpEscape(STARTDOC)\n");
2879 status = XvpEscape(dpy, ENDDOC, NULL, NULL, NULL);
2882 fprintf (stdout, "Error occurred in XvpEscape(ENDDOC)\n");
2888 #endif /* #if 0 at function start */