home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / POVHELP.ZIP / source / phe2rtf.c < prev    next >
C/C++ Source or Header  |  1994-09-29  |  24KB  |  918 lines

  1.  
  2.  
  3. /****************************************************************************
  4. *                   PHLP2RTF.C - version 1.0
  5. *
  6. *  This module implements the POV-Help database to Rich Text Format converter
  7. *
  8. *  WARNING      WARNING      WARNING       WARNING      WARNING       WARNING
  9. *
  10. *  THIS PROGRAM IS NOT FINISHED AND THE RTF PRODUCED IS NOT EVEN *MEANT* TO WORK
  11. *  IT IS A ROUGH DRAFT OF A FIRST ATTEMPT AND IS PROVIDED AS IT FORMS A GOOD
  12. *  BASIS FOR PORTING POV-HELP'S OUTPUT TO ANOTHER TEXT FORMAT.
  13. *
  14. *  from Persistence of Vision Raytracer
  15. *  Copyright 1994 Persistence of Vision Team
  16. *  Copyright 1994 Christopher J. Cason.
  17. *---------------------------------------------------------------------------
  18. *  NOTICE: This source code file is provided so that users may experiment
  19. *  with enhancements to POV-Ray and to port the software to platforms other
  20. *  than those supported by the POV-Ray Team.  There are strict rules under
  21. *  which you are permitted to use this file.  The rules are in the file
  22. *  named POVLEGAL.DOC which should be distributed with this file. If
  23. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  24. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  25. *  Forum.  The latest version of POV-Ray may be found there as well.
  26. *
  27. *  POV-Ray files may also be obtained from ftp.uwa.edu.au in pub/povray.
  28. *
  29. *  This program was written in its entirety by Christopher J. Cason.
  30. *  Its use is freely and permanently granted to the POV-Team and POV users
  31. *  under the conditions specified in POVLEGAL.DOC.
  32. *
  33. *  Author : C. J. Cason (cjcason@yarrow.wt.uwa.edu.au, CIS 100032,1644)
  34. *
  35. *****************************************************************************/
  36.  
  37. /*---------------------------------------------------------------------------*/
  38. /* NOTE : If you're porting this to another architecture, don't forget that  */
  39. /*        the POV-Help database stores words and dwords in LSB-first format. */
  40. /*---------------------------------------------------------------------------*/
  41.  
  42. #include <stdio.h>
  43. #include <mem.h>
  44. #include <string.h>
  45. #include <alloc.h>
  46. #include <stdlib.h>
  47. #include <conio.h>
  48. #include <dos.h>
  49. #include <bios.h>
  50. #include <ctype.h>
  51. #include "help.h"
  52.  
  53. typedef unsigned char   uchar ;
  54.  
  55. #define MAX_REF         512
  56. #define MAX_FRAGMENT    16
  57. #define MAX_LINK        64
  58. #define VSIZE_Y         128
  59. #define VSIZE_X         128
  60.  
  61. #define TITLE           0x01
  62. #define COPYRIGHT       0x02
  63. #define AUTHOR          0x03
  64. #define FAQ             0x04
  65. #define CONTENTS        0x100
  66.  
  67. #define PRESERVE        (preserve_formatting || code_fragment || line_drawing)
  68.  
  69. #ifdef max
  70. #undef max
  71. #endif
  72.  
  73. #ifdef min
  74. #undef min
  75. #endif
  76.  
  77. #define max(a,b)        ((int) (a) > (int) (b) ? (a) : (b))
  78. #define min(a,b)        ((int) (a) < (int) (b) ? (a) : (b))
  79.  
  80. #ifndef TRUE
  81. #define TRUE            1
  82. #define FALSE           0
  83. #endif
  84.  
  85. typedef struct
  86. {
  87.   unsigned char         start_vx ;
  88.   unsigned char         end_vx ;
  89.   unsigned short        id ;
  90.   unsigned short        start_vy ;
  91.   unsigned short        end_vy ;
  92. } viewer_reference ;
  93.  
  94. typedef struct
  95. {
  96.   unsigned char         start_vx ;
  97.   unsigned char         end_vx ;
  98.   unsigned short        start_vy ;
  99.   unsigned short        end_vy ;
  100. } viewer_code_fragment ;
  101.  
  102. typedef struct
  103. {
  104.   /* these first three entries must not be changed/moved */
  105.   unsigned long         section ;
  106.   unsigned long         section_length ;
  107.   unsigned char         is_appendix ;
  108.   unsigned char         number [16] ;
  109.   unsigned char         title [80] ;
  110.   unsigned              index ;
  111. } viewer_toc ;
  112.  
  113. uchar                   *title ;
  114. uchar                   *reference_strings ;
  115. uchar                   **reference_string_index ;
  116. unsigned char           reference ;
  117. unsigned char           highlight ;
  118. unsigned char           bold ;
  119. unsigned char           code_fragment ;
  120. unsigned char           heading ;
  121. unsigned char           line_drawing ;
  122. unsigned char           preserve_formatting ;
  123. unsigned char           table ;
  124. unsigned char           list ;
  125. unsigned char           list_entry ;
  126. unsigned char           *toc ;
  127. unsigned char           *section ;
  128. unsigned long           links [MAX_LINK] ;
  129. unsigned long           *reference_index ;
  130. unsigned short          reference_count ;
  131. unsigned short          code_fragment_count ;
  132. unsigned short          TOCsize ;
  133. unsigned short          link_count ;
  134. unsigned short          noFAQ = 1 ;
  135. unsigned short          justifyOn = 1 ;
  136. FILE                    *inF ;
  137. FILE                    *outF ;
  138. viewer_toc              tc ;
  139. viewer_reference        *references ;
  140. viewer_code_fragment    *code_fragments ;
  141. help_file_header        header ;
  142.  
  143. char                    *rtf_header [] =
  144. {
  145. "{\\rtf1\\ansi \\deff0\\deflang1024\n",
  146. "{\\fonttbl\n",
  147. "{\\f0\\froman Times New Roman;}\n",
  148. "{\\f1\\froman Symbol;}\n",
  149. "{\\f2\\fswiss Arial;}\n",
  150. "{\\f3\\froman CG Times (W1);}\n",
  151. "{\\f4\\fswiss Univers (W1);}\n",
  152. "{\\f5\\froman Tms Rmn;}\n",
  153. "{\\f6\\fswiss Helv;}\n",
  154. "{\\f7\\fmodern pica;}\n",
  155. "{\\f8\\fmodern Courier;}\n",
  156. "{\\f9\\fmodern Modern;}\n",
  157. "{\\f10\\froman Roman;}\n",
  158. "{\\f11\\fmodern Courier New;}}\n",
  159. "{\\colortbl;\n",
  160.   "\\red0\\green0\\blue0;\n",
  161.   "\\red0\\green0\\blue255;\n",
  162.   "\\red0\\green255\\blue255;\n",
  163.   "\\red0\\green255\\blue0;\n",
  164.   "\\red255\\green0\\blue255;\n",
  165.   "\\red255\\green0\\blue0;\n",
  166.   "\\red255\\green255\\blue0;\n",
  167.   "\\red255\\green255\\blue255;\n",
  168.   "\\red0\\green0\\blue127;\n",
  169.   "\\red0\\green127\\blue127;\n",
  170.   "\\red0\\green127\\blue0;\n",
  171.   "\\red127\\green0\\blue127;\n",
  172.   "\\red127\\green0\\blue0;\n",
  173.   "\\red127\\green127\\blue0;\n",
  174.   "\\red127\\green127\\blue127;\n",
  175.   "\\red192\\green192\\blue192;\n",
  176. "}\n",
  177. "{\\stylesheet\n",
  178.   "{\\s242\\tqc\\tx4320\\tqr\\tx8640 \\f5\\fs20\\lang1033 \\sbasedon0\\snext242 footer;}\n",
  179.   "{\\s244 \\f5\\fs16\\up6\\lang1033 \\sbasedon0\\snext0 footnote reference;}\n",
  180.   "{\\s245 \\f5\\fs20\\lang1033 \\sbasedon0\\snext245 footnote text;}\n",
  181.   "{\\s252\\li360 \\b\\f5\\lang1033 \\sbasedon0\\snext255 heading 3;}\n",
  182.   "{\\s253\\sb120 \\b\\f6\\lang1033 \\sbasedon0\\snext0 heading 2;}\n",
  183.   "{\\s254\\sb240 \\b\\f6\\ul\\lang1033 \\sbasedon0\\snext0 heading 1;}\n",
  184.   "{\\s255\\li720 \\f5\\fs20\\lang1033 \\sbasedon0\\snext255 Normal Indent;}\n",
  185.   "{\\f5\\fs20\\lang1033 \\snext0 Normal;}\n",
  186.   "{\\info{\\title help.exe Project: help.exe Help}\n",
  187.   "{\\subject help.exe Help Index}\n",
  188.   "{\\author PHE2RTF converter copyright (c) 1994 Christopher J. Cason}\n",
  189.   "{\\doccomm help.exe Main help index.}\n",
  190.   "{\\creatim\\yr1994\\mo7\\dy9}\n",
  191.   "{\\revtim\\yr1994\\mo7\\dy9\\hr0\\min0}\n",
  192.   "{\\version1}\n",
  193.   "{\\edmins0}\n",
  194.   "{\\nofpages0}\n",
  195.   "{\\nofwords0}\n",
  196.   "{\\nofchars0}\n",
  197.   "{\\vern0}\n",
  198. "}}\n",
  199. "\\paperw12240\n",
  200. "\\paperh15840\n",
  201. "\\margl1800\n",
  202. "\\margr1800\n",
  203. "\\margt1440\n",
  204. "\\margb1440\n",
  205. "\\gutter0\n",
  206. "\\ftnbj\n",
  207. "{\\ftnsep \\pard\\plain \\f5\\fs20\\lang1033 \\par }\n",
  208. "\\sectd \\linex576\\endnhere \\pard\\plain \\sl240 \\f5\\fs20\\lang1033\n",
  209. NULL
  210. } ;
  211.  
  212. /* in device_setup, do whatever setup is needed for your output medium */
  213.  
  214. void device_open (void)
  215. {
  216.   char        **s = rtf_header ;
  217.  
  218.   while (*s)
  219.     fprintf (outF, "%s", *s++) ;
  220. }
  221.  
  222. void device_close (void)
  223. {
  224.   fprintf (outF, "}\n") ;
  225. }
  226.  
  227. void process_section (unsigned start)
  228. {
  229.   fprintf (outF, "%s", start ? "{\\f2 \n" : "\\page }\n") ;
  230. }
  231.  
  232. void process_end (void)
  233. {
  234.   fprintf (outF, "}") ;
  235. }
  236.  
  237. void set_paragraph (void)
  238. {
  239.   fprintf (outF, "\\par ") ;
  240. }
  241.  
  242. void set_indent (void)
  243. {
  244. /*  fprintf (outF, "\\li60 ") ; */
  245. }
  246.  
  247. void set_highlight (unsigned state)
  248. {
  249.   fprintf (outF, "\\%s ", state ? "ul" : "ul0") ;
  250. }
  251.  
  252. void set_bold (unsigned state)
  253. {
  254.   fprintf (outF, "\\%s ", state ? "b" : "b0") ;
  255. }
  256.  
  257. void set_code_fragment (unsigned state)
  258. {
  259.   fprintf (outF, "%s", state ? "{\\keep\\f11 " : "}") ;
  260. }
  261.  
  262. void set_heading (unsigned state)
  263. {
  264.   fprintf (outF, "%s", state ? "{\\qc " : "}") ;
  265. }
  266.  
  267. void set_line_drawing (unsigned state)
  268. {
  269.   fprintf (outF, "%s", state ? "{\\keep\\f11 " : "}") ;
  270. }
  271.  
  272. void set_preserve (unsigned state)
  273. {
  274.   fprintf (outF, "%s", state ? "{\\keep\\f11 " : "}") ;
  275. }
  276.  
  277. void set_table (unsigned state)
  278. {
  279.   set_preserve (state) ;
  280. }
  281.  
  282. void set_reference (unsigned state, viewer_reference *r)
  283. {
  284.   fprintf (outF, "\\%s ", state ? "ul" : "ul0") ;
  285. }
  286.  
  287. void set_list (unsigned state, unsigned count)
  288. {
  289. }
  290.  
  291. void set_list_entry (unsigned state, unsigned count)
  292. {
  293. }
  294.  
  295. void vputchar (char ch)
  296. {
  297.   if ((unsigned char) ch < 0x80 && strchr ("\\{}", ch) == NULL)
  298.     fprintf (outF, "%c", ch) ;
  299.   else
  300.     fprintf (outF, "\\'%02x", ch) ;
  301. }
  302.  
  303. void vputstr (char *s)
  304. {
  305.   while (*s)
  306.     vputchar (*s++) ;
  307. }
  308.  
  309. unsigned pointcount (char *s)
  310. {
  311.   unsigned    count = 0 ;
  312.  
  313.   while (*s)
  314.     if (*s++ == '.')
  315.       count++ ;
  316.   return (count) ;
  317. }
  318.  
  319. unsigned ustrcmp (char *s1, char *s2)
  320. {
  321.   while (*s1 && *s2)
  322.     if (toupper (*s1++) != toupper (*s2++))
  323.       return (1) ;
  324.   return (*s1 || *s2) ;
  325. }
  326.  
  327. viewer_reference *create_reference (unsigned short id)
  328. {
  329.   if (reference_count == MAX_REF) return (NULL) ;
  330.   references [reference_count].id = id ;
  331.   return (references + reference_count++) ;
  332. }
  333.  
  334. void clear_references (void)
  335. {
  336.   reference_count = 0 ;
  337. }
  338.  
  339. viewer_code_fragment *create_code_fragment (void)
  340. {
  341.   if (code_fragment_count == MAX_FRAGMENT) return (NULL) ;
  342.   return (code_fragments + code_fragment_count++) ;
  343. }
  344.  
  345. void clear_code_fragments (void)
  346. {
  347.   code_fragment_count = 0 ;
  348. }
  349.  
  350. viewer_toc *getTC (unsigned index)
  351. {
  352.   uchar                 *s ;
  353.   static viewer_toc     result ;
  354.  
  355.   if (index >= header.section_count + header.appendix_count) index = 0 ;
  356.   s = toc + (unsigned) ((unsigned long) TOCsize * index) ;
  357.   memcpy (&result, s, sizeof (TOC_entry)) ;
  358.   s += sizeof (TOC_entry) ;
  359.   strcpy (result.number, s) ;
  360.   strcpy (result.title, s + header.sec_number_len) ;
  361.   result.index = index ;
  362.   return (&result) ;
  363. }
  364.  
  365. viewer_toc *findTCfromOffset (unsigned long offset)
  366. {
  367.   unsigned              i ;
  368.   static viewer_toc     result ;
  369.  
  370.   for (i = 0 ; i < header.section_count + header.appendix_count ; i++)
  371.   {
  372.     result = *getTC (i) ;
  373.     if (result.section > offset) continue ;
  374.     if (result.section + result.section_length <= offset) continue ;
  375.     return (&result) ;
  376.   }
  377.   return (NULL) ;
  378. }
  379.  
  380. char *get_section (viewer_toc *tc, unsigned number)
  381. {
  382.   uchar       *section ;
  383.   unsigned    count ;
  384.  
  385.   *tc = *getTC (number) ;
  386.   fseek (inF, tc->section, SEEK_SET) ;
  387.   if (tc->section_length + 1 > 65534U)
  388.   {
  389.     printf ("section too big for present allocation code") ;
  390.     return (NULL) ;
  391.   }
  392.   if ((section = calloc ((unsigned) tc->section_length + 1, 1)) == NULL)
  393.   {
  394.     printf ("error - cannot allocate enough memory for section %s", tc->number) ;
  395.     return (NULL) ;
  396.   }
  397.   if (fread (section, (unsigned) tc->section_length + 1, 1, inF) == 0)
  398.   {
  399.     printf ("could not read section") ;
  400.     return (NULL) ;
  401.   }
  402.   count = (unsigned) tc->section_length ;
  403.   while (section [count - 1] == '\n' || section [count - 1] == PARAGRAPH) count-- ;
  404.   section [count] = '\0' ;
  405.   return (section) ;
  406. }
  407.  
  408. unsigned findSection (char *s)
  409. {
  410.   unsigned              i ;
  411.   viewer_toc            result ;
  412.  
  413.   for (i = 0 ; i < header.section_count + header.appendix_count ; i++)
  414.   {
  415.     result = *getTC (i) ;
  416.     if (ustrcmp (s, result.number)) continue ;
  417.     return (i) ;
  418.   }
  419.   return (-1) ;
  420. }
  421.  
  422. unsigned findTitle (char *s)
  423. {
  424.   static char           str [80] ;
  425.   unsigned              i ;
  426.   viewer_toc            result ;
  427.  
  428.   strupr (s) ;
  429.   for (i = 0 ; i < header.section_count + header.appendix_count ; i++)
  430.   {
  431.     result = *getTC (i) ;
  432.     if (ustrcmp (s, result.title)) continue ;
  433.     return (i) ;
  434.   }
  435.   for (i = 0 ; i < header.section_count + header.appendix_count ; i++)
  436.   {
  437.     result = *getTC (i) ;
  438.     strcpy (str, result.title) ;
  439.     strupr (str) ;
  440.     if (strstr (str, s) == NULL) continue ;
  441.     return (i) ;
  442.   }
  443.   return (-1) ;
  444. }
  445.  
  446. void format_section (viewer_toc *tc, unsigned char *section)
  447. {
  448.   unsigned              id ;
  449.   unsigned              escape = 0 ;
  450.   unsigned char         *s ;
  451.   viewer_reference      *r ;
  452.  
  453.   clear_references () ;
  454.   clear_code_fragments () ;
  455.   process_section (TRUE) ;
  456.   if (tc)
  457.   {
  458.     set_heading (TRUE) ;
  459.     if (tc->is_appendix) vputstr ("APPENDIX ") ;
  460.     vputstr (tc->number) ;
  461.     vputstr ("\t") ;
  462.     vputstr (tc->title) ;
  463.     set_heading (FALSE) ;
  464.   }
  465.  
  466.   while (*section == '\n' || *section == PARAGRAPH) section++ ;
  467.  
  468.   for (s = section ; *s ; s++)
  469.   {
  470.     if (escape == 0)
  471.     {
  472.       switch (*s)
  473.       {
  474.         case ESCAPE :
  475.              escape++ ;
  476.              break ;
  477.  
  478.         case PARAGRAPH :
  479.              set_paragraph () ;
  480.              break ;
  481.  
  482.         case INDENT :
  483.              set_indent () ;
  484.              break ;
  485.  
  486.         case REFERENCE :
  487.              id = *++s ;
  488.              id += (unsigned) *++s * 256 ;
  489.              r = create_reference (id) ;
  490.              break ;
  491.  
  492.         case TARGET :
  493.              break ;
  494.  
  495.         case REFERENCE_ON :
  496.              if (r == NULL) break ;
  497.              set_reference (TRUE, r) ;
  498.              break ;
  499.  
  500.         case REFERENCE_OFF :
  501.              if (r == NULL) break ;
  502.              set_reference (FALSE, r) ;
  503.              r = NULL ;
  504.              break ;
  505.  
  506.         case HIGHLIGHT_ON :
  507.         case HIGHLIGHT_OFF :
  508.              set_highlight (*s == HIGHLIGHT_ON) ;
  509.              break ;
  510.  
  511.         case BOLD_ON :
  512.         case BOLD_OFF :
  513.              set_bold (*s == BOLD_ON) ;
  514.              break ;
  515.  
  516.         case CODE_ON :
  517.              code_fragment++ ;
  518.              set_code_fragment (TRUE) ;
  519.              break ;
  520.  
  521.         case CODE_OFF :
  522.              code_fragment = 0 ;
  523.              set_code_fragment (FALSE) ;
  524.              break ;
  525.  
  526.         case HEADING_ON :
  527.         case HEADING_OFF :
  528.              set_heading (*s == HEADING_ON) ;
  529.              break ;
  530.  
  531.         case LINE_ON :
  532.         case LINE_OFF :
  533.              set_line_drawing (*s == LINE_ON) ;
  534.              break ;
  535.  
  536.         case PRESERVE_ON :
  537.         case PRESERVE_OFF :
  538.              set_preserve (*s == PRESERVE_ON) ;
  539.              break ;
  540.  
  541.         case TABLE_ON :
  542.         case TABLE_OFF :
  543.              set_table (*s == TABLE_ON) ;
  544.              break ;
  545.  
  546.         case LIST_ON :
  547.              if ((list = *++s) == 1) list++ ;
  548.              set_list (TRUE, list) ;
  549.              break ;
  550.  
  551.         case LIST_OFF :
  552.              set_list (FALSE, list) ;
  553.              break ;
  554.  
  555.         case LIST_ENTRY_ON :
  556.              list_entry++ ;
  557.              set_list_entry (TRUE, list) ;
  558.              break ;
  559.  
  560.         case LIST_ENTRY_OFF :
  561.              list_entry = 0 ;
  562.              while (*s == ' ') s++ ;
  563.              set_list_entry (FALSE, list) ;
  564.              break ;
  565.  
  566.         default :
  567.              vputchar (*s) ;
  568.              break ;
  569.       }
  570.     }
  571.     else
  572.     {
  573.       vputchar (*s) ;
  574.       escape = 0 ;
  575.     }
  576.   }
  577.   if (reference)
  578.   {
  579.     reference_count-- ;
  580.     reference = 0 ;
  581.   }
  582.   process_section (FALSE) ;
  583. }
  584.  
  585. void format_authors (char *s)
  586. {
  587.   clear_references () ;
  588.   vputstr ("AUTHORS\r\n") ;
  589.   vputstr (s) ;
  590. }
  591.  
  592. void load_links (void)
  593. {
  594.   unsigned    child_count ;
  595.  
  596.   link_count = 0 ;
  597.   fseek (inF, reference_index [references [0].id], SEEK_SET) ;
  598.   fread (&child_count, 2, 1, inF) ;
  599.   if (child_count >= MAX_LINK - 1) child_count = MAX_LINK - 1 ;
  600.   fread (links, 4, link_count = child_count + 1, inF) ;
  601. }
  602.  
  603. void display_text (unsigned what)
  604. {
  605.   char                  *text ;
  606.   char                  *s ;
  607.   unsigned              i ;
  608.   unsigned long         offset ;
  609.   unsigned long         length ;
  610.  
  611.   process_section (TRUE) ;
  612.   switch (what)
  613.   {
  614.     case COPYRIGHT :
  615.          offset = header.copyright ;
  616.          length = header.copyright_length ;
  617.          break ;
  618.  
  619.     case AUTHOR :
  620.          offset = header.authors ;
  621.          length = header.author_length ;
  622.          break ;
  623.  
  624.     default :
  625.          return ;
  626.   }
  627.  
  628.   if (length > 65534U)
  629.   {
  630.     printf ("section too big for present allocation code\r\n") ;
  631.     return ;
  632.   }
  633.   if ((text = calloc ((unsigned) length + 1, 1)) == NULL)
  634.   {
  635.     printf ("cannot allocate memory for text\r\n") ;
  636.     return ;
  637.   }
  638.   fseek (inF, offset, SEEK_SET) ;
  639.   if (fread (text, (unsigned) length + 1, 1, inF) == 0)
  640.   {
  641.     printf ("could not read text\r\n") ;
  642.     free (text) ;
  643.     return ;
  644.   }
  645.   text [(unsigned) length] = 0 ;
  646.  
  647.   for (s = text, i = (unsigned) length ; i ; i--, s++)
  648.     if (*s == '\0')
  649.       *s = '\n' ;
  650.  
  651.   if (what == AUTHOR)
  652.     format_authors (text) ;
  653.   else
  654.     format_section (NULL, text) ;
  655.  
  656.   free (text) ;
  657.   process_section (FALSE) ;
  658. }
  659.  
  660. void display_contents (void)
  661. {
  662.   unsigned              i ;
  663.   unsigned              offset ;
  664.   viewer_toc            tc ;
  665.  
  666.   clear_references () ;
  667.   process_section (TRUE) ;
  668.  
  669.   vputstr (title) ;
  670.  
  671.   for (i = 0 ; i < header.section_count + header.appendix_count ; i++)
  672.   {
  673.     if (i == header.section_count)
  674.     {
  675.       vputstr ("*** APPENDICES ***") ;
  676.     }
  677.     tc = *getTC (i) ;
  678.     if (noFAQ && strstr (tc.title, "FREQUENTLY ASKED QUESTIONS") != NULL) break ;
  679.     offset = pointcount (tc.number) * 3 ;
  680.     vputstr (tc.number) ;
  681.     vputstr ("\t") ;
  682.     vputstr (tc.title) ;
  683.   }
  684.   process_section (FALSE) ;
  685. }
  686.  
  687. unsigned load_strings (void)
  688. {
  689.   char        *s ;
  690.   char        str [81] ;
  691.   unsigned    i ;
  692.   unsigned    count ;
  693.  
  694.   if ((reference_strings = farcalloc ((unsigned) header.reference_string_length, 1)) == NULL) return (1) ;
  695.   if ((reference_string_index = farcalloc (header.reference_count * 4, 1)) == NULL) return (1) ;
  696.   s = reference_strings ;
  697.   for (i = 0 ; i < header.reference_count ; i++)
  698.   {
  699.     fseek (inF, reference_index [i], SEEK_SET) ;
  700.     fread (&count, 2, 1, inF) ;
  701.     fseek (inF, (count + 1) * 4, SEEK_CUR) ;
  702.     if (fgets (str, 80, inF) == NULL) break ;
  703.     strcpy (s, str) ;
  704.     reference_string_index [i] = s ;
  705.     s += strlen (str) + 1 ;
  706.   }
  707.   return (0) ;
  708. }
  709.  
  710. void init (void)
  711. {
  712.   if ((references = calloc (sizeof (viewer_reference), MAX_REF)) == NULL)
  713.   {
  714.     printf ("cannot allocate memory for references\r\n") ;
  715.     exit (1) ;
  716.   }
  717.   if ((code_fragments = calloc (sizeof (viewer_code_fragment), MAX_FRAGMENT)) == NULL)
  718.   {
  719.     printf ("cannot allocate memory for code fragments\r\n") ;
  720.     exit (1) ;
  721.   }
  722.   if ((toc = malloc ((unsigned) header.table_of_contents_length)) == NULL)
  723.   {
  724.     printf ("cannot allocate memory for table of contents\r\n") ;
  725.     exit (1) ;
  726.   }
  727.   TOCsize = sizeof (TOC_entry) + header.sec_number_len + header.sec_title_len ;
  728.   if ((reference_index = malloc ((unsigned) header.reference_index_length)) == NULL)
  729.   {
  730.     printf ("cannot allocate memory for reference index\r\n") ;
  731.     exit (1) ;
  732.   }
  733.   fseek (inF, header.reference_index, SEEK_SET) ;
  734.   if (fread (reference_index, (unsigned) header.reference_index_length, 1, inF) == 0)
  735.   {
  736.     printf ("could not read reference index\r\n") ;
  737.     exit (1) ;
  738.   }
  739.   if ((title = calloc ((unsigned) header.title_length + 1, 1)) == NULL)
  740.   {
  741.     printf ("cannot allocate memory for title\r\n") ;
  742.     exit (1) ;
  743.   }
  744.   fseek (inF, header.title, SEEK_SET) ;
  745.   if (fread (title, (unsigned) header.title_length + 1, 1, inF) == 0)
  746.   {
  747.     printf ("could not read title\r\n") ;
  748.     exit (1) ;
  749.   }
  750.   title [(unsigned) header.title_length] = 0 ;
  751.   if (load_strings ())
  752.   {
  753.     printf ("could not load reference strings\r\n") ;
  754.     exit (1) ;
  755.   }
  756. }
  757.  
  758. unsigned main (unsigned argc, char *argv [])
  759. {
  760.   int                   number = -1 ;
  761.   int                   count = -1 ;
  762.   char                  *s1 = "HELP.PHE" ;
  763.   char                  *s2 = "" ;
  764.   char                  gotoSection [16] = "1.0" ;
  765.   char                  gotoTitle [80] = "" ;
  766.  
  767.   while (++argv, --argc)
  768.   {
  769.     if (**argv == '-' || **argv == '+')
  770.     {
  771.       switch (toupper ((*argv) [1]))
  772.       {
  773.         case 'I' :
  774.              s1 = *argv + 2 ;
  775.              break ;
  776.  
  777.         case 'O' :
  778.              s2 = *argv + 2 ;
  779.              break ;
  780.  
  781.         case 'F' :
  782.              noFAQ = 0 ;
  783.              break ;
  784.  
  785.         case 'N' :
  786.              number = atoi (*argv + 2) ;
  787.              if (count == -1) count = 0 ;
  788.              break ;
  789.  
  790.         case 'S' :
  791.              strncpy (gotoSection, *argv + 2, 15) ;
  792.              if (count == -1) count = 0 ;
  793.              break ;
  794.  
  795.         case 'T' :
  796.              strncpy (gotoTitle, *argv + 2, 79) ;
  797.              if (count == -1) count = 0 ;
  798.              break ;
  799.  
  800.         case 'C' :
  801.              count = atoi (*argv + 2) ;
  802.              break ;
  803.  
  804.         case 'J' :
  805.              justifyOn = (*argv) [2] != '-' ;
  806.              break ;
  807.  
  808.         case '?' :
  809.         case 'H' :
  810.              printf ("\r\nPHE2RTF : POV-Help to Rich Text Format\r\n\n") ;
  811.              printf ("-i    : set input file name (default HELP.PHE)\r\n") ;
  812.              printf ("-o    : set output file name (default stdout)\r\n") ;
  813.              printf ("-j[-] : justify ON (default), -j- to turn off\r\n") ;
  814.              printf ("-f    : include FAQ section (if present) in output (default omit)\r\n") ;
  815.              printf ("-sX.Y : start from section X.Y (default 1.0)\r\n") ;
  816.              printf ("-tABC : start from section with title ABC\r\n") ;
  817.              printf ("-nn   : start from the nth section (first = 0)\r\n") ;
  818.              printf ("-cn   : process 'n' sections (default all unless -s, -t or -n, where 'n' = 1)\r\n") ;
  819.              printf ("\r\n") ;
  820.              return (0) ;
  821.  
  822.         default :
  823.              printf ("unknown option '%s'\r\n", *argv) ;
  824.              return (1) ;
  825.       }
  826.     }
  827.   }
  828.  
  829.   if ((inF = fopen (s1, "rb")) == NULL)
  830.   {
  831.     printf ("could not open input file '%s'\r\n", s1) ;
  832.     printf ("use phe2rtf -h for help\r\n") ;
  833.     return (1) ;
  834.   }
  835.   if (*s2)
  836.   {
  837.     if ((outF = fopen (s2, "wt")) == NULL)
  838.     {
  839.       printf ("could not open output file '%s'\r\n", s2) ;
  840.       printf ("use phe2rtf -h for help\r\n") ;
  841.       return (1) ;
  842.     }
  843.   }
  844.   else
  845.     outF = stdout ;
  846.   if (fread (&header, sizeof (help_file_header), 1, inF) == 0)
  847.   {
  848.     printf ("could not read header\r\n") ;
  849.     return (1) ;
  850.   }
  851.  
  852.   if (memcmp (header.signature, "POV-Help", 8) != 0)
  853.   {
  854.     printf ("header ID failed consistency check\r\n") ;
  855.     return (1) ;
  856.   }
  857.  
  858.   if (header.reader_version > VERSION)
  859.   {
  860.     printf ("version error ! database is not compatible [needs version %d.%d of reader]\r\n",
  861.              header.reader_version / 100, header.reader_version % 100) ;
  862.     return (1) ;
  863.   }
  864.  
  865.   init () ;
  866.  
  867.   fseek (inF, header.table_of_contents, SEEK_SET) ;
  868.   if (fread (toc, (unsigned) header.table_of_contents_length, 1, inF) == 0)
  869.   {
  870.     printf ("could not read table of contents\r\n") ;
  871.     return (1) ;
  872.   }
  873.  
  874.   device_open () ;
  875.  
  876.   if (*gotoTitle) number = findTitle (gotoTitle) ;
  877.   if (*gotoSection) number = findSection (gotoSection) ;
  878.  
  879.   if (number == -1)
  880.   {
  881.     number = 0 ;
  882.     count = header.appendix_count + header.section_count ;
  883.   }
  884.   else
  885.     if (count == 0)
  886.       count = 1 ;
  887.  
  888.   if (count == -1)
  889.     count = header.appendix_count + header.section_count - number ;
  890.  
  891.   if (number + count > header.appendix_count + header.section_count)
  892.     count = header.appendix_count + header.section_count - number ;
  893.  
  894. /*display_contents () ;*/
  895.  
  896.   while (count--)
  897.   {
  898.     section = get_section (&tc, number++) ;
  899.     if (noFAQ && strstr (tc.title, "FREQUENTLY ASKED QUESTIONS") != NULL) break ;
  900.     format_section (&tc, section) ;
  901.     free (section) ;
  902.   }
  903.  
  904. /*clear_references () ;*/
  905. /*display_text (AUTHOR) ;*/
  906.  
  907.   device_close () ;
  908.  
  909.   farfree (reference_string_index) ;
  910.   farfree (reference_strings) ;
  911.   free (toc) ;
  912.   free (code_fragments) ;
  913.   free (references) ;
  914.   free (title) ;
  915.   fclose (inF) ;
  916.   return (0) ;
  917. }
  918.