Packages specify their scenes in a list referenced by the sceneIndexicalList field of software package objects. When a package is unpacked, the scenes in the list are automatically installed into the system indexical iSceneIndexicalList.NewContentProxy() can now be used by subclasses of Scene to return subclasses of ContentProxy. Class Scene implements the new operation PrototypeContentProxy() which returns iPrototypeContentProxy. NewContentProxy() now calls this new operation instead of copying iPrototypeContentProxy directly. Subclasses of Scene can override PrototypeContentProxy() to return a ContentProxy subclass instead of reimplementing NewContentProxy().
The go to button in the package scene does not appear until the package has been unpacked. Now that the system configuration is flexible, it is not possible to figure out a proper go to location for most packages until they have been installed.
Removed the GoToGuide() method, which makes it possible to remove the guideBook field of class SoftwarePackage. This means that the guide button no longer exists in the package scene.
Created a new class, CardScene, that displays a card, but not necessarily a stack. This new class sits between Scene and StackScene in the class hierarchy. Moved the following operations from StackScene to CardScene: InstallCurrentCard(), RemoveCurrentCard() CurrentCard(), DefaultTool(), PlaceName(), Finalize(), MakeAddressesContentList(), ToggleEnvelope(), ForwardCard(), and ReplyToCard().
Renamed Scene_Stamps to LocalStamps(). It now returns an ephemeral list holding the stamps in this scene's SceneAdditions. SetLocalStamps() stores the contents of the list passed to it instead of storing the list itself.
SceneAdditions now has a new field, ownerScene which refers back to the scene that these additions appear in.
The skipSearching scene flag is obsolete.
MagicScript and Telescript were intertwined entities in Magic Cap 1.x. Rosemary separates the two. The Process class is now used for Magic scripts only. Telescript agents inherit from new classes.Magic Script now uses a Java based model of exeuction instead of the former Telescript based model.
Scripts are now defined in a high level language in object definition files, so that scripts can be edited directly. This is what a script look like:
Script unnamed9523; script prototype is [(Reference) -> void]; push iTextSelectionWindow; call Target [(Reference) -> Reference]; copy into variable 1; push iTextStyleWindow; call SetTarget [(Reference, Reference) -> void]; push iTextStyleWindow; call ShowOrHide [(Reference) -> void]; push iTextSelectionWindow; call OnScreen [(Reference) -> Boolean]; copy into variable 1; if true, goto label1; return; label1: push iTextSelectionWindow; call Disappear [(Reference) -> void]; End Script;
Scripts are attached to objects with this syntax:
instance <class> <tag> [<name>] <triggerOperation>: (Script <scriptTag>);
The <triggerOperation> is the operation that the script overrides, that used to be specified in the initial on statement in 1.x MagicScripts. This will usually be Action.The Rosemary Magic Cap API tries to avoid having multiple operations have the same name but different interfaces. Since Magic Cap doesn't do polymorphism, this is just plain confusing. Many operations have been removed or renamed to avoid this problem. Removed the operations TSInitialize(), Throw(), Current(), Done(), Next(), And(), Or(), Sum(), Difference(), Multiply(), Divide(), Compare(), Quotient(), Modulus(), Order(), IsBefore(), ValidateKeys(), Signature() and IsAfter().
Scripts will be able to invoke class operations and intrinsics.
Created new mixin HasBuiltInScrollArrows so classes other than list views can save the overhead of separate ScrollArrow objects. Classes ListView, ContainerWindow, Annotation and TaskAnnotation all inherit from this class now. This class also has some new operations for subclassing: ScrollArrowImage() which returns the image, ScrollArrowPositions() which returns the positions, UseBuiltInScrollArrows() which lets subclasses control whether each instance uses the built in arrows or not.HasBuiltInScrollArrows_DotInWhichScrollArrow is a new operation that returns a new enumerurated ScrollArrowType: noScrollArrow, scrollBackArrow, and scrollForwardArrow. HasBuiltInScrollArrows overrides CanDrawIn() to return kDontDrawHere if the start point of iCurrentTouchInput is in one of the built in scroll arrows. This fixes the problem of being able to scribble over the scroll arrows for classes that mix in HasBuiltInScrollArrows and have a superclass that handles CanDrawIn().
HasBuiltInScrollArrows supports both horizontal and vertical scrolling. The attribute ScrollsHorizontally() distinguishes the scrolling orientation. By default, this attribute returns true. Class Corridor now mixes in with HasBuiltInScrollArrows and overrides this attribute to implement horizontal scrolling.
Clarified scrolling inheritance to avoid problems where ScrollToBottom() and ScrollToEnd() could call each other ad infinitum. HasScrolling_ScrollToBeginning calls ScrollToTop() and ScrollToLeft(). HasScrolling_ScrollToEnd calls ScrollToBottom() and ScrollToRight. Classes that inherit from HasScrolling must implement ScrollToTop(), ScrollToLeft(), ScrollToBottom() and ScrollToRight(). Classes do not need to override ScrollToBeginning or ScrollToEnd.
The searching framework has been reorganized and improved. The classes CanBeSearched, CanBeSearchResult and CanShowSearchResults implement the basic searching architecture and will always be present in the system. The remaining search classes, ChooseSearchTool, Sniffy, SearchingListView and SearchingWindow implement the search user interface. These classes may not be present in all future versions of Magic Cap.CanBeSearched, which mixes in with Viewable, defines the frequently overridden method SearchForObject(). Subclasses of Viewable mix this in if they have a better idea about how to match text or images than just looking at all the subviews and calling MatchText() and MatchImage() on them, which is the default implementation.
CanBeSearchResult, a mixin with Object, defines methods needed to show the found object in a list and to display it to the user when selected in the list. This class defines the method DisplaySearchResult() which should be overridden for a matched viewable to properly display itself. This class replaces the SearchResult class.
CanShowSearchResults is an abstract mixin which defines the API for the searching user interface. It defines two methods, AddSearchResult() and AddSearchCandidate() which must be implemented by subclasses. Each object that is searched can report matching items back to the window with AddSearchResult(), and can report new objects to search back to the window with AddSearchCandidate().
SearchingWindow provides an implementation of CanShowSearchResults. It handles the user interface while the search is in progress and lists the search results. This class kicks the search off on either iCurrentScene or the new indexical iOutermostScene (usually iDowntownScene).
SearchingListView keeps around information about which found item was most recently displayed to support finding the next or previous item.
Sniffy is the class formerly known as SearchingAgent. The commandWindow field has been renamed searchingWindow. The commandButtons field has been renamed arrowImages. The operation ShowCommandWindow() has been renamed ShowSearchingWindow().
Sniffy always searches the current scene first. This simplies the searching interface; the "search this scene only" switch has been removed. The underlying support code has also been removed: the attribute SearchSceneOnly() and the indexical iNoMatchingItemsInScene have been removed.
TextSearchResult is a subclass of CanBeSearchResult that knows how to display matched text in scenes and cards.
DatebookSearchResult is a subclass of CanBeSearchResult that knows how to display text in notes, viewables in notes, viewables in the task editor and viewables in the task view.
AddressCardSearchResult keeps track of an address card or name card and a viewable or label. AddressCardSearchResult_DisplaySearchResult goes to the specified address card and highlights the viewable or label. Name cards can be found if they are filed elsewhere in Magic Cap, like the file cabinet.
Introduced support routines BlinkLabelAt() in classes AddressPanel and PhonePanel to support revealing and blinking labels on name cards when searching for contact information.
Viewable now mixes in with CanBeSearchResult and overrides DisplaySearchResult() to go to the enclosing scene or card and reveal the viewable.
Viewable_MatchViewable has been replaced by Viewable_MatchImage. MatchViewable() used to create a stamp from the image just to match the image contained in the stamp. MatchImage() just matches the image and helps to clarify what was being searched for anyway.
The skipSearching scene flag is obsolete.
Removed Card_MatchText which existed solely for the old searching framework.
Renamed SearchingWindow_InitiateSearch to SearchNow() since the method not only starts but also finishes the search.
Broke HasIndexing_FindExactMatch into FindElementMatching(), FindElementMatchingSubstring() and FindElementMatchingInitialSubstring(). FindExactMatch() used to find a similar whole string in some cases and a similar substring in others. FindElementMatching() now finds in a list the index of the first item whose sort-name matches a supplied text object. FindElementMatchingInitialSubstring() returns the index of the first item whose sort-name starts with the supplied text. FindElementMatchingSubstring() returns the index of the first item that contains the specified substring anywhere in the sort-name. The argument allowFollowingElement allows FindElementMatchingInitialSubstring() to return the first element that sorts after the search text if there is no match.
Removed HasIndexing_FindClosestMatch because it has always been conceptually flawed and broken.
Added better feedback that lets a user know that a search in progress can be stopped. Now, when a search is in progress, the text and image buttons and the search criteria field are covered with a text field that states that a search is in progress, but the stop button can be used to stop the search. The new field SearchingWindow_statusField contains a reference to this text field.
Improved the interface for finding objects in the garbage. Before, when Sniffy found text on a card in the trash, displaying the search result would hop the minicard to the desk before zooming it open. However, it was hard to tell that the minicard was coming from the trash because it the hop started at the position in the trash window that the minicard would have been at had the window been open. Now, the gadget of the enclosing window (the dump truck) is highlighted, and the hop starts from there when it's hopping a card to the desk. In the case, where the minicard is coming from a window that isn't showing, and the window doesn't have an onscreen gadget, the minicard is now always hopped from offscreen.
Fixed bugs that prevented Sniffy from searching in the file cabinet. There were two problems: cards inside folders in the file cabinet were never searched, and the folder names were never searched.
Renamed FolderTray_FindCard to FolderTray_FolderContainingCard.
Added FolderTray_DrawerContainingFolder to allow checking the name of a folder. You can use this method to determine if a particular folder is in the file cabinet somewhere. The drawer containing this folder is returned, or nilObject if the folder is not in any drawer.
Added FolderTray_PrepareToDisplayFolder. Given a folder in the file cabinet, it goes to the file cabinet with the correct drawer visible and set up the folder in the folder scene.
iMagicSound is played when the search is complete.
Added the intrinsics MakeShared(), MakeModifiable() and CopyNonShared(). Currently, these routines just call through to the old sharing model. By using these new interfaces, the transition to the new model will be easier. MakeModifiable() should be called when a shared object is about to be modified. CopyNonShared() should be called when a shared object is going to be copied, then modified. MakeShared() should be called when the modifications are finished and the object is again ready to be made unique among its sharing compatriots. This new suite of calls replaces the old DeleteDuplicate() call.The new shared object model introduces a new set of object management calls, and redefines the behavior of some existing calls.
- CopyNear
- old model: Copies the object.
- new model: Makes a non-shared copy of all objects, even shared objects.
- CopySharedNear
- old model: Calls MoveNear() except for indexicals.
- new model: Makes a shared copy for all objects except for indexicals, which are passed through without being copied.
- MakeModifiableNear
- old model: Calls CopyNear() on shared objects and indexicals. MoveNear() is called on non-shared objects.
- new model: Makes all objects modifiable. For non-shared objects, this is like calling MoveNear(). For shared objects, this may involve making a non-shared copy. The original shared object is always destroyed. Indexicals are just copied.
- MakeSharedNear
- old model: Calls DeleteDuplicate(), then MoveNear() for shared objects. MoveNear() is called for shared objects. Indexicals are passed through.
- new model: A shared copy is made, and the original copy is destroyed. Indexicals are passed through.
- Destroy
- old model: Destroys non-shared objects, but complains if a shared object or indexical is passed.
- new model: Destroys shared or non-shared objects, but does nothing to indexicals.
Destroy() no longer works for indexicals and shared objects in the old runtime. If you want to destroy an object referred to by an indexical, you need to call DirectID() first. Because Destroy() no longer works with indexicals, it has been turned into an intrinsic. This means that it can no longer be overridden. The operation ShallowDestroy() has been removed entirely.
MoveNear() does not exist in the new runtime. CopySharedNear() or MakeModifiableNear() should be used instead.
CopyTransient() and CopySystemPersistent() will create non-shared copies of an object, even if the object was shared. Callers need to call MakeShared() on the result to make a shared copy.
A new idiom is used to deal with ownership of shared objects. If a method is going to store a shared object into a strong field (objects in these fields are copied), the caller of the method is assumed to be the owner of the object, and the method must call CopySharedNear() to make a shared copy to store in the field. This means the caller must call Destroy() on the shared object they pass to the method if the caller created the object originally.
Object fields that refer to images now follow this idiom. Most of these changes occured within implementations of SetImage(). Code that stores an image in a field now call CopySharedNear() to create a new instance of the image near the owning object and destroy the original image.
Implementations of SetStyle(), SetBorder(), SetShadow(), SetSound(), SetShapeType() and SetRequestedFont also follow the new idiom now.
Instances of class AddressCard are no longer shared in Rosemary. The only reason they were shared at all was to reduce the amount of memory address cards consumed. AddressCard never really behave like a real shared object. The use of AddressCard instances should be phased out in favor of the new ContactAddresses and Contacts classes, but because instances of these new classes are not shared, AddressCard was made non-shared for parallelism. Since address cards are no longer shared, the UnsharedAddressCard class is no longer necessary.
Removed the HasDigest class, which was used by the old sharing model to provide the CRC for images, sounds, etc. Removed the definitions of Object_Digest and Object_MakeDigest.
Removed the UnsharedImage class. This is no longer needed because the new sharing model is shared per instance rather than per class.
The Rosemary version of Magic Cap introduces a hash table class. Magic Cap uses class HashTable to maintain many internal tables, but packages can use it for other purposes as well. Class HashTable defines the interface for adding and removing objects from the hash table, for searching for a particular entry, and for iterating over every entry in the table. The base HashTable class uses a CRC of the first four bytes of the key as the default hash function. Subclasses that require a different hashing function should override ComputeHashFromKey() and KeyMatchesHashEntry().
Text sorting and comparison (searching) used to be intertwined in the class LegacySortOrder. Rosemary splits these functions into two discrete classes, HasSortOrder and HasSearchCriteria. The interface for sorting address cards is defined by the mixin HasAddressCardSortOrder.Text sorting is language dependent. Rosemary defines the basic text comparison interface in the mixin class HasSortOrder. Localized versions of Magic Cap will use table driven implementations of the methods defined by HasSortOrder to provide proper sorting of text for that country.
The new mixin class HasSortText allows objects that have a sort name different from their name to still sort properly. HasSortText is a simple mechanism that allows Japanese objects to use kanji in their names to sort by their kana readings. Instances that don't need a different sort name can set the sortText field to nilObject.
Text searching is a localizable service, implemented in the localization package of international versions of Magic Cap. The abstract mixin class HasSearchCriteria defines the interface for localizable text searching. Each system has one instance of this mixin, referenced by the iDefaultSearchCriteria indexical. The text searching code implemented by LegacySortOrder has been moved into this class. HasText_FindText delegates calls to iDefaultSearchCriteria.
Rosemary provides better sound compression, increasing the storage capacity for sounds by a factor of three. Five second sound clips now take only 9K instead of 27K. While the API remains unchanged, the underlying compression algorithms have been replaced. By default, recording a sound stamp uses 2 bit ADPCM compression with a 7.2KHz sampling frequency. Holding down the option key when initiating a record uses 4 bit ADPCM compression at 11KHz.Renamed class ADPCM4bitCompressionAlgorithm to ADPCM4bitCompression. Class CVSDCompressionAlgorithm, which implemented the old compression algorithm, has been removed. Replaced iCDRomXACompression with iADPCM4bitHQCompression.
Removed the PlayRingSound() intrinsic. This just called PlaySound() anyway.
InstrumentCompletionProc() now takes a structure that contains the sound that was completed and any transform state that might have been allocated. Now the completion procedure can remove the sound that actually finished being played. PlayInstrumentNote() sets up this new structure.
Removed the completion and loop parameters for PlayInstrumentNot().
Fixed Sound_IsThisPlaying to correctly check to see if a sound was playing. You must call CheckPendingRun(false) if you do a busy-wait for a sound to finish.
BeginInstrumentSample() now returns a boolean value that says whether or not the sample was successfully added to the play list.
Fixed a bug where EndInstrument() would not properly stop the playing instrument.
The Macintosh simulator now uses 16-bit samples to play sound. This means that Macintosh System Software version 7.5.3 is required to run the simulator.
Removed the Speaker_PlaybackQuality attribute, since only 11K sound samples are supported in Rosemary.
Removed Sound_Decompress.
Created a new class, CardScene, that displays a card, but not necessarily a stack. This new class sits between Scene and StackScene in the class hierarchy. Moved the following operations from StackScene to CardScene: InstallCurrentCard(), RemoveCurrentCard() CurrentCard(), DefaultTool(), PlaceName(), Finalize(), MakeAddressesContentList(), ToggleEnvelope(), ForwardCard(), and ReplyToCard().Created a new class, SortedStackOfCards, that contains the sorting functionality that was implemented by SortedList. Classes that used to inherit from both StackOfCards and SortedList should now inherit from SortedStackOfCards instead.
Stacks of cards no longer have an insert order as defined by the InsertOrder() attribute. New cards are now always placed at the end of the stack for normal stacks, and at the appropriate place for sorted stacks.
The book of rules has been improved to deal with packages better. Created a new class, BookOfRulesStack, which automatically includes rules pages for all package scenes which are made public. Packages can publicize their scenes by installing into the new indexical iPublicPackageSceneList. Right now, packages must install into this list explicitly, but in future releases, iPackageStandardPlaces might be brought back and this list may be rebuilt automatically.
Package stacks are now kept in a list referenced by the stackIndexicalList in the software package object. When packages are unpacked, the stacks in this list are automatically installed into the system indexical iStackIndexicalList.
Removed the storage map feature and the supporting code.Fixed a bug where devices would hang after deleting changes from the package.
Improved the performance of displaying storeroom shelves. It used to add packages to the shelf one at a time to space them out nicely. Packages are put on the shelf in one fell swoop, resulting in displaying packages twenty five times faster. The new method Shelf_PositionAllContents does this work.
Removed obsolete fields Shelf_useFirstOnly, Shelf_growWhenDroped, and method Shelf_DroppedFromWindow.
Removed the cardOnly, mailFolder, and canSwallow fields of the StorageBox class. Storage boxes also can no longer swallow anything.
Removed the boxLock and isPackageBox fields of the StorageBox class.
Added Stream_WriteBigEndianWord, which assures that the word is written in a big endian format even on a little endian machine.Replaced Stream_ReadWord with Stream_ReadBigEndianWord. This new method simply reads a word on big endian hosts. On little endian hosts, the bytes in the word will be swapped.
Added new mixin classes Reader and Writer which implements class independent buffering for streams. These replace the non-functional ReadInChunksStream and WriteInChunksStream, as well as the StreamBuffer class. These classes mix in with Stream.
The Writer mixin automatically closes the writing stream when you destroy it, so you only need to call Destroy(), instead of Close(); Destroy().
Removed the LoopbackStream class.
Added a boolean parameter to CanConnect(). This parameter specifies whether or not an announcement stating why the connection couldn't be established should be presented.