home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol293 / toc.lbr / TBLCTENT.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1986-12-17  |  17.3 KB  |  510 lines

  1. program tblctent(input, output, infile, outfile);
  2.  
  3. (* WordStar file utility  --  9-21-85  Ver 1.0P *)
  4. (* Copyright  1985  by Dean A. Fields           *)
  5. (*                                              *)
  6. (* Written in TURBO PASCAL Ver. 3.0             *)
  7. (*     on a COMPAQ                              *)
  8. (*                                              *)
  9. (* Creates a Table of Contents  for  a WordStar *)
  10. (*   document file.  TBLCTENT looks for control *)
  11. (*   codes, and takes whatever is between them  *)
  12. (*   and places it in the table of contents     *)
  13. (*   file.  The control codes are, ^R to start  *)
  14. (*   and stop inclusion into the table of       *)
  15. (*   contents file.  They are placed in the     *)
  16. (*   file by entering a ^P^R at the begining    *)
  17. (*   and end of the text you want included into *)
  18. (*   the table of contents file.  The ^R's      *)
  19. (*   should never have WordStar dot commands    *)
  20. (*   between them.  The name of the table of    *)
  21. (*   contents file is the same as the input     *)
  22. (*   document, except the file type which is    *)
  23. (*   ".TBC".                                    *)
  24. (*                                              *)
  25.  
  26. Const
  27.     MaxLineLen = 255;              (* max. input line length *)
  28.     version = '1.0P';              (* version number *)
  29.     date = 'September 21, 1985';   (* release date *)
  30.     MaxNum = 4;                    (* maximum number of digits for .PN n *)
  31.     space = $20;
  32.     bell = 07;
  33.     lf = 10;
  34.     cr = $0D;
  35.     ctlr = 18;
  36.     period = 46;
  37.     tens = 10;
  38.     hundreds = 100;
  39.     thous = 1000;
  40.     MaxChrs = 55;                  (* max. char.s allowed for TBC entry *)
  41.     PageLen = 55;                  (* number of lines per page *)
  42.     ControlR_1 : boolean = false;
  43.     ControlR_2 : boolean = false;
  44.     dop : boolean = false;
  45.     ChNum : integer = 1;
  46.     page_num : integer = 0;
  47.     line : integer = 0; (* variable that contains the current *)
  48.                         (*     TBC line # being output for    *)
  49.                         (*     the current TBC page           *)
  50. (*
  51.  * TblLine is the next line to be printed to the .TBC file
  52.  *)
  53.     TblLine : integer = 7; (* initialize TblLine to 7 *)
  54.  
  55. TYPE
  56.     AnyString= string[255];
  57.  
  58. VAR
  59.     infile, outfile : text;
  60.     LineIn : array[1..MaxLineLen] of byte;
  61.     LoopCntr, chrcnt, indx : integer;
  62.     dot_cmnd, cancel : boolean;
  63.     page_num_print : array[1..4] of byte;
  64.     ch : char;    (* character read from input file *)
  65.  
  66. (*
  67.  * The following function converts any lower case characters in a string
  68.  * to upper case, and was copied from TURBO PASCAL manual (v3.0) page 146.
  69.  *)
  70. FUNCTION StUpCase(st:anystring):anystring;
  71. VAR
  72.     I : integer;
  73. begin (* FUNCTION StUpCase *)
  74.     for i:= 1 to length(st) do
  75.         st[i] := upcase(st[i]);
  76.     stupcase := st;
  77. end;
  78.  
  79.  
  80. (*
  81.  * This procedure opens the input and output files
  82.  *)
  83. PROCEDURE open_files;
  84. VAR
  85.     infname : string[20];
  86.     outfname : string[20];
  87.     ans : string[10];
  88.     goodfile : boolean;
  89.     dotpos, FileNmeEnd : integer;
  90.  
  91. BEGIN
  92.     repeat
  93.         write('Enter input filename  --> ');
  94.         readln(infname);
  95.         infname := StUpCase(infname);
  96.         assign(infile, infname);
  97.         {$I-} reset(infile) {$I+};
  98.         goodfile := (IOresult = 0);
  99.         if not goodfile then
  100.         begin
  101.             clrscr;
  102.             GotoXY(1,6);
  103.             write (chr(bell));
  104.             writeln('FILE ', infname, 'NOT FOUND!!!');
  105.             delay(6000);
  106.         end;
  107.     until goodfile;
  108.     repeat
  109.         dotpos := 0;
  110.         FileNmeEnd := length(infname);
  111.         dotpos := POS('.', infname);
  112.         if (dotpos > 0) then
  113.         begin
  114.             dotpos := pred(dotpos);
  115.             outfname := copy(infname, 1, dotpos);
  116.         end
  117.         else
  118.             outfname := copy(infname, 1, FileNmeEnd);
  119.         insert('.TBC', outfname, (FileNmeEnd+1));
  120.         FileNmeEnd := 20 - (FileNmeEnd+4);
  121.         delete(outfname, (FileNmeEnd+5), FileNmeEnd);
  122.         assign(outfile, outfname);
  123.         {$I-} reset(outfile) {$I+};
  124.         goodfile := (IOresult <> 0);
  125.         if not goodfile then
  126.         begin
  127.             write(chr(bell), 'FILE ', outfname, ' EXISTS, OVERWRITE? (Y/N) ');
  128.             readln(ans);
  129.             goodfile := (UpCase(ans[1]) = 'Y');
  130.             gotoxy(1, 7);
  131.             write('                                            ');
  132. (*
  133.  * the following code allows a to return to DOS, after
  134.  * closing the input file; in the event that goodfile comes
  135.  * back as an 'N'.
  136.  *)
  137.             if not goodfile then
  138.             begin
  139.                 cancel := true;
  140.             end
  141.         end;
  142.     until goodfile;
  143.     rewrite(outfile);
  144. (*
  145.  * output standard Table of Content header to output file
  146.  *)
  147.     writeln(outfile, '.op');
  148.     writeln(outfile);
  149.     writeln(outfile);
  150.     writeln(outfile, '                        Table of Content');
  151.     writeln(outfile);
  152.     writeln(outfile);
  153.     writeln(outfile);
  154.     end; (* procedure open_files *)
  155.  
  156.  
  157. (*
  158.  * The following procedure reads a line of input, ended by CRLF, into an
  159.  * internal buffer, for further processing. As the input characters are
  160.  * read they are anded with decimal 127 to strip of the 8th bit, if it's
  161.  * set.
  162.  *)
  163.     PROCEDURE get_line;
  164.     VAR
  165.         lonum : byte;    (* variable used to strip 8th bit *)
  166.  
  167.     begin
  168.         ch := chr(0);
  169.         lonum := 0;
  170.         chrcnt := 0;
  171.         while not eof(infile) and (lonum <> lf) do
  172.         begin
  173.             chrcnt := succ(chrcnt);
  174.             read(infile, ch);
  175.             lonum := (ord(ch) and 127);
  176.             LineIn[chrcnt] := lonum;
  177.         end
  178.     end; (* procedure get_line *)
  179.  
  180.  
  181. (*
  182.  * Procedure test_line searches the input line, that has been read in
  183.  * by get_line, for the following conditions:
  184.  *        .OP  -> which causes the program to stop searching for Table
  185.  *                of Content information, because .OP turns off page
  186.  *                number and therefore there is no page number to
  187.  *                associate to the Table of Content entry, and thus
  188.  *                no reason to report a Table of Content entry.
  189.  *
  190.  *        .PA     which causes the page number variable to be
  191.  *                inceremented
  192.  *        .PN n   which causes the page number variable to be set
  193.  *                to number n of the .PN n command.  n can not be
  194.  *                larger than 9999.
  195.  *)
  196.     PROCEDURE test_line;
  197.     VAR
  198.         pndx : integer;    (* index for page_num_print array *)
  199.  
  200.     begin
  201.         dot_cmnd := false; (* initialize dot_cmnd to false *)
  202. (*
  203.  * search for .OP
  204.  *)
  205.         if LineIn[1] = period then
  206.         begin
  207.             ch := chr(LineIn[2]);
  208.             if UpCase(ch) = 'O' then
  209.             begin
  210.                 ch := chr(LineIn[3]);
  211.                 if UpCase(ch) = 'P' then
  212.                 begin
  213.                     line := 0;
  214.                     dop := true;
  215.                 end
  216.             end
  217.         end;
  218. (*
  219.  * search for .PA
  220.  *)
  221.         if LineIn[1] = period then
  222.         begin
  223.             ch := chr(LineIn[2]);
  224.             if UpCase(ch) = 'P' then
  225.             begin
  226.                 ch := chr(LineIn[3]);
  227.                 if UpCase(ch) = 'A' then
  228.                 begin
  229.                     line := 0;
  230.                     dot_cmnd := true;
  231.                     page_num := succ(page_num);
  232.                 end
  233.             end
  234.         end;
  235. (*
  236.  * search for .PN n
  237.  *)
  238.         if LineIn[1] = period then
  239.         begin
  240.            ch := chr(LineIn[2]);
  241.            if UpCase(ch) = 'P' then
  242.            begin
  243.                ch := chr(LineIn[3]);
  244.                if Upcase(ch) = 'N' then
  245.                begin
  246.                    line := 0;
  247.                    dop := false; (* reset dop flag *)
  248.                    dot_cmnd := true;
  249.                    indx := 4;
  250. (*
  251.  * ignore spaces between .pn and number, if any
  252.  *)
  253.                    while LineIn[indx] = space do indx := succ(indx);
  254.                    pndx := 0;
  255.                    repeat
  256.                        pndx := succ(pndx);
  257.                        page_num_print[pndx] := LineIn[indx];
  258.                        indx := succ(indx);
  259.                        if pndx > MaxNum then
  260.                        begin
  261.                            if LineIn[indx] <> cr then
  262.                            begin
  263.                                ClrScr;
  264.                                gotoxy(1,10);
  265.                                writeln(chr(bell),'Invalid .PN command, number is too large');
  266.                                writeln('Last valid page number was ', page_num);
  267.                                writeln('Table of Content program ABORTING!!');
  268.                                delay(6000);
  269.                                cancel := true;
  270.                                LineIn[indx] := cr;  (* force repeat until to end *)
  271.                            end
  272.                        end;
  273.                    until LineIn[indx] = cr;
  274. (*
  275.  * the follow code converts the n, of the .PN n command, from a text number
  276.  * to an integer number
  277.  *)
  278.                    page_num := page_num_print[pndx] - 48;
  279.                    Case pndx of
  280.                        2 : begin
  281.                            page_num := page_num + ((page_num_print[pndx-1] - 48) * tens);
  282.                            end;
  283.                        3 : begin
  284.                            page_num := page_num + ((page_num_print[pndx-1] - 48) * tens);
  285.                            page_num := page_num + ((page_num_print[pndx-2] - 48)* hundreds);
  286.                            end;
  287.                        4 : begin
  288.                            page_num := page_num + ((page_num_print[pndx-1] - 48) * tens);
  289.                            page_num := page_num + ((page_num_print[pndx-2] - 48) * hundreds);
  290.                            page_num := page_num + ((page_num_print[pndx-3] - 48) * thous);
  291.                            end;
  292.                    end (* case *)
  293.                end (* if *)
  294.            end (* if *)
  295.        end (* if *)
  296.      end; (* procedure test_line *)
  297.  
  298.  
  299. (*
  300.  * Procedure translate_line translates fenced Table of Content entries
  301.  * into Table of Content entries in the Table of Content file. (if you
  302.  * can figure out that last sentence, you'll have no problem with the
  303.  * this program) Control R is the fence character. This procedure
  304.  * searches for a Control R. When the first Control R is encountered, a
  305.  * flag (ControlR_1) is set true and the following characters are written
  306.  * to the Table of Content file. When a second control R is found then a
  307.  * flag (ControlR_2) is set true, which ends character writting to the
  308.  * Table of Content file, clears both Control R flags, formats the rest
  309.  * of the Table of Content line, and puts in the page number for that
  310.  * entry.
  311.  *)
  312.     PROCEDURE translate_line;
  313.     VAR
  314.         indx1 : integer;         (* index used to step thru the input line *)
  315.         RemainChrs : integer;    (* variable to contain the number of   *)
  316.                                  (*    characters remaining in the TBC  *)
  317.                                  (*    line being printed. Used for     *)
  318.                                  (*    formatting TBC lines so that     *)
  319.                                  (*    they look uniform.               *)
  320.  
  321.     begin (* procedure translate_line *)
  322.         for indx1 := 1 to chrcnt do    (* process every character in the line *)
  323.         begin
  324. (*
  325.  * check for a ^R
  326.  *)
  327.             if LineIn[indx1] = ctlr then
  328.             begin
  329.                 indx1 := succ(indx1);
  330. (*
  331.  * if a ^R found, then determine which one
  332.  *)
  333.                 if (ControlR_1) then ControlR_2 := true
  334.                 else ControlR_1 := true;
  335.             end;
  336. (*
  337.  * the follwoing code is executed if the 2nd ^R is found
  338.  *)
  339.             if ControlR_2 then
  340.             begin
  341.                 ControlR_1 := false;
  342.                 ControlR_2 := false;
  343. (*
  344.  * keep TBC lines to 55 characters wide, max
  345.  *)
  346.                 if ChNum > MaxChrs then ChNum := MaxChrs;
  347. (*  determine the number of characters not used, out of a max. of 55 *)
  348.                     RemainChrs := MaxChrs - ChNum;
  349. (*  if RemainChrs does not divide evenly by 2, then a space is       *)
  350. (*  needed before you can start putting the dots on the TBC line     *)
  351.                     if (RemainChrs MOD 2) > 0 then
  352.                         write(outfile, ' ');
  353. (*  integer div. of RemainChrs by 2 yields the number of dots to be  *)
  354. (*  printed                                                          *)
  355.                 RemainChrs := RemainChrs DIV 2;
  356.                 write(outfile, ' ');
  357. (*  print the dots                                                   *)
  358.                 for LoopCntr := 1 to RemainChrs do
  359.                     write(outfile, '. ');
  360. (*  print the page number                                            *)
  361.                 write(outfile, page_num:4);
  362.                 writeln(outfile);
  363. (* incerement the TBC line counter and reset the TBC character       *)
  364. (*  counter to 1                                                     *)
  365.                 TblLine := succ(TblLine);
  366.                 ChNum := 1
  367.             end;
  368. (*
  369.  * the follwoing code is executed if the 1st ^R is found
  370.  *)
  371.             if ControlR_1 then
  372.             begin
  373.                 if ChNum = 1 then
  374.                 begin
  375.                     write(outfile, '   ');    (* indent each TBC line by 3 char.s *)
  376.                 end;
  377.                 if ChNum < MaxChrs then
  378.                 begin
  379. (*
  380.  * CR and LF are filtered from Table of Content entries, in the event
  381.  * that an entry spans a line.
  382.  *)
  383.                     if LineIn[indx1] <> cr then
  384.                     begin
  385.                         if LineIn[indx1] <> lf then
  386.                         begin
  387. (*
  388.  * filter out control characters
  389.  *)
  390.                             if LineIn[indx1] > 31 then
  391.                             begin
  392.                                 ch := chr(LineIn[indx1]);
  393.                                 write(outfile, UpCase(ch));
  394.                                 ChNum := succ(ChNum)
  395.                             end (* if > 31 *)
  396.                         end (* if lf *)
  397.                     end (* if cr *)
  398.                 end (* if ChNum *)
  399.             end (* if *)
  400.         end; (* for *)
  401.     end; (* procedure translate_line *)
  402.  
  403.  
  404. (*
  405.  * The following function returns a true value if the
  406.  * character input was a "Y" or "y"
  407.  *)
  408.     FUNCTION inyn : boolean;
  409.     VAR
  410.         ans : string[10];
  411.  
  412.     begin
  413.         write('Y/N  ');
  414.         readln(ans);
  415.         inyn := (UpCase(ans[1]) = 'Y')
  416.     end; (* function inyn *)
  417.  
  418.  
  419.   (*
  420.    * The process procedure controls Table of Content processing,
  421.    * if the program is not canceled at the open_file procedure.
  422.    * This procedure executes get_line to retrieve a line from
  423.    * the input file; executes test_line to search for WordStar
  424.    * dot commands; executes translate_line, depending on the
  425.    * results of test_line, and counts the number of pages of
  426.    * input to be scanned for Table of Content entries.
  427.    *)
  428.     PROCEDURE process;
  429.     VAR
  430.         contnu : boolean;   (* set false if program is to be *)
  431.                             (*     abnormally ended *)
  432.  
  433.     BEGIN
  434.         contnu := true;
  435.         gotoxy(1,12);
  436.         write('Page # ');
  437.         while contnu do
  438.         begin
  439.             get_line;
  440.             test_line;
  441.             if not cancel then
  442.             begin
  443.                 if not dop then
  444.                 begin
  445.                     if not dot_cmnd then
  446.                     begin
  447.                         line := succ(line);
  448.                         if line > PageLen then
  449.                         begin
  450.                             line := 0;
  451.                             page_num := succ(page_num)
  452.                         end; (* if line > PageLen *)
  453.                         translate_line;
  454.                         gotoxy(8, 12);
  455.                         write(page_num:5)
  456.                     end (* if not dot_cmnd *)
  457.                 end (* if not dop *)
  458.             end
  459.             else
  460.                 contnu := false;
  461.         if eof(infile) then
  462.             contnu := false;
  463.         end (* while contnu *)
  464.     end; (* procedure process *)
  465.  
  466.  
  467. (*
  468.  * The exit procedure displays an end of processing message, closes
  469.  * all open files, and returns to DOS
  470.  *)
  471.     PROCEDURE exit;
  472.     begin
  473.         ClrScr;
  474.         gotoxy(1, 11);
  475.         if cancel then
  476.         begin
  477.             writeln('Table of Contents program Aborted!!');
  478.             close(infile);
  479.             close(outfile)
  480.         end
  481.         else
  482.         begin
  483.             writeln('Table of Content program completed!');
  484.             writeln(outfile);
  485.             close(infile);
  486.             close(outfile)
  487.         end
  488.     end; (* procedure exit *)
  489.  
  490.  
  491. (*
  492.  * MAIN is the actual Table of Content program. It announces
  493.  * the start of the program, and ask for the name of the file
  494.  * to be scanned for Table of Content entries.
  495.  *)
  496.     BEGIN (* main *)
  497.         ClrScr;
  498.         cancel := false;
  499.         writeln;
  500.         writeln('WordStar Table of Content generator Program');
  501.         writeln('Copyright 1985 by Dean A. Fields');
  502.         writeln('Version # ', version, ' of ', date, '.');
  503.         writeln;
  504.         gotoxy(1, 6);
  505.         open_files;
  506.         if not cancel then
  507.             process;
  508.         exit
  509.     end. (* main *)
  510.    COM MÇ