[View Controller.h] 
[View Controller.m] 
[View Document.h] 
[View Document.m] 
[View DocumentReadWrite.m] 
[View Edit_main.m] 
[View Encodings.txt] 
[View LineAndCharacterRange.h] 
[View LineAndCharacterRange.m] 
[View MultiplePageView.h] 
[View MultiplePageView.m] 
[View MyTextView.h] 
[View MyTextView.m] 
[View NSMenuAdditions.h] 
[View NSMenuAdditions.m] 
[View Preferences.h] 
[View Preferences.m] 
[View README.GBDbundle.rtf] 
[View README.rtf] 
[View ScalingScrollView.h] 
[View ScalingScrollView.m] 
[View TextEdit.rtf] 
[View TextFinder.h] 
[View TextFinder.m] 



This file describes how to use the GDBbundle I wrote for the TextEdit demo application released by NeXT.

The GDB bundle was designed to be used specifically with TextEdit. It can't be used neither by the Edit application or by ProjectBuilder although it would be nice to have it also integrated into ProjectBuilder.

GDBbundle uses its own gdb which is a modified version of NeXT's version that makes possible sending back in the client bundle the output generated by gdb commands. There are also some other additions to the gdb to make possible getting the local variables of a frame. To install the modified version of gdb just copy it into a public place like /usr/local/bin. Be sure this directory is searched first when the shell searches for commands; you can do this by changing the PATH environment variable.

You have to follow the following simple steps to have a gdb session:

1. Start TextEdit.
2. From a terminal window start gdb with the following command line:

  $ gdb -connect TextEdit progname

This will start gdb and will make it connect to the TextEdit application. You'll have to have the TextEdit application already started, it will not start it for you.

It is possible to have a remote debugging session with GDBbundle. You'll have to start the TextEdit application on the machine you want to have the windows. Then start gdb with the following command:

  $ gdb -connect TextEdit:remote_machine progname

This will start gdb and will make it connect to the TextEdit application. You'll have to have the TextEdit application already started, it will not start it for you.

The modified version of gdb prints a message saying it tries to make a connection with TextEdit on a host:

Sep 01 23:25:30 gdb[4800] Debugger Controller: looking for connection named TextEdit on host *nil*

If you don't see this message then you're most probably running the system gdb!

Known bugs and limitations

GDBbundle and the actual TextEdit application have the following bugs and limitations:

 sometimes when you change the function before the results came back from gdb, the client gets confused and enters into an infinite loop. The only solution is to quit TextEdit and enter again.
 first time the last function is clicked it doesn't get selected. Click on the "start" function and then again on the function you want.
 gdb does not have command line history and editing when working with GDBbundle.

Copyright and copying terms

The TextEdit application was written by NeXT; all the right are reserved by NeXT. The GDBbundle was written by Ovidiu Predescu and all the rights are reserved. The TextEdit and GDBbundle are released together under the GPL license. Donations are welcome; please contact me for my address.

Happy hacking,
Ovidiu Predescu <ovidiu@net-community.com>



This directory contains the source code for the TextEdit demo, which is a simple text editor based on the 4.0 text system.  

Changes since 4.1
 Changed #ifdef WIN32 in Document.m to more dynamic calls to NSInterfaceStyleForKey()
 Added support for the new hyphenation feature in the text system
 Got tab stop locations in plain text mode to be recomputed when needed

Major source files and what's interesting about them:


Contains most of the implementation for the Document class. One instance of this is created for every document (new or saved) in TextEdit.  The internal designated initializer for this class is init; however, external clients should go through initWithPath:encoding:uniqueZone:; or better yet openUntitled or openDocumentWithPath:encoding:.

The text contents (characters, attachments, attributes) of the document are kept in an instance of NSTextStorage. There is also one NSLayoutManager, and one or more NSTextViews (depending on whether "wrap to page" mode is selected). setHasMultiplePages: determines whether the document is in "wrap to page" mode or not; study this method, addPage, and removePage to see how to create and manipulate NSTextViews programmatically.

setRichText: demonstrates what needs to happen when you want to convert an attributed string from being "rich" to "plain" and back. Note that in the new text system setting setRichText: on a text view simply prevents the user from manipulating attributes; however, the backing store can still contain multiple fonts, colors, etc. This is why this method needs to do the things it does.

As you will note, there is a good deal of code to deal with encoding of the characters in the document when the document contains plain text. The instance variable encodingIfPlainText stores the encoding of the document; this is either deduced from the file or specified by the user when the document is opened. Keeping this encoding around allows the document to be saved with the same encoding as it was read. (When in memory the character encoding of the document is somewhat meaningless, because the characters in the document are stored in an NSString, whose backing stores are always expressed in terms of Unicode characters. The encoding determines how to save the document when saved as plain text.)

The encodings recognized by NSString are listed in NSString.h; the encodings listed in the open panel accessory view are listed in the resource file Encodings.txt. TextEdit uses three additional values for encodings to denote unknown encoding, RTF, and RTFD; this is somewhat of a hack, but the chosen values are unlikely to be used as encoding values in the system.

Document class contains an instance of NSPrintInfo to store the default settings for printing. Setting horizontal pagination to NSFitPagination allows the text to be printed with the same wrapping as on the screen. In non-"wrap to page" mode this means the text might need to be scaled smaller when printed.

The method doForegroundLayoutToCharacterIndex: shows how to get the text system to lay text out in the foreground up to a certain character location. By default the text system does its layout in the background, which allows bringing up the window fairly quickly. The user can even edit, print, or save the document while the background layout is going on. Although this is rather interesting in practice, having the scrollbar race down the page when the document first comes up can be confusing to some users. Thus TextEdit causes a portion of the document (by default the first 100,000 characters) to be laid out before the document is displayed. For documents that are larger the layout will still continue in the background once the document is displayed. Note that the user can always cause a full layout to happen by hitting the "End" key on the keyboard.

There are a couple of instances of Windows-specific code in Document.m. Both are concerned with tweaking the look of the document scrollview to match the Windows guidelines. Note that rather than using a compile-time default (#ifdef WIN32), we look at the interface style to dynamically match the look & feel.

Features poorly implemented in Document include saveTo: (which would save the document elsewhere without changing its current path) and dynamically changing the tab stops in plain text documents on font changes (this should really be handled by the text system at some point). It would also be great (and easy!) to add undo.

One final note on the Document class: The example program Yap has a cleaner Document, which Yap subclasses to add Yap-specific functionality. If you need a very simple document class to handle text documents, you might want to check out Yap's Document.m.


This file contains the file I/O code, including a few convenience methods on NSAttributedString. The method loadFromPath:encoding: opens the specified file using the specified encoding, and the method  saveToPath:encoding:updateFilenames: saves the document using the specified name and encoding. 


This file contains the central controller object for TextEdit, which responds to application messages such as openFile:, printFile:, etc, and also implements the info panel.

A piece of Windows-specific code in this file assures that when the users double-click on a TXT.rtf within a .rtfd directory, the .rtfd is opened instead of the TXT.rtf. This gets around the fact that we cannot (yet) allow opening directories as documents from the Explorer.


In "wrap to page" mode there is one NSTextView per page. MultiplePageView is the top level view which groups all of these views.  It is inserted as the document view of the scroll view in the document window. MultiplePageView is fairly simple, providing support for conversions between page numbers and rects, and drawing the background for the pages.

A possible enhancement to this class would be to have it allow the user to manipulate the page margins by dragging guides around. An advanced exercise would be to add custom markers to the ruler to allow changing the page margins via the ruler as well.


Contains ScalingScrollView, a subclass of NSView to implement a scroll view with a popup to allow setting the zoom factor. This class is fairly generic and can easily be used in a variety of cases.


Along with the corresponding nib file FindPanel.nib implements basic replace and find functionality on text stored in an NSTextStorage.  Among other things demonstrates communicating with the pasteboard to get/set the find string.


Provides a preferences controller to read/write preferences stored in the defaults database. Provides support for specifying default values for the preferences, and tries to minimize the amount of information written out to the database by removing entries which have default values. 

Note that the preferences panel in TextEdit does not have an "OK" button to confirm the changes; changes take place immediately. However the Preferences class supports a panel with OK/Revert buttons; simply connect the OK button to ok:, and the Revert button to revert:.

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.