Chapter 12. Rich Text Format and NSText

The MathPaper windows that we built in the last chapter didn’t quite live up to their initial billing. We promised what you see on the left side of Figure 12-1 but gave what you see on the right. The difference between the two windows is a matter of fonts and formatting. Although the NSTextView object that we used allows a great deal of control over fonts and formatting, when we invoked the replaceCharactersInRange:withString: method in PaperController we were simply pasting plain ASCII text into the selection, which comes up as left-justified monofont text — not very interesting. To get the promised fonts and formatting, we’ll have to learn about Rich Text Format (RTF). Most of today’s word processors (e.g., TextEdit, Microsoft Word) support RTF, and it has been used as a cross-platform format for years, so you probably know a little bit about it already. In this chapter, we’ll show you how to code RTF right into your applications.

What we promised (left) and what we’ve delivered so far (right)

Figure 12-1. What we promised (left) and what we’ve delivered so far (right)

Rich Text Format

Suppose you want to amaze your friends by showing them how easy it is to create text with different font sizes in a window. You might want the final window to look something like that shown in Figure 12-2.

Desired text output

Figure 12-2. Desired text output

One way that you can do this is by using the NSText class as if it were a simple text editor, sending an instance of NSText commands to insert text, select the text, and then change the text to the desired size. Although this is an inefficient way to manipulate the NSText class, it is conceptually easy.

Formatting NSTextView Output

The NSText class (the superclass of our friend, NSTextView) provides lots of commands for selecting, modifying, and altering the text it contains. The NSFont class allows us to create a font with any name and point size, and the NSMakeRange( ) function returns an NSRange structure with a requested starting point and length. With the NSFont and NSRange, we need to send only a few messages to create the text in Figure 12-2.

Assume that theText is an object of the NSText class. The first message we’ll need is:

[theText replaceCharactersInRange:aRange withString:aString]

which replaces a substring of text in our NSText object with the string “aString”. The substring being replaced starts at position aRange.start and has length aRange.length. This is conceptually the same as selecting the substring in an editor and then typing some new text to replace it.

The next message we’ll need is:

[theText setFont:aFont range:aRange]

which sets the text in theText (an NSText object) in the range aRange to have the font aFont.

The last message we’ll need is:

[NSFont fontWithName:aName size:aSize]

which invokes an NSFont class (or factory) method to create a new font object with the name aName and point size aSize.

Following is the method we used to create the Helvetica text in the window in Figure 12-2:

- (IBAction)fontDemo:(id)sender
{
    float s;

    for (s = 10.0 ; s < 36.0 ; s += 5.0) {

        NSString *str = [NSString 
            stringWithFormat:@"This is Helvetica in size %g
", s];

        int length = [ [theText textStorage] length];
        NSRange range;

        [theText replaceCharactersInRange:NSMakeRange(length,0)
                               withString:str];

        range = NSMakeRange(length,[str length]);

        [theText setFont:[NSFont fontWithName:@"Helvetica" size:s]
                   range:range];
    }
}

If you want to see the fontDemo: method’s output, create a new project and insert the method in a new subclass of NSObject. The subclass should also contain an outlet called theText that connects to an NSScrollView in a window. To invoke the method, instantiate an object of your new subclass, make it the delegate of the File’s Owner, and invoke fontDemo: in the applicationDidBecomeActive: notification method. (Note that this is not the only way to do this.[33])

When we wrote our original NeXTSTEP book back in 1992, we called this method slowFontDemo: because it was very slow. Running on a 25-Mhz NeXTstation (CPU speed has certainly gotten better, thanks to Moore’s law), you could actually watch each line of text being inserted into the text object and being reformatted to the specified size. It actually looked like somebody was sitting down at the computer’s keyboard, inserting the string “This is Helvetica in size nn” into the text editor, selecting it with the mouse, and changing its size. When the method ran, it was just plain ugly. But that was 10 years ago. If you build a “quickie” application that invokes the fontDemo: method and run it today, the text will appear immediately. This is a testament both to the significantly faster speed of today’s computers and to the improved algorithms used for rastering fonts.

Indeed, this short demonstration shows some of the significant advantages of Cocoa for handling text:

  • The fonts look great, because they’re automatically scaled by Quartz to whatever size you request.

  • The text automatically wraps when you resize the window.

  • The second time you run this demo it will run even faster, because the Window Server will have cached bitmaps for the sizes of the fonts that you have specified.

Nevertheless, it’s somewhat awkward to drive the NSText object like a word processor. For our purposes, it’s far better to simply load a file into the NSText object and have it display all of the fonts at the same time. To do that, we need to learn about Rich Text.

Rich Text Syntax

The other way to manipulate text is by constructing the text you want ahead of time — with all of the fonts and formatting commands already in place — and then reading it into the NSText object in a single operation. One format for this data stream, called Rich Text , was developed by Microsoft in the 1980s.

Rich Text looks a little like the codes used by TeX (pronounced “tech,” as in the word “technique”), the document typesetting system developed by Donald Knuth. Here’s the “raw” Rich Text code that will display the same fonts and text as the above demonstration:

{
tf1macansicpg10000cocoartf100
{fonttblf0fswissfcharset77 Helvetica;}
{colortbl;
ed255green255lue255;}
margl1440margr1440vieww8320viewh3920viewkind0
pard	x1440	x2880	x4320	x5760	x7200qlqnatural

f0fs20 cf0 This is Helvetica in size 10

fs30 This is Helvetica in size 15

fs40 This is Helvetica in size 20

fs50 This is Helvetica in size 25

fs60 This is Helvetica in size 30

fs70 This is Helvetica in size 35

fs20 
}

An RTF file consists of unformatted text (e.g., “This is Helvetica”), control words (e.g., fonttbl), control symbols (e.g., ~), and groups enclosed by curly braces ({}). Each control word begins with a backslash ( ) and consists of a string of letters followed by an optional numeric argument. Each control symbol (none in our previous example) begins with a backslash and is followed by exactly one nonalphanumeric character (e.g., ~ represents a nonbreaking space). Curly braces have a special meaning: they define groups that support Rich Text graphics states. If you change the state of a font within a graphics state, the change is lost when the state is closed.

Don’t be alarmed if Rich Text seems a little complicated! There are really only a few Rich Text controls that you need to be concerned about, and later in this chapter, we’ll introduce an RTF object that handles them for you automatically. Many of the RTF controls that are generated by the previous examples can safely be ignored.

Using TextEdit to Explore RTF

The Mac OS X editor TextEdit is a Rich Text editor. If you open a new file with TextEdit, it will be either a plain text file or an RTF file, depending on your TextEdit preference settings. If it’s plain text, choose TextEdit’s Format Make Rich Text menu command to make it RTF. Then save the “empty” file, and you’ll get a file that contains the following information:

{
tf1macansicpg10000cocoartf100
{fonttbl}
{colortbl;
ed255green255lue255;}
margl1440margr1440vieww9260viewh7500viewkind0
}

Try this in TextEdit, save your file, and then use the Unix cat (or vi, pico, etc.) command to list the file’s contents in a Terminal window. (The contents of your file may differ slightly, depending on your defaults.) If you add three lines of text in TextEdit in Helvetica (probably your default font), as shown in the window on the left in Figure 12-3, you’ll end up with something like this:

{
tf1macansicpg10000cocoartf100
{fonttblf0fswissfcharset77 Helvetica;}
{colortbl;
ed255green255lue255;}
margl1440margr1440vieww9000viewh7820viewkind0
pard	x1440	x2880	x4320	x5760	x7200qlqnatural

f0fs24 cf0 This is line 1
This is line 2
This is line 3
}
TextEdit files to examine RTF codes for text, weights, and angles

Figure 12-3. TextEdit files to examine RTF codes for text, weights, and angles

When TextEdit reads a file, it checks the first five characters to see if they are “{ tf”. If they are, TextEdit assumes that the file is in Rich Text Format.

Next, let’s experiment with text weight and angle changes. The window on the right in Figure 12-3 produces the following RTF code:

{
tf1macansicpg10000cocoartf100
{fonttblf0fswissfcharset77 Helvetica;f1fswissfcharset77 
Helvetica-Bold;f2fswissfcharset77 Helvetica-Oblique;
f3fswissfcharset77 Helvetica-BoldOblique;}
{colortbl;
ed255green255lue255;}
margl1440margr1440vieww9620viewh7500viewkind0
pard	x1440	x2880	x4320	x5760	x7200qlqnatural

f0fs24 cf0 This line is plain

f1 This line is bold

f2i0 This line is italic

f0i0 ul This line is underlined

f3i ulnone This line is bold italic
}

Now let’s try changing the font size. The window on the left in Figure 12-4 produces this RTF file:

{
tf1macansicpg10000cocoartf100
{fonttblf0fswissfcharset77 Helvetica;}
{colortbl;
ed255green255lue255;}
margl1440margr1440vieww3560viewh1820viewkind0
pard	x1440	x2880	x4320	x5760	x7200qlqnatural

f0fs20 cf0 This line is 10 point size

fs24 This line is 12 point size

fs28 This line is 14 point size

fs31 This line is 15.5 point size
}
TextEdit files to examine RTF codes for sizes and fonts

Figure 12-4. TextEdit files to examine RTF codes for sizes and fonts

Finally, let’s try changing fonts . The window on the right in Figure 12-4 produces this RTF file:

{
tf1macansicpg10000cocoartf100
{fonttblf0fswissfcharset77 Helvetica;f1fnilfcharset80 
AppleGothic;f2fmodernfcharset77 CourierNewPSMT;
f3fromanfcharset77 TimesNewRomanPSMT;f4fscriptfcharset77 
BrushScriptMT;}
{colortbl;
ed255green255lue255;}
margl1440margr1440vieww3500viewh2020viewkind0
pard	x1440	x2880	x4320	x5760	x7200qlqnatural

f0fs28 cf0 This is Helvetica

f1 This is AppleGothic

f2 This is Courier New

f3 This is Time New Roman

f4i This is Brush Script MT}

RTF Control Words and Symbols

Rich Text Format is a system for encoding various kinds of font information into a printable ASCII character stream (only 7-bit ASCII characters are used, for portability). Using Rich Text control words, you can encode font, size, and even margin changes in an application-independent fashion. There are many Rich Text control words; Apple implements only a subset of them. This brief discussion should be enough to get you going.

An RTF document begins with the character string “{ tf0” or “{ tf1” and ends with a closing brace, “}”. Inside the RTF document, you can have control words, which begin with a backslash (), and text. Control symbols are interpreted as commands, while text is displayed or printed.

You can have additional pairs of braces within an RTF file. Any formatting controls that you issue within a pair of braces will be used but will not be printed when the Rich Text is printed. For example, the following sequence in an RTF file:

This is { a test} of Rich Text.

prints like this:

This is a test of Rich Text.

Controls can appear anywhere in the text. For example, the strings:

This is  a test plain of Rich Text.

and:

This is  a test 0 of Rich Text.

print like this (the same as the string with braces above):

This is a test of Rich Text.

Normally, Rich Text ignores carriage returns. If you want a carriage return, precede it with a backslash (). If you want a backslash, type a double backslash (\). These are examples of control symbols.

You can define any number of fonts within an RTF document. Fonts are given numbers; you usually define them within a set of braces at the beginning of the document. In our earlier example, the following string defined a single font table, with the font f0 being Helvetica:

{fonttblf0fswissfcharset77 Helvetica;}

Table 12-1 summarizes some common RTF controls.

Table 12-1. Common RTF controls

Control word

Meaning

tf

Declares a file to be a Rich Text file — you should use tf0 or tf1

Font control word

Meaning

fonttbl

Begins definition of a font table

f0

Selects font 0

fswiss fontname

Selects a sans-serif font fontname

fmodern fontname

Same as fswiss

froman fontname

Selects a serif font fontname

fnil fontname

Selects another kind of font fontname

fs nn

Selects a font size — nn is in half points

Font control word

Meaning

plain

Plain



Bold

0

No bold

i

Italic

i0

No italic

gray nnn

Gray; nnn= 0 for black, 1000 for white

ul

Underline

ul0

No underline

up nn

Superscript nn half points

dnnn

Subscript nn half points

Formatting word

Meaning

xd5 l

Left-justify text (quad left)

xd5 c

Center-justify text (quad center)

xd5 r

Right-justify text (quad right)

ab

Tabstop

paperw nnnn

Paper width in twips[a]

paperh nnnn

Paper height in twips

margl nnn

Left margin

margr nnn

Right margin

fi nnnn

First-line indent in twips

li nnnn

Left indent in twips

ulw

Word underline

uld

Dotted underline

[a] There are 1,440 twips in an inch.

The RTF controls in Table 12-2, while useful, are not currently implemented by Apple.

Table 12-2. Unimplemented RTF controls

RTF control

Meaning

shad

Shadow

scaps

Small caps

caps

All caps

v

Invisible text

uldb

Double underline

If you specify a font that isn’t available on the machine you’re using, you are likely to get Courier.



[33] Another way to create an application to invoke fontDemo: is to use Project Builder and Interface Builder to create a project with an NSTextView object in a window and a menu item called Demo. Then subclass NSObject to get the MyObject class, and add an outlet called theText and an action called fontDemo: to it. Instantiate the subclass to get a MyObject instance, connect the theText outlet to the NSTextView outlet, and make the Demo menu cell send the action message fontDemo: to the MyObject instance. Finally, unparse MyObject, type in thefontDemo: code above, build and run the application, and choose the Demo menu command.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.144.248