From: stolte@irit.irit.fr (Nilo STOLTE)
Newsgroups: comp.lang.postscript
Subject: TEXT FORMATTER - New Version
Date: 22 Nov 92 18:56:20 GMT
Organization: IRIT-UPS, Toulouse, France
Keywords: PostScript Text Formatter

Hi!

  Here goes a new version of the formatter to accept ANY number of pages and
that doesn't requires the comment %%Page: to be printed. Don't use it with the Pageview though. The older version should be used with it.

Nilo.

%!PS-Adobe-1.0
%%Title: Postscript text formatter
%%Author: Nilo Stolte
%%Page:
/reencsmalldict 12 dict def
/ReEncodeSmall
 { reencsmalldict begin
   /newcodesandnames exch def
   /newfontname exch def
   /basefontname exch def
   /basefontdict basefontname findfont def
   /newfont basefontdict maxlength dict def
   basefontdict
   { exch dup /FID ne
     { dup /Encoding eq
       { exch dup length array copy
         newfont 3 1 roll put
       }
       { exch newfont 3 1 roll put
       }
       ifelse
     }
     { pop pop }
     ifelse
   } forall
   newfont /FontName newfontname put
   newcodesandnames aload pop
   newcodesandnames length 2 idiv
   { newfont /Encoding get 3 1 roll put
   }
   repeat
   newfontname newfont definefont pop
   end
 } def
/scandvec [
 8#300 /Oacute
 8#311 /Atilde
 8#321 /oacute
 8#322 /Otilde
 8#323 /Ccedilla
 8#324 /otilde
 8#325 /ccedilla
 8#330 /Eacute
 8#331 /atilde
 8#332 /eacute
 8#333 /Udieresis
 8#334 /udieresis
 8#340 /Aacute
 8#342 /Acircumflex
 8#344 /Iacute
 8#347 /ecircumflex
 8#360 /aacute
 8#362 /acircumflex
 8#364 /iacute
 8#367 /eacute
 8#374 /uacute
 8#375 /ocircumflex
 8#376 /egrave
] def
/Times-Roman /Times-Roman-Scand scandvec
ReEncodeSmall
/Times-Roman-Scand findfont
13 scalefont setfont

/normalwidth ( ) stringwidth pop def
/maxbreakwidth 8 def
/maxlinesinpage 50 def

/tabwidth 30 def
/wordbreak ( ) def
/BreakIntoLines
  { /proc (nova_linha) cvx cvn def
    /linewidth (tamanho_linha) cvx cvn def
    /textstring exch def
    
    /breakwidth maxbreakwidth def
    /curwidth 0 def
    /lastwordbreak 0 def
    /startchar 0 def
    /restoftext textstring def
    /wordcount 0 def
    
    { restoftext wordbreak search
      { /nextword exch def pop
        /restoftext exch def
        /wordwidth nextword stringwidth pop def
        nextword (\011) eq
        { /curwidth curwidth tabwidth add def
          /wordwidth 0 def
        } if
        curwidth wordwidth add linewidth gt
        breakwidth  maxbreakwidth lt 
        nextword (\001) eq
        nextword (\015) eq
        or or or
        { textstring startchar
          lastwordbreak startchar sub
          getinterval /curline exch def
          nextword (\015) eq
          { curline () ne
            { { curline wordbreak search
                { /palavra exch def pop
                  /curline exch def
                  palavra () ne palavra (\011) ne and
                  { palavra show
                    normalwidth 0 rmoveto
                  } if
                  palavra (\011) eq
                  { tabwidth 0 rmoveto } if
                }
                { pop exit}
                ifelse
              } loop
            } if
          }
          { { curline wordbreak search
              { /palavra exch def pop
                /curline exch def
                palavra () ne palavra (\011) ne and
                { palavra show
                  breakwidth 0 rmoveto
                } if
                palavra (\011) eq
                { tabwidth 0 rmoveto } if
              }
              { pop exit}
              ifelse
            } loop
          } ifelse 
          yline maxlinesinpage lt
          { textstring dup length lastwordbreak sub lastwordbreak exch 
            getinterval
            /yline 0 def exit
          } if
          nextword (\001) ne nextword (\015) ne and
          { /startchar lastwordbreak def              
            /lastwordbreak lastwordbreak nextword length add 1 add def
          }
          { /lastwordbreak lastwordbreak nextword length add 1 add def
            /startchar lastwordbreak def
            /wordwidth 0 def
            /nextword () def
          } ifelse
          proc
          nextword () eq
          { /wordcount 0 def }
          { /wordcount 1 def } ifelse
          /curwidth wordwidth def
          /breakwidth maxbreakwidth def
        }
        { /curwidth curwidth wordwidth add def
          wordwidth 0 gt
          { /wordcount wordcount 1 add def
            wordcount 2 gt
            { /breakwidth linewidth curwidth sub wordcount 1 sub div def
            }
            { /breakwidth linewidth curwidth sub def
            } ifelse
          } if
          /lastwordbreak lastwordbreak nextword length add 1 add def
        }
        ifelse
      }
      { pop exit
      }
      ifelse
    } loop
    /lastchar textstring length def
    lastchar startchar gt yline 0 ne and
    { textstring startchar lastchar startchar sub getinterval show proc } if
 } def
/yinic 755 def
/yline yinic def
/ydec 13.07 def
/xrightmargin 72 def
/nova_linha {/yline yline ydec sub def
              xrightmargin yline moveto
            } def
/tamanho_linha 470 def
/alinha_dir { dup stringwidth pop tamanho_linha exch sub 0 rmoveto } def

xrightmargin yinic moveto

(November, 22th 1992.)  alinha_dir show 

/yline yline 15 sub def
nova_linha

(Hi everybody: \015 \015 \
\011 There is someboby that has asked me for a copy of the PostScript \
formatter I've written. So I send a copy of it. It is really a modification of \
a program in the Cookbook. \(Program 12 / A simple line breaking algorithm\). \
It also contains the program 18 to add accents to foreign languages. \015 \
\011 There are some very important variables to define the format of the \
resulting text. They are \(to change, locate /<variable name>\): \015 \015 \
\011 - yinic, inicial "y" value; \015 \
\011 - tamanho_linha, the size of the line; \015 \
\011 - tabwidth, the size of the tab spacing; \015 \
\011 - xrightmargin, the right margin; \015 \
\011 - ydec, the amount decremented from yline at each new line; \015 \
\011 - yline, variable that has the current line "y" value; \015 \
\011 - maxbreakwidth, maximal admitted space between words; \015 \
\011 - maxlinesinpage, maximal number of lines in a page. \015 \
\015 \011 In adittion there are values that should be set into the commands, \
like the size of the characters. It should be set in the "scalefont" command. \
\015 \011 Although this example is pretty clear, some comments should be done \
to use it correctly. The text to be formatted must be into a string pushed \
onto the stack as a parameter to the BreakIntoLines procedure. Inside this \
string is imperative the use of white space followed by a back slash \
in each line end. If the formatting fails this is most of the times the main \
reason. Inside this string many commands can be used to indicate special \
format characteristics. These commands are octal numbers, which in PostScript \
are represented as a backslash followed by three octal digits. It is \
imperative to separate these commands from the text before and after by one \
space. This is the second main source of errors. These commands should not be \
confused with the special characters also represented as octal numbers, \
that CAN be joined to the words. These commands are: \015 \015 \
\011 - \134001, Breaks the line and justify; \015 \
\011 - \134011, TAB character. Most used as paragraph; \015 \
\011 - \134015, CR character. Breaks the line, but doesn't justify. \015 \
\015 \011 Page breaks are automatic, but there must be at least the same \
number of "%%Page:" comments as the number of pages of the formatted text \
IF YOU USE Pageview!!! If you don't use Pageview, that is, you would only \
print the formatted file, you don't need anymore this. This new version does \
it automatically. With this new version the text can be of any size that it \
will break the pages properlly when printing. The version to the Pageview \
then remains reserved only to see the formatted text on the screen or to \
debug when altering the program. \015 \
\011 The names of the special characters to make accents in foreign \
languages, to change them, can be found \
in the red book under the title of "Codes and Names" in the appendix A. \
Observe the \134scandvec array and the octal codes on the left. On the \
right there are these names of characters which should be coded inside the \
text as the octal code \(ex: \362 is represented by \134362 inside the text\). \
Bug reports please mail to stolte@irit.fr. \
It is not what it could be called an \
ultimate text formatter and have its limitations. I count on you all to \
extend this program to a more complete set of comands to turn it \
more  flexible and usefull. Any changing should be mailed to me. \
\015 \015  Abra\325os, \015 \015 Nilo Stolte. \
\015 \015 PS: this text surpasses one page on purpose! )

{ BreakIntoLines
  showpage
  count 0 eq {exit} if
  /yline yinic def
  xrightmargin yinic moveto
} loop