[No, this isn't an oversight! We've left this document here for those who may have worked with OpenDoc DR2 but not DR3, and are now converting directly to DR4. Others can feel free to ignore this document.]
This document summarizes some of the major changes from Developer Release 2 (May ’95) to Developer Release 3 (August ’95) that will require you to change your source code. This is not an exhaustive list, but points out the major changes that will affect all or almost all part editors. Nor does it attempt to go into full detail; in most cases, the relevant recipe documents will give you the information you need to implement the changes. The sample parts also show how things should be done.
If your part editor was derived from sample code like SamplePart, ODLeafPart or the Peng-based parts, it might be easiest to take the DR3 version of the sample part and copy your editor-specific changes into it, rather than trying to rev your entire existing code.
You may want to take a look at DR3 API Changes, also in the Tech Notes folder, which lists all the API changes made between DR2 and DR3.
Reference Counting
• Our goal since DR2 has been to keep API changes to a minimum. But in order to work properly with pre-emptive multi-tasking (as on OS/2 and in the future on MacOS) we had to enforce some conventions with reference-counting. The general rule is: All methods that return a ref-counted object which is not an invariant of the object you're sending the message to, increment the reference-count of the object returned. This ensures that nothing in another thread could delete the object before the caller gets a chance to increment its ref-count.
• Does that sound confusing? To make it easier to remember, all methods that return a new reference to a ref-counted object now begin with the word “Acquire”. For instance, ODFrame::GetFrameShape is now called ODFrame::AcquireFrameShape. Even the method ODRefCntObject::IncrementRefCount was renamed ODRefCntObject::Acquire. Whenever you see “Acquire___” in a name, that means that you are responsible for releasing the object returned by the method.
• Due to these changes, there are several methods whose return values you didn't need to release in earlier versions, but you do now. For instance, ODFrame::GetWindow did not increment the ref-count of the ODWindow returned. It is now called AcquireWindow and does increment the ref-count.
• What does this mean to you? The two things you need to do are:
(1) Change the names of some of the methods you call from “Get___” to “Acquire___”. The compiler will flag all of these as errors since the old method name no longer exists.
(2) Add code to release references to objects returned from methods that didn't previously increment the ref-count. The refbal tool in the Goodies folder is invaluable for this — it will scan your source code and detect potential ref-count leaks. In fixing these situations you may want to use the TempObj utility, which is documented in the Tech Notes folder.
ODPart API Changes
• GetExtension was renamed AcquireExtension, and GetContainingPartProperties to AcquireContainingPartProperties, as per the Get—>Acquire changes described above.
• ContainingPartPropertiesChanged was renamed ContainingPartPropertiesUpdated, and EmbeddedFrameChanged was renamed EmbeddedFrameUpdated.
You'll need to rename these messages in the “override:” section of your part's .idl file, and the actual methods in your part's implementation file, and of course run the SOM compiler again.
• The type ODChangeID was renamed ODUpdateID. This affects the ODPart LinkUpdated and EmbeddedFrameUpdated and methods, which now take ODUpdateID parameters; change the parameter types in your part's implementation file.
Scripting API Changes
• ODDesc now has Get/SetDescType, and Get/SetRawData methods.
• ODNameResolver::SetUserToken is gone. Instead, ODNameResolver::GetUserToken returns a reference to the user's token.
• All methods of ODSemanticInterface have default implementation. You only have to override what you need when you subclass.
• Removed ODSemanticInterface::CallTokenInquiryProc. Its functionality is available in the standard part token now.
Other Changes
• ODDraft::BeginClone now takes an ODFrame* parameter. See the cloning recipes for details.
• ODDraft now has an IsValidID method that you can use to detect invalid IDs. Formerly this had to be done by detecting an exception returned from other draft methods, which is cumbersome. The linking recipes discuss how to use this method.
• ODDraft::CreateFrame now takes an “isSubFrame” parameter, but no “isRoot” parameter. This change affects only containing parts. See the embedding recipes for details.
• ODTypeListIterator's First and Next methods now return a pointer to a copied ODType string. You are responsible for deleting this string.
• The implementation of ODLinkSource::Clear has changed to remove the contents property completely. See the linking recipes for details.
• Mouse-up events are now always sent to the part that received the mouse-down event, regardless of where the mouse is at the time of the mouse-up. This makes it easier for parts to track drags if they aren't using the drag manager.
Changes To Utilities
Most of the changes summarized below are described in more detail in the documents in the Utilities Documentation folder.
• The List utility was renamed LinkList to avoid a name conflict with a list.h file in the Standard Template Library included with CodeWarrior 6.
• BeginUsingLibraryResources and EndUsingLibraryResources (in the UseRsrcM utility) can now nest: you can now activate your part's resource file more than once. This prevents crashes where one method that calls Begin and End happens to call another method that also calls Begin and End. In order for this to work, Begin now returns a 32-bit magic number that you need to pass to the matching End call. If you use the C++ version (CUsingLibraryResources) this all happens automatically and you don't need to change your code.
• The functions ODGetAsciiTextProp and ODSetAsciiTextProp were removed from StdTypIO, since Ascii text is no longer a standard data type. If you need to read and write raw text, just use the regular storage unit API to do so. However, we suggest that international text (ODIText) be used instead, since it's more localizable. There are utilities like ODGet/SetITextProp that will read and write this.
• There's a new utility called TempObj that uses the miracle of C++ operator overloading to provide “smart pointers” to objects, which automatically delete or release the object when the pointer goes out of scope. This can make it a lot easier to manage ref-counting, especially in an exception-safe way.
• Another new utility called Crawl lets you capture and dump stack crawls. This is a neat debugging feature that is used in a variety of places in the debug build of OpenDoc. For instance, when an exception is thrown a stack crawl is dumped to the log so you can see where it came from. And warnings emitted by WARN( ) show the name of the calling function. In order for function names to be accessible your code must be compiled with MacsBug names (68k) or traceback tables (PPC). Traceback tables in CodeWarrior are activated by putting “#pragma traceback on” in your prefix file.
• The Memory Manager (MemMgr.h and ODMemory.h) includes new functions that let you check the free space in the OpenDoc heap or the application heap. This will help your code preflight memory availability.
• Exception handling (the Except utility) is now really and truly compatible with C, as well as with native C++ exception handling. This was promised in DR2 but there turned out to be a few remaining problems.
• The CodeWarrior library ODMoreUtilities.lib is obsolete; remove it from your project file if it's present. (The utilities have been moved into the main ODUtilities.lib.)
Miscellaneous Changes
• StdTypes.r was renamed ODTypes.r. This is the standard header that part editor resource (.r) files should include.