From: zaphod@ctrg.rri.uwo.ca (Lance R. Bailey)
Subject: Re: text formatters written in PostScript?
Reply-To: zaphod@ctrg.rri.uwo.ca
Organization: University of Western Ontario
Distribution: na
Date: Fri, 16 Oct 1992 10:33:30 GMT
Keywords: long

In article <1bkhvdINNdku@gap.caltech.edu> carl@SOL1.GPS.CALTECH.EDU (Carl J  
Lydick) writes:
>No, we're not.  We realize that were such a program available, one could  
simply
>download the program and the text to the PostScript printer and let IT do the
>formatting.  If we use more than one operating system in our work, it wouldn't
>be necessary to port the code for the formatter to each operating system.

well, this is NOT an automajik text formatter in PS, but it is the latest
(as of last night) version of ParaShow, my easyformatter in PostScript.

The problem was that when creating slides, or summat with BASIC text 
formatting, I would be pulling out my hair while manually linebreaking and
positioning. adding a single word could cause 10 minutes of shuffling "moveto"s
to get things lined up again.

ParaShow takes some simple definitions such as margins, linespacing, format
style and "what to do with the currentpoint after the text"

ParaShow will not stay within the page edges. ParaShow will not do page 
breaking. ParaShow DOES allow you to quickly format sections of text on 
a page.

There are couple of improvements over the last version,
  - the line spacing is no longer negative. I kept going "up" the page,
    so allowed a positive line spacing to be "up"
  - instead of specifying the maximum line width, and working from the
    currentpoint, you specify the left and right margin. the Y value is
    still pulled from currentpoint.
  - the currentpoint may be placed in 4 different ways after the text is
    printed (see below)


usage::
 int   int   int   int   int   int   string    ParaShow  -
 CP    LS    LM    RM    I     FT    S         ParaShow  -

CP is where the currentpoint will be located after the text is printed.
   0 - place where the next line of text would have gone.
   1 - place where the next line of text would have gone, BUT with one blank
       line insterted (useful for leaving blank line betwixt blocks of text)
   2 - leave at the end of the last line
   3 - as with '2', but with a single space added. makes it possible to change
       fonts in the middle of a paragraph.

LS is the linespaceing. a positive integer means DOWN the page
LM is the left margin
RM is the right margin
I is the indent on the first line. a negative gives hanging paragraphs
FT is the format type
   0 - is filled text (acheived by stretching the text)
   1 - is left justified
   2 - is right justified
   3 - is centered
S is the string. preceeding spaces are removed, multiple spaces are compacted

There are two test pages: the first shows each of the four format styles with
each of the four "where to leave currentpoint treatments". An X marks the
position of currentpoint.

the second page shows how to use the code to handle font changes in mid 
paragraph.

--
Lance R. Bailey  System/Network Manager         Robarts Research Institute
     NeXT/email: zaphod@ctrg.rri.uwo.ca    box: Clinical Trials Resources Group
            fax: +1 519 663 3789                P.O. Box 5015, 100 Perth Dr.
            vox: +1 519 663 3787 x4108          London, Canada N6A 5K8
My Canada Includes the World Series

-------cut-here-------------------------------------------------------
%!PS-Adobe-2.0 EPSF-2.0
% ParaShow -- take a string and format it into a paragraph
% realized by lance bailey (zaphod@uuserve.on.ca, lrb@rri.uwo.ca)
% 
%lineAfterText linespace maxlen indent text    formattype ParaShow  -
%boolean       int       int    int    string  int        ParaShow  -


/ParaShowDict 10 dict def
ParaShowDict begin

/showIT {} def

/concatonate        %    string1 string2   CONCATONATE  string2string2
{  2 copy length exch length dup 5 1 roll add string
   dup dup 6 1 roll 4 1 roll
   5 -1 roll 3 -1 roll putinterval 0 exch putinterval
}bind def


/length2            % string string   LENGTH2  int 
{stringwidth pop exch stringwidth pop add}def


/isblank            % string ISBLANK boolean          is the supplied  
*character* a string?
{(\t\n\r\f ) exch search {pop pop pop true}{pop false} ifelse } def


/getword            %   string  GETWORD  remainingstring word true    
                    %   string  GETWORD  string false   
{ dup dup () eq
   {pop false}
   { 0 {  2 copy get ( ) dup 0 4 -1 roll put isblank not
                 {exit}if 1 add 2 copy exch length ge {pop pop -1 exit} if
       } loop
       dup -1 eq{pop pop () false}   
       {   dup 4 1 roll {  2 copy get ( ) dup 0 4 -1 roll  put isblank
             {exch pop exit}if 1 add 2 copy exch length ge {pop pop -1 exit} if
           } loop
           dup -1 eq{ pop dup length 3 -1 roll dup 3 -1 roll sub neg  
getinterval()exch true} 
           {  2 copy 2 copy 7 -1 roll dup 3 1 roll sub getinterval 5 1 roll
              {  2 copy get ( ) dup 0 4 -1 roll  put isblank not
                 {exch pop exit}if 1 add 2 copy exch length ge {pop pop 0 exit}  
if
              } loop
              dup 0 eq {pop pop pop () exch  true}
              {  exch pop exch dup length 3 -1 roll dup 3 1 roll sub  
getinterval exch true
              } ifelse
           } ifelse
       } ifelse
   } ifelse
} def



/buildline      % maxlen builtline text   BUILDLINE   maxlen remainder string
{ { getword                        % stack is maxlen builtline string word true
                                   % OR stack is string () false
    { exch 4 1 roll                % stack is string maxlen builtline word
      2 copy length2 ( ) exch      % stack is string maxlen builtline word ( )  
lenofnew
      5 -1 roll dup 3 -1 roll      % stack is string builtline word ( ) maxlen  
maxlen lenofnew
      gt                           % stack is string builtline word ( ) maxlen
      { 5 -1 roll dup () eq {5 2 roll pop ()}{5 2 roll}ifelse concatonate
        concatonate exch           % stack is maxlen string new-builtline
      }
      { 5 1 roll  concatonate      % stack is maxlen string builtline word( )
        exch dup length 1 sub dup 0 lt{pop 0}if  0 exch getinterval exch
        3 -1 roll concatonate      % stack is maxlen builtline word string( )
        exit
      }ifelse
    }
    {exit}ifelse
  } loop
  exch
} def


/textshow        
[{dup stringwidth pop 3 -1 roll exch div 1 scale show}
 {show pop}
 {dup stringwidth pop 2 div neg 0 rmoveto show pop}
 {dup stringwidth pop neg 0 rmoveto show pop}
] def    %fill leftjustified centered rightjustified


/LLS  %last line show, how to show the last line of text
[{dup stringwidth pop exch show}
 {dup stringwidth pop exch show}
 {dup stringwidth pop dup -2 div 0 rmoveto  exch show 2 div}
 {dup stringwidth pop dup neg 0 rmoveto exch show neg}
] def   %fill leftjustified centered rightjustified


/LLP %last line pos, how to place currentpoint after the last line of text
[ {pop dup add 0 exch rmoveto}
  {pop 0 exch rmoveto}
  {0 rmoveto pop}
  {dup 0 lt ( ) stringwidth pop exch {neg}if add 0 rmoveto}
] def  % Extra line,  no Extra line,  just after text, after text with a blank

/FLP %first line pos, how to place currentpoint before the first line of text
[ {exch dup currentpoint exch pop moveto sub}
  {exch dup currentpoint exch pop moveto sub}
  {2 copy add 2 div currentpoint exch pop moveto exch sub}
  {dup currentpoint exch pop moveto exch sub}
] def  %fill leftjustified centered rightjustified

end

%stack should contain (from top down)
%   format      int: 0=filled, 1=left justified, 2=centered, 3=right justified
%   text        string: all blanks, tabs and newlines reduced to single blank
%   indent      int: indent of first line measured in pts, use 0 on centered  
text
%   leftmarg    int: left margin
%   rightmarg   int: right margin
%   linespace   int: line spacing desired
%   extra line  boolean: do we print a blank line after the paragraph
%we calculate
%   maxlen      int: maximum length of a line
%   showIT      proc: how to show the lastline

/ParaShow %currentpoint linespace leftmarg rightmarg indent formattype text    
PARASHOW  -
          %int          int       int      int       int    int        string  
PARASHOW  -
          %CP           LS        LM       RM        I      FT         S       
PARASHOW  -
{ ParaShowDict
  begin
    exch dup 6 4 roll 4 -1 roll               %stack is CP LS I text FT LM RM  
FT
    FLP exch get exec                  %stack is CP LS I text FT ML
    4 1 roll                                  %stack is CP LS ML I text FT
    dup 7 1 roll                              %stack is FT CP LS ML I text FT
    5 -1 roll neg 5 1 roll                    % "fix" (negate) the linespacing
    textshow exch get/showIT exch def         %stack is FT CP LS ML I text
    { 3 1 roll 2 copy                         %stack is FT CP LS text ML I ML I
      8 -1 roll dup 9 1 roll 3 eq{dup neg exch}{dup}ifelse %tweek indenting on  
rightjustify
      0 rmoveto sub                           %stack is FT CP LS text ML I ML-I
      4 -1 roll                               %stack is FT CP LS ML I ML-I text
      () exch buildline                       %stack is SLL CP LS ML I ML-I  
remainder text
      2 copy pop length 0 eq           % END IF REMAINDER NULL
      {  8 1 roll 4{pop}repeat 4 2 roll       % stack is CP LS text FT
         LLS exch get gsave exec grestore     % get and exec proc to show  
lastline
         3 -1 roll                            % stack is LL LS CP,currentpoint  
is end of text
         LLP exch get exec                    % get and exec the proc to place  
currentpoint
         exit                         % EXIT POINT!!!
      } if
      3 -1 roll exch dup()eq                  %stack is FT  CP LS ML I  
remainder ML-I text
      {pop pop}{gsave showIT grestore}ifelse  %stack is SLL CP LS ML I  
remainder
      exch dup neg 0 rmoveto 3 -1 roll        %stack is FT CP LS remainder I ML
      exch pop 0                              %stack is FT CP LS remainder 0 ML
      4 -1 roll dup 0 exch rmoveto            %stack is FT LS remainder 0 ML CP
      4 1 roll   3 -1 roll                    %stack is FT CP LS ML 0 remainder
    } loop
  end
} def

% sample test stuff

{ /X {-3 -3 rlineto 6 6 rlineto -3 -3 rlineto -3 3 rlineto 6 -6 rlineto stroke}  
def
  gsave
/Time-Roman findfont 10 scalefont setfont 200 780 moveto
0.9 dup scale
0 12 200 400 0 0 (this is some text for a test of the code we are testing)  
ParaShow
gsave X grestore 0 -30 rmoveto
0 12 200 400 0 1 (this is some text for a test of the code we are testing)  
ParaShow
gsave X grestore 0 -30 rmoveto
0 12 200 400 0 2 (this is some text for a test of the code we are testing)  
ParaShow
gsave X grestore 0 -30 rmoveto
0 12 200 400 0 3 (this is some text for a test of the code we are testing)  
ParaShow
gsave X grestore 0 -30 rmoveto

1 12 200 400 0 0 (this is some text for a test of the code we are testing)  
ParaShow
gsave X grestore 0 -30 rmoveto
1 12 200 400 0 1 (this is some text for a test of the code we are testing)  
ParaShow
gsave X grestore 0 -30 rmoveto
1 12 200 400 0 2 (this is some text for a test of the code we are testing)  
ParaShow
gsave X grestore 0 -30 rmoveto
1 12 200 400 0 3 (this is some text for a test of the code we are testing)  
ParaShow
gsave X grestore 0 -30 rmoveto

2 12 200 400 0 0 (this is some text for a test of the code we are testing)  
ParaShow
gsave X grestore 0 -30 rmoveto
2 12 200 400 0 1 (this is some text for a test of the code we are testing)  
ParaShow
gsave X grestore 0 -30 rmoveto
2 12 200 400 0 2 (this is some text for a test of the code we are testing)  
ParaShow
gsave X grestore 0 -30 rmoveto
2 12 200 400 0 3 (this is some text for a test of the code we are testing)   
ParaShow
gsave X grestore 0 -30 rmoveto

3 12 200 400 0 0 (this is some text for a test of the code we are testing)  
ParaShow
gsave X grestore 0 -30 rmoveto
3 12 200 400 0 1 (this is some text for a test of the code we are testing)  
ParaShow
gsave X grestore 0 -30 rmoveto
3 12 200 400 0 2 (this is some text for a test of the code we are testing)  
ParaShow
gsave X grestore 0 -30 rmoveto
3 12 200 400 0 3 (this is some text for a test of the code we are testing)   
ParaShow
gsave X grestore 0 -30 rmoveto
grestore
showpage
} exec


{   /ROMAN {/Times-Roman findfont 20 scalefont setfont}def
    /BOLD {/Times-Bold findfont 20 scalefont setfont}def
    100 740 moveto 400 740 lineto stroke
    200 720 moveto

    ROMAN
    3 22 100 400 0 1 (this is some text which preceeds a bold word. Here is the  
word:)ParaShow
    BOLD
    3 22 100 400 currentpoint pop 100 sub 1 ( bold ) ParaShow
    ROMAN
    2 22 100 400 currentpoint pop 100 sub 1 (and here we are continuing  
onwards.) ParaShow
    showpage
} exec