Classes for supporting Telescript in Magic Cap have been removed from Rosemary.
In order to be able to display character data in any language, the API of the Magic Cap text framework has changed in Rosemary. Magic Cap supports Unicode characters in the existing text framework; Magic Cap text objects can already contain Unicode character data. However, there are many operations that take ASCII characters or Pascal style strings as parameters. The Rosemary release of Magic Cap no longer supports the use of Pascal style strings as parameter data types. All interfaces that use the String data type have been replaced with interfaces that use text objects. Operations that return text objects will also follow a new convention: if no text needs to be returned, nilObject is returned instead of an empty text object.C literals are still legal; the Rosemary release of Magic Cap will provide versions of the C string library routines, such as strcmp() and printf(), so it will be easier to port code from other platforms to Magic Cap.
Many new operations have been added to make many types of text manipulation easier, including new routines for sorting names, and formatting numbers.
In order to be usable in other countries, Magic Cap needs to be able to display characters in languages other than English. Certain languages have characters that cannot be expressed in 8 bits of data. Since the String data type can only represent 8 bit characters, operations that use String are not useful in these countries.
Communicators will not be limited to displaying character data in one language. For example, it's entirely possible that a Japanese Magic Cap communicator can receive e-mail in another language. The message should be displayed in the language it was composed in, provided that the receiving communicator has the proper fonts to display the contents of the message.
If your package already uses text objects as the interface for character data manipulation, you're already most of the way there and will only have minor changes to make. On the other hand, if you make extensive use of Pascal strings in your package code, you will need to convert your package to use text objects.
Even if you don't plan to localize your package to other languages, users might send data from your package to a communicator that is localized to a different language. The data needs to be stored in a format that can be interpreted by the receiving communicator. For this reason, you should avoid using the String data type for parameters to your class methods.
Text objects are the preferred container for character data. In some instances, character literals will be more appropriate than text objects. For example, using a literal to represent a modem command string is perfectly valid. In these instances, you should use C style, null terminated strings to represent your data. User visible text should be defined as Text objects in your instance definition file, never inline in your code.
Rosemary also contains hot text. This feature recognizes and interprets URLs, e-mail addresses, phone numbers, person names and dates, and offers to do something useful with them when they are tapped. The functionality is implemented by class TextInterpreter.
The MakeComparable() intrinsic is used to normalize text objects so that equality can be assumed and tested for when similarity is meant. This operation returns a new, normalized text object that has been stripped of style information.
Removed the use of the String type from the Magic Cap API. All character data should be passed using Text objects, or instances mixing in with HasText, or at worst, character literals. Replaced these calls with equivalent calls that took Text parameters.
The TextInfo() method has been removed from the API. This routine took an index and returned a string base on that index. Distinct attributes have been added to replace this functionality. TextInfo() used to be declared by class Object and subclasses overrode it to deal with specific indices. Rather than declaring a glut of new attributes in class Object, created the mixin classes HasContent, HasContact and HasAddress and grouped the attributes into these classes. Three attributes remain attributes of class Object: ContentDescription(), DateAsText() and SizeInKBytes().
HasText_CopyTextRangeToBuffer is now an intrinsic operation. Additionally, the <rangeToCopy.length> field will always return the actual number of characters that were copied. This has always been the case, but was never documented. HasText_CopyTextToLiteral and HasText_ComputeTextCRC have also been changed to be intrinsic operations.
Removed the operation TextStyleCoupon_CouponText. The only purspose of this operation was to handle the case where the coupon object didn't have a name.
The operation HasText_MatchText has been removed. Call HasText_ContainsText instead.
Added the new operations HasText_RemoveTextUpToCharacter and HasText_RemoveTextUpToAndIncludingCharacter. The first method deletes any text before the character the is passed in if the character is found. The latter method removes the passed in character as well.
Moved the ReplacedContents() and ReplacingContents() methods from the TextField class to the TextContainer class.
The mixin class HasContent defines the attributes ShortContentDescription() and TypeDescription().
The mixin class HasContact defines the attributes ContactLocation() and ContactPhoneNumber().
The mixin class HasAddress defines the attributes DateReceivedAsText(), ShortDateReceivedAsText(), DateSentAsText(), ShortDateSentAsText(), RecipientName(), SenderName() and SenderOrRecipientName(), and Subject(). In previous releases of Rosemary, Subject() was called SubjectAsText().
The ValueAt() method of list views was similar to TextInfo(). It has been replaced by the CellValue() method to return the value of a given cell. You should use the new placement attributes for TextInfo related uses of ValueAt().
Introduced the operation HasCharacters(). This operation should be called to determine if a text object is empty rather than comparing the text object against nilObject.
The new text API will return ephemeral Text objects. These objects are not long lived; if you need to store a text object, you should call CopyNear() to move the text object into persistent memory. The new text API will also return nilObject rather than an empty Text object. You can use the new method NewTextIfNil() that will create a new ephemeral text object if nilObject was returned from a previous text method.
Auto-getters that return text objects will return ephemeral text objects. Text auto-getters do the equivalent work of:
return CopyText(Field());Text auto-setters will store a copy of the text object that is passed in. They do the equivalent ofDestroy(Field()); SetField(CopyTextNear(text, self));Added class AttributeMappedText. This is a subclass of AttributeText that remaps a text object every time another object changes.
Text mappings work differently in Rosemary to reduce the amount of shadowing that can occur. Callers of MapText() that modify the valueText (by calling ReplaceLine() on the text mapping) should create a transient copy of the text mapping instead of working with the original. TextMapping_MapAndMarkText now nils out the valueText field after mapping the text. This means that you can't set up a text mapping and then use it on multiple objects.
TextMapping_ValueFromIndex now converts sender and receiver from contacts to contact addresses so GivenName() will work. This is a hack that will have a better fix in the future.
Introduced the operation HasText_TruncateText. This routine can be used to shorten a text object to fit a text length limit (not a display width limit). Future versions of this operation will make sure not to separate combining marks from their base characters, so it's a good idea to call this operation instead of truncating in some other way.
Magic Cap 1.5 introduced the feature of one-line text fields that shrunk the font size used in the text field as entered text became too long to fit in the field. Rosemary extends this feature to work with multi-line text fields. In these fields, the size of the font will shrink when the height is too large.
The flags word of classes AttributeText and StructuredField have been split into individual Boolean fields. This makes figuring out which bits to you need to set to get the proper behaviors simpler.
The AttributeType() operation is no longer supported in the new runtime. The class AttributeText has been changed to no longer depend on it. AttributeText objects can no longer point to integer attributes. Use the new attributes SentCountAsText() and ReceivedCountAsText() instead.
The operations DrawWrapped() and DrawClipped() could be used to either draw some text or to measure it. Both operations determined which function to perform based on whether or not the canvas was nilObject. The API of these routines so that there is a distinct boolean parameter that specifies whether the routines should draw or measure instead of relying on an implied meaning of another parameter. The clip and canvas parameters have been removed at any rate for the current canvas and current clip work.
Added the attribute [Set]ModeAlteration() to class TextField. This attribute is used to specify the mode a keyboard will be in when a text field becomes active. This allows TextField subclasses to specify which two modes the mode switch on the keyboard switches between. By default, class TextField allows the keyboard to switch between kDefaultAlphabetMode and kNumbersMode. A subclass of TextField, class KeyboardModeField, overrides ModeAlteration() to tell the keyboard to switch to the mode specified by the keyboardMode field. All this is to work around the fact that there is only one bit available in TextField_fieldFlags to specify the default mode, but international systems might have different default keyboards depending on the text field.
Fixed HasText_InsertLiteral so it can insert more than hundred characters.
Added the operations HasText_AccumulateTextCRC and HasText_ComputeTextCRC which compute the CRC of just the character data in a text object while ignoring referenced objects, such as styles. These operations replace Utilities_HashText and Utilities_TextHash.
Removed support for copyAttribute_Mask in class AttributeText.
Made MainText() and StreetAddress() be attributes instead of pairs of operations.
ColumnTitle() now returns a text object instead of modifying one.
The operations MakeCharacterLowercase() and MakeCharacterUppercase() have been removed because changing case on a per-character basis doesn't always work in some languages. A new intrinsic, HasText_MakeUppercase replaces MakeCharacterUppercase(). This routine that calls the localizable case conversion interface and returns a new text object.
The class CaseConverter defines the API for localizable uppercasing. Magic Cap provides the class SystemCaseConverter with the default implementation. The indexical iDefaultCaseConverter references the default instance of this class. SystemCaseConverter uses a localizable table that defines the uppercase mappings for all characters that are mapped one to one. It may also have a multiline text object describing initial strings that should be uppercased entirely even if the caller only asks for the initial capitals; this handles the Dutch "ij" that is always mapped to "IJ". SystemCaseConverter also handles four precomposed Unicode characters that have different uppercase and titlecase variants.
Renamed the routines CharacterAt(), ReplaceCharacterAt() and DeleteCharacterAt() to xxxCharacterAfter. Other xxxAt methods in Magic Cap are one based and these routines are zero based. This makes the API more consistent.
Hitting the tab key on a card with only one text field set the current typing target to nilObject, but didn't hide the keyboard. Changed SelectNextField() to not change the typing target if there's only one text field and it doesn't have its putAwayKeyboard bit set. This makes hitting the tab key in this situation do nothing, which is the desired behavior.
Fixed a bug where text coupons dropped into size-restyling fields aren't truncated properly.
Added HasText_CopyPlainTextIfStyled. This returns self if the object has no styles, or an ephemeral style-less copy of the text otherwise.
Made HasText_TruncateText properly handle 0 as the maximumCharacters parameter. This now truncates the entire string. Fixed a bug where this method was truncating one too many characters.
Renamed TextWidth() to TextWidthInStyle().
Renamed CompareText() to CompareTextCharacters().
Fixed a bug where incorrect found items were reported when searching for text. Found text was remembered by which text field it was in. Now that forms are copied, if the text field was in a form, that text field might not exist by the time the text is displayed. Text fields are now remembered by index into the form items list rather than by ObjectID. TextSearchResult now stores a form item number instead of whether the text was in card data. This field is zero for non-form items; for form items it is the index in the form items list of the text field.
Removed task specific text mapping cases from TextMapping_ValueFromIndex.
Renamed FindMatchingLine() to FindIdenticalLine() to make it clearer the type of matching that is performed. This name more closely parallels the other matching operation, FindSimilarLine().
Many other operations have been renamed to reflect the fact that they work with Text objects instead of strings.
Old name New name CanonicalASCIIHash ComparableASCIIHash CanonicalCharacterMightMatch ComparableCharacterMightMatch CopyTextRangeTransient CopyTextRange
(now returns an ephemeral)CopyTextTransient CopyText
(now returns an ephemeral)DateText DateAsText DateTextFromDays DateAsTextWithFormat DisplayNameUnflipped DisplayNameForSorting ExtractAreaCode FindNumericPrefix GetFieldDumpString FieldDumpText GetLtWtName LightweightName IntegerToText TextFromSigned
TextFromUnsignedIntToKByteString NumeralFromKBytes IntToBytes TextFromSigned
TextFromUnsignedLine CopyLine MakeCanonical MakeComparable MakeNumberedString NumberedTextFromLiteral MakeSearchString MakeSearchText NumberToStr TextFromSigned
TextFromUnsignedPlayDTMFStr PlayDTMF SearchName SearchName
SearchNameForSortingSetLine ReplaceLine [Set]NameAsText [Set]Name StringEqual IsTextIdentical
IsTextSimilarStringToPhoneKeys MapPhoneKeys StripLeadingWhiteSpace StripLeadingWhitespace StripTrailingWhiteSpace StripTrailingWhitespace
(changed "whiteSpace" to "whitespace" in general)TextFromLiteral NewTextFromLiteral TextFromSigned SignedNumeral TextFromUnsigned Numeral TextToString CopyTextToLiteral ValueString ValueAsText VariableNameToNumber FindVariableByName VariableNumberToString VariableName
Touch(), and its related calls, will sometimes move the responder object into a different cluster, but the calling routine would not know that this happened. Made the methods Viewable_Touch, Viewable_Press, Viewable_MoveTouch, and Movable_MovePress return either self, or the new transplanted self. In addition, the methods Viewable_CopyTouch, Viewable_CopyPress, and Window_DropACopy return the new copy or nilObject if no copy was made for whatever reason.
The object runtime in Magic Cap 1.x uses one namespace for integers, object IDs, class numbers and operation numbers. The shared namespace meant that these numbers could be used interchangeably. An operation could be defined to return an unsigned value, and this value could potentially be any one of the mentioned types. The new runtime model in Rosemary separates these concepts, requiring them to be non interchangeable data types.This separation means that certain values can no longer be used interchangeably. A large amount of code currently uses 0 for nilObject and vice versa. This will no longer be allowed in Rosemary. Rosemary introduces the notions of nilClass and nilOperation for the same reason. The separation of class and operation number namespaces means that dispatching against a class number is distinct from the standard object dispatching mechanism. You can no longer create a method that can be dispatched to by either an object or by a class number; two distinct methods must be declared. Operations that are dispatched to by specifying a class number as the self parameter are declared using the class operation keyword in class definitions.
define class Cluster; inherits from Object; class operation GetCurrent(): Object; operation SetCurrent(): Object, safe, noFail; end class;
The object and instance compilers have been changed to support the namespace separation. This support appears as stricter type checking at compile time. The changes to the object and instance compilers will also affect C code. Method parameter lists are checked against the operation interface defined in class definitions to make sure that they match.New types have been defined to specify these distinct types; you can't use Unsigned to specify an operation number, intrinsic number or class number. Instead use the types OperationNumber, IntrinsicNumber and ClassNumber. Created ClassNumberList, IntrinsicNumberList, ClassOperationNumberList and ClassNumberList to hold lists of these new types of values.
Created new operations [Set]FieldValue() which are parallel to [Set]FieldOf. These operations should be used to read non-object field values.
New operations have been added to support the new data types. Macros to specify a particular cluster, like InLockedSystem() and InSystemTransient() replace the old cluster constants (kLockedSystem, kSystemTransient, etc.) You should use the new macros where you used to use the old constants, like the nearThis parameter to the Near() allocation methods.
Operations that would sometimes return an integer value and at other times return an object have been split into calls that handle a specific data type. For example, Object_Attribute has been replaced with Object_ObjectAttribute and Object_IntegerAttribute.
Callers of IntegerAttribute() that use the result as a short integer need to explicitly cast the result into a short because the new runtime does not automatically clear the high word or sign extended the result.
Existing methods that were dispatched to either by ObjectID or class number have been split into two distinct methods. Added operations ImportClassNumber(), MakeUsableClassNumber(), and MakeStorableClassNumber() to deal with class numbers. These are parallel to Import(), MakeUsable(), and MakeStorable. Methods that were only dispatched to via class numbers are now class operations. Also added MakeUsableClassOperationNumber(), MakeUsableOperationNumber() and MakeUsableIntrinsicNumber().
The names of several operations have been changed to avoid type conflicts. There used to be several classes that used the same method name for operations that really had nothing to do with each other. Some of these operations had return values that are now of different types.
The header files define a little used constant, kStopIterating, which tells iterators to stop. This constant is really an ObjectID, so replaced it with iStopIteratingConstant to keep the namespace boundary clean.
Currently, the Pointer data type in class definition files maps to any pointer type in C code. A side effect of checking method parameters against operation interfaces is that pointer types in class definitions must be distinct for Rosemary.
Stricter type checking by the compiler means that code that used to compile before might now have several compiler errors. Most of these problems can be solved by applying explicit type casts to the parameter.
Pointers are used most extensively for Init() calls, actors and iterators. The class compiler will still know only the basic Pointer data type. This means that the parameter interface of the previously mentioned types of calls should be declared to use a void pointer type, and then have the pointer parameter cast to the specific pointer type inside the routine itself. Instead of doing this:
Method void Actor_Init(ObjectID self, NewActorParameters *params)Do this:
Method void Actor_Init(ObjectID self, const void *castThis) { const NewActorParameters *params = (const NewActorParameters *) castThis; }Because of the strict parameter passing and function resulrules, prototypes for functions that dispatch an operation must match the prototype of the operation that is going to be called. This means that OperationByNumber() would only work on operations that take an integer parameter and return an integer result. Because OperationByNumber() is used for many operations that take a parameter or return a result that is other than an interger, several new versions of OperationByNumber() have been created. Be sure that you use the correct version. The new versions are OperationByNumberPassBoolean(), OperationByNumberPassShort(), OperationByNumberPassInteger(), OperationByNumberPassObject(), OperationByNumberReturnBoolean(), OperationByNumberReturnShort(), OperationByNumberReturnInteger(), and OperationByNumberReturnObject().
Because PerformConfirmationFancy() calls OperationByNumber() when the user confirms a window, new variants of this method, as well as the ConfirmationDialog class have been created. Created subclasses of ConfirmationDialog that hold a boolean or object parameter when the user confirms the window. ConfirmationDialog should be used when no parameter should be passed when the user confirms the window. ConfirmationDialogBoolean should be used when a boolean parameter is passed when the user confirms the window. ConfirmationDialogObject should be used when an object parameter is passed when the user confirms the window. New versions of PerformWithConfirmationFancy() have been created to be able to pass the different parameter types. You need to make sure that the class of the ConfirmationDialog object passed to a PerformWithConfirmationFancy() variant matches the parameter type. You should dispatch against a ConfirmationDialog when calling PerformWithConfirmationFancy(), a ConfirmationDialogBoolean when calling PerformWithConfirmationFancyPassBoolean(), and a ConfirmationDialogObject when calling PerformWithConfirmationFancyPassObject().
IntegerAttribute() and SetIntegerAttribute() call OperationByNumber() so they needed to be updated as well. New versions, ShortAttribute(), SetShortAttribute(), BooleanAttribute() and SetBooleanAttribute() have been added.
AttributeStemp called IntegerAttribute() which means it didn't workj for attributes that were booleans. AttributeStamp is now an abstract superclass that has new concrete subclasses BooleanAttributeStamp and IntegerAttributeStamp.
The BeginReadFields() and BeginModifyFields() family of calls now return typed pointers instead of void * and const void *.