Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Paragraph Return 1

Status
Not open for further replies.

Rick4

IS-IT--Management
Oct 3, 2003
6
US
Is it possible to take an unknown length text string and put it into a
"(unknown length text string.) show" line and if it exceeds a known length have it insert a paragraph return so that the results may look something like this:
unknown length
text string.
which would obviously have to replace spaces or even better and more intuitive to break long words appropriately with hyphenations.
All help greatly appreciated,
Rick
 
Sure there is... there isn't a concept of "paragraph return" though. Everything is positioned... I don't know where to start, this is basic to PostScript but requires a basic understanding OF PostScript.

Hyphenation is possible, but exceedingly difficult.

One of the first things a beginning PostScript programmer does is write a line-return or word-wrap procedure. As the programmer becomes more skilled, he (or she) will then add advanced features, such as justification, centering, and so on.

The heart of the technique is the "search" operator, where you search for the space character. Add the stringwidth of the "pre" substring to your left margin and compare to the position of your right margin. If it's still within bounds, show it, if not, reposition to your left-margin and down your lead amount. Redefine the "post" substring as your source string, until you loop through the whole string.

Make sense?

Thomas D. Greer
 
Thanks for your help on this, I'll give it a shot, but may require more help. I guess I couldn't hide the fact that I'm a newbie.

I've worked with the following code to center a text string and have incurred yet another situation that I can't seem to find the answer for.

Consider the following example:

/Times-Roman findfont 10 scalefont setfont
0 setgray
0 234 moveto
(text string here) stringwidth pop
198 exch sub 2 div
0 rmoveto
(text string here) show

Is it possible to have just the word "text" in bold and "string here" remain Times-Roman and yet all in the same line to retain the centering function?
 
Yes, you can do that. What you'll quickly discover though, is that you have to program all of this. There aren't quick and easy switches or "bold tags" like in HTML.

You have to break things down into small steps.

1) set your plain font.
2) break your string into pieces
3) measure the pieces that print in the plain font
4) set your bold font
5) measure the bold substrings
6) add all the substrings together
7) calculate your starting x position
8) set the plain font, show the plain substrings
9) set the bold font, show the bold substrings

Then think long and hard about the most effecient way to write this code. Construct a procedure to do it, pass your string in...

I'm here to help, I've been a PostScript programmer and trainer for years.

Thomas D. Greer
 
Rick,

This is a lot of code to try to digest... but if you can work your way through this and understand what is happening and why, you'll be well on your way.

This is to "word-wrap" a string. As a bonus it also includes (depends upon) a string concatenation procedure.

Code:
%!PS

/catstr  % string and array concatenation
{ /catcore
  { exch 2 copy
    length exch length add
    string dup dup 5 2 roll
    copy length exch
    putinterval
  } def
  dup type (stringtype) eq
  {catcore}
  { dup length 1 sub /catL exch def {} forall catL {catcore} repeat}
  ifelse
} bind def

% space-counting procedure
/spacecount
  { 0 exch ( )
    { search 
        { pop 3 -1 roll 1 add 3 1 roll  
        }
        { pop exit
        } ifelse
    } loop
  } bind def

% make some abbreviations, definitions
/space ( ) def                    % define a space
/dsp { dup stringwidth pop } def  % measure text
/cpp { currentpoint pop } def     % where are we?
/ssp { space search pop } def     % look for spaces

/x 72 def       % one-inch left margin
/rm 288 def     % right margin
/yPos 600 def   % starting y position
/leading 12 def % space between lines
/y {yPos leading sub dup /yPos exch def} bind def

% measure words: keep running total: newline when required
/P { ( ) catstr dup spacecount
     { ssp dsp cpp add rm gt
       { x y moveto exch catstr show }
       { exch catstr show }
       ifelse
     } repeat pop
   } def


/Helvetica 10 selectfont
x y moveto
(Now is the time for all good men to come to the aid of their country.) P

Thomas D. Greer
 
It's giving me the following error:

Stack:
/spacecount

I found a mini application in the PLRM but it's not working either, it hangs but doesn't return any errors. Can you look at it and deduce what may be going wrong with it?
Thanks,
Rick

%!PS-Adobe-2.0

/wordbreak () def
/BreakIntoLines
{/proc exch def
/linewidth exch def
/textstring exch def


/breakwidth wordbreak stringwidth pop def
/curwidth 0 def
/lastwordbreak 0 def

/startchar 0 def

/restoftext textstring def


{restoftext wordbreak search
{/nextword exch def pop
/restoftext exch def
/wordwidth nextword stringwidth pop def

curwidth wordwidth add linewidth gt
{textstring startchar
lastwordbreak startchar sub
getinterval proc
/startchar lastwordbreak def
/curwidth wordwidth breakwidth add def}
{/curwidth curwidth wordwidth add
breakwidth add def
}ifelse
/lastwordbreak lastwordbreak
nextword length add 1 add def
}
{pop exit}
ifelse
}

loop

/lastchar textstring length def
textstring startchar lastchar startchar sub
getinterval proc
}def

/Times-Roman findfont 16 scalefont setfont

/yline 650 def

(Just have some text here to demonstrate how the application is supposed to work, this should be enough text.)

300
{72 yline moveto show
/yline yline 18 sub def}


BreakIntoLines


showpage
 
I've tested the code I've posted extensively, and it's in production at several high-traffic commercial printing sites.

Did you copy/paste exactly? What version of Distiller are you running (assuming you're running Distiller).

Thomas D. Greer
 
The problem with the code you posted is with the definition of "wordbreak". You have an empty string, whereas you need a space:

Code:
/wordbreak ( ) def

But my code is better :). If you can get it working (I'll help), then we can add a "J" procedure for full-justified text, and a "C" procedure for centering, "R" for right-justified, etc.

Thomas D. Greer
 
The log file generated follows:

%%[ Error: undefined; OffendingCommand:    ]%%

Stack:
/spacecount


%%[ Flushing: rest of job (to end-of-file) will be ignored ]%%
%%[ Warning: PostScript error. No PDF file produced. ] %%

Acrobat 4.0
I have Acrobat 5.0, on another machine if it would be worth trying there. I did copy the code exactly as you posted it.
Thanks,
Rick
 
Dunno what to say, I copied/pasted the posted code into a file and it runs fine. <shrug>. The code you posted will work if you redefine /wordbreak ( ) def.

Thomas D. Greer
 
Actually, no it doesn't , I mean the file distills and creates a PDF but it doesn't wrap the text. It runs off the page.

Some specs may help:
Mac OSX
BBEdit 6.5
Distiller 4.0
(Trying MacGhostView and MacPS2PDF as well)

Is there a syntax highlighting text editor more appropriate for this? If so, what is your suggestion?

I really want this to work, I understand most everything going on here but need a little help determining exactly what this line is doing, I admit this is over my head at the moment, but with some help I'll catch on. What exactly are we poping on and off the stack or reorganizing on the stack?: this line:
        { pop 3 -1 roll 1 add 3 1 roll  

from this section:
/spacecount
  { 0 exch ( )
    { search
        { pop 3 -1 roll 1 add 3 1 roll  
        }
        { pop exit
        } ifelse
    } loop
  } bind def

Thank You for your patience,
Rick
 
Rick,

I wish I knew what was going wrong on your system. I copied the code as you posted it, fiddled with it until I found the problem, tested it and so on.

In other words, I'm not just making assertions here, but actually testing everything.

The code fragment you just posted looks wrong. I can't really tell, maybe the forum software is doing something goofy. There should be a space between the parentheses.

Here's the breakdown: spacecount is a proc that returns the number of spaces in any given string. The first thing I do to a string is append a space to the end of it. Thus, the number of spaces=number of words.

1st, the spacecount proc puts a zero on the stack. This is the number of spaces. I'll add 1 to it each time I find a space. So now I have the string and 0 on the stack. &quot;exch&quot; swaps them. Next comes a space: ( ). That's a single space character inside parens. So the stack looks like:

space
string
zero

Next is the search. I'm searcing for a space in the string. (note that this search occurs within a loop).

Search returns a boolean (true or false). If true (it finds a string), it splices the string into 3 pieces and leaves them on the stack: post match pre bool. In other words, the substring after the search string, the search string, the substring before the search string, and &quot;true&quot;.

If false, it returns the entire string and false: string false.

At this point , the ifelse fires. If true, look what happens:

pop 3 -1 roll 1 add 3 1 roll

What's on the stack to be popped off? The boolean is gone, the ifelse consumed it. So it's the &quot;pre&quot; substring. Our first word/space. Throw the word away (pop!).

Our stack now looks like:

match
post
0

3 -1 roll &quot;rolls&quot; the 0 to the top. Next is &quot;1 add&quot;. Add 1 to 0, we found a space. Stack is:

1
match
post

3 1 roll rearranges the stack:

match
post
1

Now we repeat the loop. We go back to &quot;search&quot;, searching &quot;match&quot; (a space character) in &quot;post&quot; (the rest of our string).

We keep looping until we find no more spaces, the false section fires, which pops of the remaining string (which is empty at this point) and exits the loop: pop exit. The end result is a number on the stack representing the number of spaces in the string.

This is used as an argument for the &quot;repeat&quot; portion of the &quot;P&quot; procedure.



Thomas D. Greer
 
I just realized something. None of this will work if the code for &quot;space&quot; as presented in this forum does not match the code for &quot;space&quot; within your strings! This might happen because of the differences between HTML, PCs and Macs. It also probably explains why the spaces look like they are disappearing in the posted code fragments.

So do this: when you copy code into your editor from the forum, backspace out all of the spaces and RETYPE THEM!! This makes sure that the spaces inside the target strings match the space inside of, in my case the spacecount proc, and in the PLRM sample the wordbreak defintion.

Thomas D. Greer
 
Brilliant! Wish I had thought of that, and as often as I've encountered similar problems when crossing platforms (slaps forehead). Works like a charm now. You mentioned earlier that once this was working we could look at the possibility of adding procedures for other justifications.

I've given some thought to this and have deduced that once the stringwidth is determined that we might subtract the stringwidth from the right margin value and add to the x start value to produce a right justified text block (my best guess, let me know if I'm anywhere in the ball park on this, it's the way I think).

The centered justification seems that it may be a little bit more tricky. Would we add spaces next to spaces to spread the string out to the desirable width?

Thanks for all the great help,
Rick
 
Rick... a shameless request. I often get business based on posts I make to this forum. I'm not soliciting your business, but would request that you mark any helpful posts I've made as such.

You understand right justification, that's how I'd approach it. Full justification involves a balance of adding a little extra space between words and a little space between letters. The balance that seems to work well is to spread 75% of the extra needed space between words, and 25% between letters.

Centering involves working back half the total line length from your centerpoint.

Thomas D. Greer
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top