home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / OUT18.ZIP / OUTFORM.INC < prev    next >
Encoding:
Text File  |  1986-11-25  |  10.7 KB  |  413 lines

  1.  
  2.  
  3. (*
  4.  * outline - a simple "outline" oriented document generator
  5.  *
  6.  * outform.inc - this module contains the procedures
  7.  *               for formatting and outputting blocks of text
  8.  *               and include files.
  9.  *
  10.  * Author:  Samuel H. Smith, 11-Jan-86
  11.  *
  12.  *)
  13.  
  14. type
  15.    word_info_rec = record
  16.       word: string[40];
  17.       spaces: integer;
  18.    end;
  19.  
  20. var
  21.    words:       array[1..40] of word_info_rec;
  22.    word_count:  integer;
  23.  
  24.  
  25. procedure print_options(var fd: textfile; opt: anystring);
  26. var
  27.    id: anystring;
  28.    code: integer;
  29.    i:    integer;
  30.  
  31. begin
  32.    i := pos(' ',opt);
  33.    if i > 1 then
  34.    begin
  35.       id := copy(opt,1,i-1);
  36.       opt := copy(opt,i,99);
  37.       while (copy(opt,1,1) = ' ') do
  38.          delete(opt,1,1);
  39.       val(opt,i,code);
  40.    end
  41.    else
  42.    begin
  43.       id := opt;
  44.       i := 0;
  45.    end;
  46.  
  47.    for i := 1 to length(id) do
  48.       id[i] := upcase(id[i]);
  49.  
  50.    if id = '.PAGE' then       {.PAGE nnn}
  51.       page_number := i
  52.    else
  53.  
  54.    if id = '.EJECT' then
  55.       prnline := 100
  56.    else
  57.  
  58.    if id = '.SMALL' then
  59.    begin
  60.       writeln(fd,^O);
  61.       indent_mult := 3;
  62.    end
  63.    else
  64.  
  65.    if id = '.ELITE' then
  66.    begin
  67.       writeln(fd,#27':');
  68.       indent_mult := 2;
  69.    end
  70.    else
  71.  
  72.    if id = '.NORMAL' then
  73.    begin
  74.       writeln(fd,^R);
  75.       indent_mult := 1;
  76.    end
  77.    else
  78.  
  79.    if id = '.ENHANCE' then       {enhanced print}
  80.       writeln(fd,#27'I'#3#27'G')
  81.    else
  82.  
  83.    if id = '.NOENHANCE' then
  84.       writeln(fd,#27'I'#1)
  85.    else
  86.  
  87.    if id = '.JUST'  then
  88.       justify := true
  89.    else
  90.  
  91.    if id = '.NOJUST'  then
  92.       justify := false
  93.    else
  94.       write(fd,'** Unknown option: ',id,' ',opt,' (',i,')');
  95.  
  96. end;
  97.  
  98.  
  99. procedure justify_line(indent:  integer);
  100. var
  101.    i,j:   integer;
  102.    need:  integer;
  103.  
  104. begin
  105.  
  106.    need := right_margin - indent - length(lineout) + words[word_count].spaces;
  107.  
  108.    while (need>0) and (word_count>2) do
  109.    begin
  110.       i := random(word_count-1);
  111.       with words[i] do
  112.          if random(spaces*spaces+1) = 1 then    {don't allot big spaces}
  113.          begin
  114.             words[i].spaces := words[i].spaces + 1;
  115.             need := need - 1;
  116.          end;
  117.  
  118.    end;
  119.  
  120.    lineout := '';
  121.    for i := 1 to word_count do
  122.    with words[i] do
  123.       lineout := lineout + word + copy('          ',1,spaces);
  124. end;
  125.  
  126.  
  127. procedure reformat_line(var fd:     textfile;
  128.                         linein:     linestring;
  129.                         indent:     integer;
  130.                         var lines:  integer);    {reformat one or more
  131.                                                   lines of text to fit
  132.                                                   the margins between
  133.                                                   'indent' and right_margin;
  134.                                                   also counts output lines}
  135.  
  136. var
  137.    i:           integer;
  138.    word:        anystring;
  139.    c:           char;
  140.  
  141. begin                 {this procedure is by far the slowest part
  142.                        of printing to a file.   there are several
  143.                        "tricky" things done here for the sake
  144.                        of greater speed.  mostly this involves taking
  145.                        advantage of the fact that str[0] is the length
  146.                        of str, and that whole string assignment generates
  147.                        code to move the whole string to/from the stack}
  148.  
  149.    if lineout='' then
  150.       word_count := 0;
  151.  
  152.    if (linein = '') or (linein[1] = ' ') then   {if this is a blank line or
  153.                                                  the start of a new paragraph}
  154.    begin
  155.       if lineout <> '' then                 {write any partial line}
  156.       begin
  157.          writeln(fd, '':indent, lineout);
  158.          pflush(fd);
  159.          lines := lines + 1;
  160.          lineout := '';
  161.       end;
  162.  
  163.       writeln(fd);                          {write a blank line}
  164.       pflush(fd);
  165.       lines := lines + 1;
  166.       word_count := 0;
  167.    end;
  168.  
  169.  
  170.    linein := linein + ' ';            {the line will now be reformatted;
  171.                                        make sure last word on the
  172.                                        line is terminated}
  173.    word := '';
  174.  
  175.    for i := 1 to length(linein) do
  176.    begin
  177.       c := linein[i];
  178.  
  179.       if c = ' ' then                   {if at the end of a word}
  180.       begin
  181.  
  182.          if (ord(word[0]) + ord(lineout[0]) + indent) >= right_margin then
  183.                                             {and the word won't fit
  184.                                              on this output line}
  185.          begin
  186.             if justify then
  187.                justify_line(indent);     {justify the line if needed}
  188.  
  189.             writeln(fd, '':indent, lineout);
  190.             pflush(fd);
  191.             lines := lines + 1;
  192.  
  193.             if word = '' then
  194.             begin
  195.                lineout := '';
  196.                word_count := 0;
  197.             end
  198.             else
  199.             begin
  200.                lineout := word + c;          {then start a new line}
  201.                word_count := 1;
  202.                words[1].word := word;
  203.                words[1].spaces := 1;
  204.             end;
  205.          end
  206.          else
  207.  
  208.          if word <> '' then
  209.          begin
  210.             word_count := word_count + 1;
  211.             words[word_count].word := word;
  212.             words[word_count].spaces := 1;
  213.  
  214.             case word[length(word)] of    {put an extra space after these}
  215.                '.',',',';',':':
  216.                   begin
  217.                      word := word + ' ';
  218.                      words[word_count].spaces := 2;
  219.                   end;
  220.             end;
  221.  
  222.             lineout := lineout + word + ' ';
  223.          end;                              {else add a word to this line.
  224.                                             a lot of time is spent on this
  225.                                             line.  how to make it faster?}
  226.  
  227.          word := '';                         {consume the word}
  228.  
  229.       end
  230.       else
  231.       begin
  232.  
  233.          word[0] := succ(word[0]);
  234.          word[ord(word[0])] := c;   {not a space, build up a word.
  235.                                      this is a faster version of
  236.                                        word := word + c;}
  237.       end;
  238.    end;
  239.  
  240. end;
  241.  
  242.  
  243.  
  244.  
  245. procedure print_include_file(var fd:    textfile;
  246.                              line:      anystring;
  247.                              indent:    integer;
  248.                              var lines: integer);   {print the contents of
  249.                                                      an include file at a
  250.                                                      given indentation.
  251.                                                      also counts output lines}
  252. var
  253.    incfile:  anystring;
  254.    incfd:    text[3000];
  255.    incline:  string[255];
  256.    txtfile:  boolean;
  257.    c:        char;
  258.    pc:       char;
  259.  
  260. begin
  261.  
  262.    incfile := locate_file(copy(line, 2, 255));
  263.    txtfile := copy(incfile,length(incfile)-3,4) = '.inc';
  264.  
  265.    if (prnfile <> 'CON.PRN') then
  266.    begin
  267.       gotoxy(10,wherey);
  268.       disp('Text: '+incfile);
  269.       clreol;
  270.    end;
  271.  
  272.    if file_exists(incfile) then
  273.    begin
  274.  
  275.       if lineout <> '' then      {flush last reformatted line}
  276.       begin
  277.          writeln(fd, '':indent, lineout);
  278.          pflush(fd);
  279.          lines := lines + 1;
  280.          lineout := '';
  281.       end;
  282.  
  283.  
  284.       assign(incfd, incfile);
  285.       reset(incfd);
  286.  
  287.       while not eof(incfd) do    {copy each line from the include
  288.                                   file; do not reformat}
  289.       begin
  290.          incline := '';
  291.          c := #0;
  292.          repeat
  293.             if not eof(incfd) then
  294.             begin
  295.                pc := c;
  296.                read(incfd,c);
  297.                if (c = #10) or (c = #13) then
  298.                   incline := incline + #0
  299.                else
  300.                   incline := incline + c;
  301.             end;
  302.          until (c = #10) or (eof(incfd));
  303.  
  304.          if paragraph_reformat and txtfile then       {reformat the text}
  305.             reformat_line(fd, incline, indent, lines)
  306.          else
  307.  
  308.          begin                            {do not reformat the text}
  309.             writeln(fd, '':indent*indent_mult, incline);
  310.             pflush(fd);
  311.             lines := lines + 1;
  312.          end;
  313.       end;
  314.  
  315.       close(incfd);
  316.    end
  317.  
  318.    else
  319.       writeln(fd, '*** Include file not found: ', line);
  320.  
  321. end;
  322.  
  323.  
  324.  
  325. procedure print_text_lines(var sec:    section_ptr;
  326.                            var fd:     textfile;
  327.                            indent:     integer;
  328.                            format:     print_formats;
  329.                            var lines:  integer);
  330.                                  {output the text line portion
  331.                                   of a section of the outline}
  332. var
  333.    i:       integer;
  334.    num:     integer;
  335.  
  336. begin
  337.  
  338.    num := lines;
  339.    lineout := '';
  340.  
  341.    for i := 1 to max_text do
  342.    with sec^ do
  343.    begin                                {output the lines of text;
  344.                                          with word wrap includes}
  345.       if text^[i] <> '' then
  346.  
  347.          if text^[i][1] = '@' then
  348.             print_include_file(fd, text^[i], indent, lines)
  349.                                              {descriptions with @filename
  350.                                               will insert the contents of
  351.                                               a file into the output}
  352.  
  353.          else
  354.  
  355.          if text^[i][1] = '&' then
  356.             print_graph_file(fd, text^[i], indent, lines)
  357.                                              {descriptions with &filename
  358.                                               will insert the contents of
  359.                                               a graphics file into the output}
  360.  
  361.          else
  362.  
  363.          if text^[i][1] = '.' then
  364.             print_options(fd, text^[i])   {process options with .xxx}
  365.  
  366.          else
  367.  
  368.          if paragraph_reformat then       {reformat the text}
  369.             reformat_line(fd, text^[i], indent, lines)
  370.          else
  371.  
  372.          begin                            {do not reformat the text}
  373.             writeln(fd, '':indent, text^[i]);
  374.             pflush(fd);
  375.             lines := lines + 1;
  376.          end;
  377.                                              {else reformat it}
  378.  
  379.    end;
  380.  
  381.  
  382.    if lineout <> '' then      {output last reformatted line}
  383.    begin
  384.       if break_into_pages then
  385.       begin
  386.          if (prnline > pagelen) then
  387.          begin
  388.             write(fd,^L);
  389.             flush(fd);
  390.             prnline := 1;
  391.          end;
  392.  
  393.          check_page_header(fd,format,sec);
  394.       end;
  395.  
  396.       writeln(fd, '':indent, lineout);
  397.       pflush(fd);
  398.  
  399.       lines := lines + 1;
  400.       lineout := '';
  401.    end;
  402.  
  403.    if num<>lines then
  404.    begin
  405.       writeln(fd);
  406.       pflush(fd);
  407.       lines := lines + 1;
  408.    end;
  409.  
  410. end;
  411.  
  412.  
  413.