home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1997 January / macformat46.iso / Shareware Plus / Developers / EnterAct / EnterAct Stuff / Converting text to HTML / move to hAWK programs / $TextToHTML
Encoding:
Text File  |  1996-08-31  |  20.5 KB  |  673 lines

  1. # This program generates a set of HTML documents corresponding to a text document
  2. # (one for each chapter and a table of contents, as explained below).
  3.  
  4. # If your document contains illustrations, you must have created the document with
  5. # EnterAct 3.7 or later (which places all PICTs in the resource fork and numbers
  6. # them 1000, 1001, 1002...1400). More exactly, if you have an old EnterAct document
  7. # you must insert or delete at least one picture using EnterAct 3.7 or later, in
  8. # order to force renumbering of the pictures. If you're not sure, use a resource
  9. # editor to check the numbering of the PICTs in the doc's resource fork.
  10.  
  11. # An overview of the whole process, using "EnterAct 3 Manual" as an example:
  12. # • get a copy of "clip2gif" by Yves Piguet (check your CD's, or Anarchie to Info-Mac)
  13. # • structure your document ("EnterAct 3 Manual"), using EnterAct if you have PICT illustrations
  14. #        (more on this important step below)
  15. # • create a folder to hold the html version of your document, and within it
  16. #     create a folder to hold the gifs ("Disk:...:E3M_HTML:Graphics:")
  17. # • run the script "PICT rsrcs to numbered gifs" from within EnterAct: in the
  18. #     first dialog, select the document to convert ("EnterAct 3 Manual"); in the second
  19. #     dialog, select the folder to hold the gifs ("Graphics"). NOTE to avoid being pestered
  20. #     about where "clip2gif" is, you should open the script using Apple's "Script Editor" first,
  21. #     and then after you have relocated "clip2gif" (you will be asked to do so by Script Editor)
  22. #     do a Save.
  23. # • when "PICT rsrcs to numbered gifs" is done, it presents you with a command
  24. #     line to run this program: select it and hit <enter> to run it. You should also
  25. #    save the command line(s) away somewhere for future reference. It looks like this:
  26. #        hAWK -f$TextToHTML -vgifList="Disk:CW CEDAR:E3M_HTML:Graphics:Unsorted gif list"
  27. #            -- "Disk:CW CEDAR:EnterAct Stuff:Documentation:EnterAct 3 Manual"
  28. #    (it will be stored in the file "$tempScriptResult" until you run your next script with EnterAct)
  29. # • when this program is done, there will be a "Contents.html" file at the top
  30. #     of the folder that holds the html version of your document, and also
  31. #     within it will be a "Text" folder holding the chapter documents, and
  32. #     your folder for the gifs will be chock full of gifs.
  33. # • drag the "Contents.html" file onto your favourite browser and verify that
  34. #     things came out the way you wanted.
  35.  
  36. # If your document contains no illustrations then you don't need to run the
  37. # "PICT rsrcs to numbered gifs" script first. But you still need to construct
  38. # a command line to run this program. First create a folder to hold the results
  39. # (eg "Disk:...:MyDoc HTML:"). Remember the full path names for this folder and for
  40. # your source document ("MyDoc"). Your command line should then look like this:
  41. # hAWK -f$TextToHTML -vgifList="Disk:...:MyDoc HTML:Graphics:Unsorted gif list"
  42. # -- "Disk:...:MyDoc"
  43. # Note that neither the "Graphics" folder nor the file "Unsorted gif list" will
  44. # exist, but you still need to include them in the command line argument. This
  45. # is a minor nuisance, but if you ever decide to include illustrations in your
  46. # document then all you have to do is create the actual "Graphics" folder within
  47. # the "MyDoc HTML" folder, run the script "PICT rsrcs to numbered gifs", and
  48. # then run the exact same command line that you produced above (or run the
  49. # command line that the script produces, which will be exactly the same).
  50.  
  51.  
  52. # The only tricky bit here is structuring your document so that this program can
  53. # convert the structure into proper html formatting. Characters in your text have to
  54. # clearly signal where headings are, where lists start, and so on. This program is
  55. # set up to handle a specific fixed structure, and if your document doesn't follow
  56. # this structure you'll have to change either your document or this program,
  57. # whichever seems easier.
  58.  
  59. # The "EnterAct 3 Manual" is an example of a document structured for use with
  60. # this program, browse through it as you read the rules below.
  61.  
  62. # Here are the structuring rules that this program expects:
  63. # • First line: presumed to be the title, skip it (the title is instead taken from
  64. #     the name of the document)
  65. # • Each chapter title should be between "dash-space" lines - - - - -,
  66. #     that is one dash-space line before the chapter title, and another
  67. #     dash-space line immediately after. The "dash space" line should begin
  68. #     with a dash '-', and the line should contain only dashes and spaces in
  69. #     any mix you like after the starting dash, at least one additional character
  70. #     after the starting dash.
  71. # • If you have a table of contents in your document, it should be preceded with
  72. #     the chapter title "CONTENTS" (between dash-space lines). The entire table
  73. #     of contents will be skipped, and regenerated by this program. Note your
  74. #     table of contents should be followed by a chapter title, since everything
  75. #     from the "CONTENTS" chapter title to the next chapter title will be skipped.
  76. # • Within each chapter, major subheadings that should be included in the main
  77. #     table of contents should be formatted "§\tSub section name". Subheadings
  78. #     that should NOT be shown in the main table of contents but SHOULD be shown
  79. #     in the table of contents for the chapter itself should be formatted
  80. #     "(§)\tSub section name".
  81. # • Subheadings that should not be shown in any table of contents should take
  82. #     the form ">\tSub section name".
  83. # • Any illustrations (PICT) must have been inserted using EnterAct, and you must
  84. #     have inserted or deleted at least one PICT using v3.7 or later of EnterAct.
  85. # • Major lists begin with "\t•". Sublists begin with "\t\t•". There should be no
  86. #     blank lines within a list, since a blank line signals the end of the list
  87. #     (including any sublists).
  88. # • Chunks of text that are to be quoted as-is with no reformatting should be
  89. #     between lines that consist of exactly four underscores "____".
  90.  
  91. # If you wish to modify the structure that this program uses, you'll need to change
  92. # the function "DoTheLines()" below. Note that structuring information is expected
  93. # to come BEFORE the text to be formatted (in chapter title the dash-space line comes
  94. # before and after the title, but the one after the title is just for the sake of
  95. # appearance in the non-html version). If you want any structuring information to
  96. # come AFTER the text (such as indicating a chapter title by just a dash-space line
  97. # following the title, no dash-space line before it) then you will have to buffer
  98. # the lines as they are read in from your document, since you won't know that
  99. # formatting is required until you've looked at the line after the one that needs
  100. # to be formatted.
  101. # For some help handling this, see
  102. # «hAWK User’s Manual» «R  2   Beyond input records»
  103. # especially the part a couple of pages in, about "End–buffered input".
  104.  
  105. # TOC and anchor handling:
  106. # Given "Name of Heading" and heading level H2 or H3:
  107. # 1 replace with <Hn><A NAME = "Name of Heading" >Name of Heading</A></Hn>
  108. # 2 if H2 head, increment h2Counter
  109. # 3 accumulate headings in TOC[h2Counter], with SUBSEP in between
  110. # 4 at end split each array entry, output URLs in unordered lists for TOC.
  111.  
  112. BEGIN {
  113.     InitSpecialCharacters();
  114.     # Remember full name of main document.
  115.     inputFile = ARGV[1];
  116.     # Get title and main head from name of document.
  117.     n = split(inputFile, names, ":");
  118.     theMainTitle = names[n];
  119.     theMainHead = names[n];
  120.     
  121.     contentsMarker = "TOC GOES HERE";
  122.     
  123.     inList = 0;
  124.     listElement = 0;
  125.     h2Counter = 0;
  126.     newParagraphComing = 1;
  127.     
  128.     currentGIF = 0;
  129.     numGIFs = 0;
  130.     doingGIF = 0;
  131.     doingAsIs = 0;
  132.     
  133.     # "gifList", full path to Unsorted gif list, should be preset
  134.     # in dialog or on the command line.
  135.     gifArrayFile = gifList;
  136.     
  137.     gifPartialLocation = "../Graphics/"; ##see just below
  138.     outFile = ""
  139.     contentsFileName = "Contents.html";
  140.     
  141.     n = split(gifArrayFile, names, ":");
  142.     for (i = 1; i < n - 1; ++i)
  143.         {
  144.         chaptersFolder = chaptersFolder names[i] ":";
  145.         }
  146.     
  147.     
  148.     graphicsFolderName = names[i];
  149.     gifPartialLocation = "../" graphicsFolderName "/"; # eg "../Graphics/"
  150.     
  151.     contentsFileLocation = chaptersFolder;
  152.     chaptersFolder = chaptersFolder "Text:";
  153.     ## eg chaptersFolder = STDPATH "E3M_HTML:Text:"
  154.     
  155.     MakeFolder(chaptersFolder);
  156.     
  157.     LoadGIFNames();
  158.     
  159.     # The main event: inhale all the lines, write the chapters, write main contents.
  160.     DoTheLines();
  161.     WriteMainContentsFile();
  162.     
  163.     # Notify we're done.
  164.     print "HTML conversion of", theMainTitle, "complete.";
  165.     }
  166.  
  167. function InitSpecialCharacters()
  168.     {
  169.     ampersand = "\\&";
  170.     lessThan = "\\<";
  171.     greaterThan = "\\>";
  172.     quote = "\\"";
  173.     euroLeft = "\\«";
  174.     euroRight = "\\»";
  175.     bullet = "\\·";
  176.     dornk = "\\¬";
  177.     section = "\\§";
  178.     para = "\\¶";
  179.     cedillaC = "\\ç";
  180.     shy = "\\­";
  181.     copyright = "\\©";
  182.     registration = "\\®";
  183.     question = "\\?";
  184.     }
  185.  
  186. # do for all input lines
  187. function DoTheLines()
  188.     {
  189.     getline < inputFile; # skip the first line
  190.     while ((getline < inputFile) > 0)
  191.         {
  192.         # Stop skipping blank lines if we were doing a GIF and hit nonblank
  193.         if ($0 != "")
  194.             doingGIF = 0;
  195.         
  196.         # "As is" sections shouldn't contain any other "structure"
  197.         if ($0 ~ /^[ \t]*____[ \t]*$/)
  198.             {
  199.             doneFirstPRELine = 0;
  200.             while ((getline < inputFile) > 0)
  201.                 {
  202.                 if ($0 ~ /^[ \t]*____[ \t]*$/)
  203.                     {
  204.                     if (doneFirstPRELine == 1)
  205.                         PrintToOutFile("</PRE>");
  206.                     break;
  207.                     }
  208.                 else
  209.                     {
  210.                     ReplaceSpecialCharacters();
  211.                     if (doneFirstPRELine == 1)
  212.                         PrintToOutFile($0);
  213.                     else
  214.                         {
  215.                         PrintToOutFile("<PRE>" $0);
  216.                         doneFirstPRELine = 1;
  217.                         }
  218.                     }
  219.                 }
  220.             }
  221.         # Remember if list element starting (one or two tabs, bullet)
  222.         else if ($0 ~ /^[\t]+•/)
  223.             {
  224.             if ($0 ~ /^\t•/)
  225.                 {
  226.                 # We may be starting a brand new list
  227.                 if (inList == 0)
  228.                     {
  229.                     PrintToOutFile("<UL>");
  230.                     inList = 1;
  231.                     }
  232.                 else
  233.                     {
  234.                     # A new list element ends any subelement
  235.                     if (subListElement == 1)
  236.                         {
  237.                         PrintToOutFile("\t</UL>");
  238.                         subListElement = 0;
  239.                         }
  240.                     }
  241.                 listElement = 1;
  242.                 # Print the first line of the new list element
  243.                 sub(/^[\t]+•[ \t]*/, "");
  244.                 ReplaceSpecialCharacters();
  245.                 PrintToOutFile("<LI>" $0);
  246.                 }
  247.             else if ($0 ~ /^\t\t•/)
  248.                 {
  249.                 # First subelement, start a new list
  250.                 if (subListElement == 0)
  251.                     {
  252.                     PrintToOutFile("\t<UL>");
  253.                     }
  254.                 subListElement = 1;
  255.                 # Print the first line of the new list subelement
  256.                 sub(/^[\t]+•[ \t]*/, "");
  257.                 ReplaceSpecialCharacters();
  258.                 PrintToOutFile("\t<LI>" $0);
  259.                 }
  260.             }
  261.         # A list finishes with a blank line (also signals new paragraph)
  262.         else if ($0 == "")
  263.             {
  264.             if (inList)
  265.                 {
  266.                 if (subListElement == 1)
  267.                     PrintToOutFile("\t</UL>");
  268.                 if (listElement == 1)
  269.                     PrintToOutFile("</UL>");
  270.                 inList = 0;
  271.                 listElement = 0;
  272.                 subListElement = 0;
  273.                 }
  274.             # Print blank lines, unless we're skipping GIF space
  275.             if (doingGIF == 0)
  276.                 PrintToOutFile("");
  277.             newParagraphComing = 1;
  278.             }
  279.         # Top level heading H2, between dashed lines
  280.         # This heading starts a new file
  281.         else if ($0 ~ /^-[ \t-]+$/)
  282.             {
  283.             getline < inputFile;
  284.             # Skip the "CONTENTS" section
  285.             SkipUnwantedSections();
  286.             # having trouble with quotes in chapter titles
  287.             SimplifyQuotes();
  288.             ReplaceSpecialCharacters();
  289.             # make sure we can use text as a file name
  290.             gsub(/\t/, " ");
  291.             gsub(/:/, " ");
  292.             StartNewChapter($0);
  293.             TOC[++h2Counter] = $0 SUBSEP;
  294.             getline < inputFile;
  295.             }
  296.         # Second level heading, shown in main contents
  297.         else if ($0 ~ /^§\t/)
  298.             {
  299.             tempLine = substr($0, 3);
  300.             $0 = tempLine;
  301.             ReplaceSpecialCharacters();
  302.             TOC[h2Counter] = TOC[h2Counter] $0 SUBSEP;
  303.             PrintHeading($0, "H3");
  304.             }
  305.         # Second level heading, NOT shown in main contents
  306.         # -- name is preceded with "!" in TOC array to signal that.
  307.         else if ($0 ~ /^\(§\)\t/)
  308.             {
  309.             tempLine = substr($0, 5);
  310.             $0 = tempLine;
  311.             ReplaceSpecialCharacters();
  312.             TOC[h2Counter] = TOC[h2Counter] "!" $0 SUBSEP;
  313.             PrintHeading($0, "H3");
  314.             }
  315.         # Third level heading, not in any contents (although it does have an anchor)
  316.         else if ($0 ~ /^>\t/)
  317.             {
  318.             tempLine = substr($0, 3);
  319.             $0 = tempLine;
  320.             ReplaceSpecialCharacters();
  321.             PrintHeading($0, "H4");
  322.             }
  323.         # GIF entry, <option><space> by itself on a line
  324.         else if ($0 ~ /^ $/)
  325.             {
  326.             PrintGIFTag(gifPartialLocation, gifName[++currentGIF]);
  327.             doingGIF = 1;
  328.             }
  329.         # regular line
  330.         else
  331.             {
  332.             ReplaceSpecialCharacters();
  333.             if (newParagraphComing == 1)
  334.                 PrintToOutFile("<P>" $0);
  335.             else
  336.                 PrintToOutFile($0);
  337.             newParagraphComing = 0;
  338.             }
  339.         }
  340.     }
  341.  
  342. # Load AND sort the gif names, to gifName[ 1..numGIFs ].
  343. # (gif name format is "arbtext#ddddd.gif")
  344. function LoadGIFNames(        x, p, a, b, numSpot, numA, trueP, i)
  345.     {
  346.     numGIFs = 0;
  347.     numA = 0;
  348.     while ((getline x < gifArrayFile) > 0)
  349.         p[++numGIFs] = x;
  350.     for (i = 1; i <= numGIFs; ++i)
  351.         {
  352.         numSpot = match(p[i], /#[0-9]+/);
  353.         # allow other files in folder, or other text in list
  354.         if (numSpot > 0)
  355.             {
  356.             a[++numA] = substr(p[i], numSpot+1, RLENGTH-1);
  357.             trueP[numA] = p[i];
  358.             }
  359.         }
  360.     if (numA+0 > 0)
  361.         {
  362.         sort(a,b,"n");
  363.         for (i = 1; i <= numA; ++i)
  364.             {
  365.             gifName[i] = trueP[b[i]];
  366.             }
  367.         }
  368.     numGIFs = numA;
  369.     }
  370.  
  371. # Print to specific file, if there is one.
  372. function PrintToOutFile(s)
  373.     {
  374.     if (outFile != "")
  375.         print s > outFile;
  376.     }
  377.  
  378. function ReplaceSpecialCharacters()
  379.     {
  380.     gsub(/\&/, ampersand); # keep this one first
  381.     gsub(/</, lessThan);
  382.     gsub(/>/, greaterThan);
  383.     gsub(/«/, euroLeft);
  384.     gsub(/»/, euroRight);
  385.     gsub(/•/, bullet);
  386.     gsub(/¬/, dornk);
  387.     gsub(/§/, section);
  388.     gsub(/¶/, para);
  389.     gsub(/ç/, cedillaC);
  390.     gsub(/—/, shy);
  391.     gsub(/©/, copyright);
  392.     gsub(/®/, registration);
  393.     
  394.     # Question mark gives trouble in anchors, do it too
  395.     #gsub(/\?/, question);
  396.     
  397.     # Short dash -- where is it in the ISO Latin-1 set??
  398.     gsub(/–/, "-");
  399.     # Ditto "…"
  400.     gsub(/…/, "...");
  401.     # And hey, where's ƒ?
  402.     gsub(/ƒ/, "f");
  403.     
  404.     # straighten out the quotes and ticks
  405.     gsub(/“/, "\"");
  406.     gsub(/”/, "\"");
  407.     gsub(/‘/, "'");
  408.     gsub(/’/, "'");
  409.     # do quotes last since we may have generated some new ones
  410.     gsub(/"/, quote);
  411.     }
  412.  
  413. function SimplifyQuotes()
  414.     {
  415.     gsub(/“/, "'");
  416.     gsub(/”/, "'");
  417.     gsub(/‘/, "'");
  418.     gsub(/’/, "'");
  419.     gsub(/"/, "'");
  420.     }
  421.  
  422. # Skip the "CONTENTS" section.
  423. function SkipUnwantedSections()
  424.     {
  425.     if ($0 ~ /^[ \t]*CONTENTS[ \t]*$/)
  426.         {
  427.         getline < inputFile;
  428.         while ((getline < inputFile) > 0)
  429.             {
  430.             if ($0 ~ /^-[ \t-]+$/)
  431.                 {
  432.                 getline < inputFile;
  433.                 break;
  434.                 }
  435.             }
  436.         }
  437.     }
  438.  
  439. # Finish writing current chapter, if any. Start a new temp file for
  440. # next chapter (tack "x" onto chapter name for the temp version)
  441. # and pump out the starting HTML.
  442. function StartNewChapter(chapterName,        truncatedName, nameLength)
  443.     {
  444.     if (outFile != "")
  445.         FinishCurrentChapter();
  446.     truncatedName = TempFileNameForChapter(chapterName);
  447.     outFile = chaptersFolder truncatedName;
  448.     StartHTML(chapterName);
  449.     }
  450.  
  451. function TempFileNameForChapter(chapterName,        fileName, nameLength)
  452.     {
  453.     fileName = chapterName ".html" "x";
  454.     nameLength = length(fileName);
  455.     if (nameLength > 31)
  456.         fileName = substr(chapterName, 1, 25) ".html" "x";
  457.     return fileName;
  458.     }
  459.  
  460. function FileNameForChapter(chapterName,        fileName, tempName, nameLength)
  461.     {
  462.     tempName = TempFileNameForChapter(chapterName);
  463.     nameLength = length(tempName);
  464.     fileName = substr(tempName, 1, nameLength - 1);
  465.     return fileName;
  466.     }
  467.  
  468. # Close temp file for chapter; copy it to final version, inserting
  469. # TOC at top; delete temp file.
  470. function FinishCurrentChapter(        nameLength)
  471.     {
  472.     PrintToOutFile("<P>");
  473.     DoChapterTOC();
  474.     EndHTML();
  475.     close(outFile);
  476.     oldOutFile = outFile;
  477.     nameLength = length(outFile);
  478.     outFile = substr(outFile, 1, nameLength - 1);
  479.     WriteFinalChapter();
  480.     close(outFile);
  481.     close(oldOutFile);
  482.     remove(oldOutFile);
  483.     # temporarily, we have no outFile to write to
  484.     outFile = "";
  485.     }
  486.  
  487. function StartHTML(chapterName)
  488.     {
  489.     PrintToOutFile("<HTML>");
  490.     PrintToOutFile("");
  491.     PrintToOutFile("<HEAD>");
  492.     PrintToOutFile("<TITLE>" chapterName "</TITLE>");
  493.     PrintToOutFile("</HEAD>");
  494.     PrintToOutFile("");
  495.     PrintToOutFile("<BODY>");
  496.     PrintToOutFile("<H1>" chapterName "</H1>");
  497.     PrintToOutFile("<HR>");
  498.     PrintToOutFile("");
  499.     PrintToOutFile(contentsMarker); # table of contents goes here on 2nd pass
  500.     }
  501.  
  502. function EndHTML()
  503.     {
  504.     PrintToOutFile("");
  505.     PrintToOutFile("</BODY>");
  506.     PrintToOutFile("");
  507.     PrintToOutFile("</HTML>");
  508.     PrintToOutFile("");
  509.     PrintToOutFile("");
  510.     }
  511.  
  512. # Print a heading and named anchor. "level" should be "H2", "H3" etc.
  513. # Having trouble with "?" in name, so leave it out of anchor name.
  514. function PrintHeading(name, level)
  515.     {
  516.     PrintToOutFile("<" level "><A NAME = \"" NoQuestionVersionOf(name) "\" >" name "</A></" level ">");
  517.     }
  518.  
  519. function NoQuestionVersionOf(name)
  520.     {
  521.     gsub(/\?/, "", name);
  522.     return name;
  523.     }
  524.  
  525. # All pictures are in ":Graphics:" beside ":Text:", and so "theLocation"
  526. # says go one level up and then down into Text.
  527. function PrintGIFTag(theLocation, theGIFName,        copyOfName)
  528.     {
  529.     PrintToOutFile("<P>");
  530.     # One little wrinkle, turn the "#" in name into "%23"
  531.     copyOfName = theGIFName;
  532.     sub(/#/, "%23", copyOfName);
  533.     PrintToOutFile("<IMG SRC=\"" theLocation copyOfName "\" ALIGN = \"top\">");
  534.     PrintToOutFile("<P>");
  535.     }
  536.  
  537. # The main table of contents.
  538. # We just print two levels. Additional levels would probably need additional
  539. # counters h3Counter, h4Counter etc and additional arrays.
  540. function DoTOC(        i, j, numSubHeads, contents, showSubs)
  541.     {
  542.     PrintToOutFile("<H2><A NAME = \"Table of Contents\">" " Table of Contents " "</A></H2>");
  543.     PrintToOutFile("<UL>");
  544.     for (i = 1; i <= h2Counter; ++i)
  545.         {
  546.         numSubHeads = split(TOC[i], contents, SUBSEP);
  547.         if (contents[numSubHeads] == "")
  548.             --numSubHeads;
  549.         
  550.         # Print the main heading, href is file corresponding to chapter
  551.         PrintToOutFile("<LI> <A HREF = \"Text/" FileNameForChapter(contents[1]) "\"> " contents[1] " </A>");
  552.         
  553.         # then print the subheadings
  554.         if (numSubHeads > 1)
  555.             {
  556.             # Check there are some headings to show - don't show if name starts with "!"
  557.             showSubs = 0;
  558.             for (j = 2; j <= numSubHeads; ++j)
  559.                 {
  560.                 if (index(contents[j], "!") != 1)
  561.                     {
  562.                     showSubs = 1;
  563.                     break;
  564.                     }
  565.                 }
  566.             if (showSubs == 1)
  567.                 {
  568.                 PrintToOutFile("\t<UL>");
  569.                 for (j = 2; j <= numSubHeads; ++j)
  570.                     {
  571.                     # href consists of location, file name (from chapter name), "#", subsection name
  572.                     if (index(contents[j], "!") != 1)
  573.                         PrintToOutFile("\t<LI> <A HREF = \"Text/" FileNameForChapter(contents[1]) "#" NoQuestionVersionOf(contents[j]) "\"> " contents[j] " </A>");
  574.                     }
  575.                 PrintToOutFile("\t</UL>");
  576.                 }
  577.             }
  578.         }
  579.     PrintToOutFile("</UL>");
  580.     }
  581.  
  582. function DoChapterTOC(        i, j, numSubHeads, contents)
  583.     {
  584.     # Print link to main table of contents
  585.     PrintToOutFile("<A HREF = \"../" contentsFileName "#Table of Contents\">Main Contents</A>");
  586.     
  587.     # Print chapter's table of contents
  588.     i = h2Counter;
  589.     numSubHeads = split(TOC[i], contents, SUBSEP);
  590.     if (contents[numSubHeads] == "")
  591.         --numSubHeads;
  592.     # Print the main heading
  593.     PrintToOutFile("<H2> <A HREF = \"#" contents[1] "\"> " contents[1] " </A></H2>");
  594.     if (numSubHeads > 1)
  595.         {
  596.         PrintToOutFile("\t<UL>");
  597.         for (j = 2; j <= numSubHeads; ++j)
  598.             {
  599.             # Trim any leading "!"
  600.             if (index(contents[j], "!") == 1)
  601.                 contents[j] = substr(contents[j], 2);
  602.             PrintToOutFile("\t<LI> <A HREF = \"#" NoQuestionVersionOf(contents[j]) "\"> " contents[j] " </A>");
  603.             }
  604.         PrintToOutFile("\t</UL>");
  605.         }
  606.     }
  607.  
  608. function WriteFinalChapter(        haveSeenContents)
  609.     {
  610.     haveSeenContents = 0; #speed things up with a simple "boolean"
  611.     
  612.     # Get lines from oldOutFile to the variable line.
  613.     while (getline line < oldOutFile > 0)
  614.         {
  615.         if (haveSeenContents == 0 && line ~ contentsMarker)
  616.             {
  617.             DoChapterTOC();
  618.             PrintToOutFile("");
  619.             haveSeenContents = 1;
  620.             }
  621.         else
  622.             PrintToOutFile(line);
  623.         }
  624.     }
  625.  
  626. # Write the main file, table of contents at one level above the chapter documents.
  627. # Finish any open chapter first.
  628. function WriteMainContentsFile()
  629.     {
  630.     if (outFile != "")
  631.         FinishCurrentChapter();
  632.     
  633.     outFile = contentsFileLocation contentsFileName;
  634.     
  635.     PrintToOutFile("<HTML>");
  636.     PrintToOutFile("");
  637.     PrintToOutFile("<HEAD>");
  638.     PrintToOutFile("<TITLE>" theMainTitle "</TITLE>");
  639.     PrintToOutFile("</HEAD>");
  640.     PrintToOutFile("");
  641.     PrintToOutFile("<BODY>");
  642.     PrintToOutFile("<H1>" theMainHead "</H1>");
  643.     PrintToOutFile("<HR>");
  644.     PrintToOutFile("");
  645.     
  646.     DoTOC();
  647.     
  648.     PrintToOutFile("");
  649.     PrintToOutFile("</BODY>");
  650.     PrintToOutFile("");
  651.     PrintToOutFile("</HTML>");
  652.     PrintToOutFile("");
  653.     PrintToOutFile("");
  654.     
  655.     close(outFile);
  656.     }
  657.  
  658. # Working within the current bounds of hAWK, we can (just barely) persuade
  659. # a folder to come into existence by using "copy", which creates folders
  660. # along the specified path if possible. So we make a file, copy it to the
  661. # folder we want to exist, and then remove both versions of the file. Ugh.
  662. function MakeFolder(folderPathName,     xFile, xFileSource, xFileDest)
  663.     {
  664.     xFile = "Temp1342134HIKE!";
  665.     xFileSource = STDPATH xFile;
  666.     xFileDest = folderPathName xFile;
  667.     print "Hello" > xFileSource;
  668.     close(xFileSource);
  669.     copy(xFileSource, xFileDest);
  670.     remove(xFileSource);
  671.     remove(xFileDest);
  672.     }
  673.