# =========== Header =========== # File: Dictionary Parts # Project: Newton Bowels # Written by: Paul Guyot (pguyot@kallisys.net) # # Created on: 12/06/2000 # Internal version: 1 # # Copyright: © 2000 by Paul Guyot. # All rights reserved worldwide. # =========== # =========== Change History =========== # 12/06/2000 v1 [PG] Creation of the file # =========== Introduction ============ In Table 1 of BitParts by Michael S. Engber, one can see that there are dictionary parts of type 'dict'. Later one can read: "Dictionary parts provide a way for you to provide custom dictionaries. Currently dictionaries of your own creation must reside in the NewtonScript heap. Dictionary parts will allow the dictionary data to remain in your package." In Newton Toolkit UserGuide, one can read: "You can use NTK to create parts of any type, including dictionary parts and font parts, by choosing Custom in Output Settings and entering a four-character type code in the type field." However nowhere is it explained how to build the dictionary. This notes explains how to do so and discusses the other methods to enable custom dictionaries. Dictionary Parts Structure ========================== A dictionary part can include several dictionaries. The output frame should be like this: output := { dictionaries: { dictionaryList: [ { name: kDictName, // Unicode String dict: kDictData, // Dictionary Binary domainType: kDictDomain, // Domain Code // Other slots to override the dictionary prototype } ] }, }; The Domain code defines where the dictionary should be used. It is encoded like the flags for recognition. Therefore, a good value for a word list is vCharsAllowed | vNameField | vAddressField = 0x00601000. Cf Newton Programmer's Reference, p. 8-8. Differences with other methods ============================== As Michal S. Engber put it, the interest of dictionary parts is that the dictionary doesn't use any heap, the data is not loaded in memory. This possibility hasn't been totally debugged as the system sends a string to the inspector when the dictionary is activated (this is only visible to users who install the dictionary when connected to the inspector). There is an official method to handle custom dictionaries. It consist in creating a new dictionary with the NewDictionary function, then to set its data with SetDictionaryData. There are two problems with this method: - creating a dictionary with NewDictionary creates a dictionary with a status slot of zero (which means the dictionary is not available widely but only in views that explicitly refer to it) and then registers it. - the data is loaded in System Heap. This is not visible immediatly since there are not a lot of utilities that track the System Heap usage. But with large dictionaries it is a problem. This official method can be improved in two ways: - to enable the dictionary as a system dictionary, one of the method is to register it ourself by creating a dictionary frame based on the dictionary proto, then initializing it and registering it. local theDict := { _proto: @171, // Dictionary proto name: kDictName, domainType: kDictDomain // other custom slots }; theDict:Initialize(15,1); // These are the default values for a word list theDict.status := 1; local int theDictID := theDict:Register(); Initialize parameters are apparently first the type (15 for enumerated dictionary) then the attribute size (usually 1). - to set the data by referencing to the dictionary data in the package instead of loading it. This can be done with some C++ code modifying the dictionary record in memory. The dictionary frame has a special slot telling where the dictionary record is. It is the dict slot. It is an integer that should be multiplied by four. It is a handle to a SDictInfo structure. typedef struct SDictInfo { long unknownLong01; // usually 0x00028D78 long dictID; long** dataHandle; // points to the dictionary data, i.e. what you // get with GetDictionaryData long* unknownPtr04; // very probably an address long* unknownPtr05; // idem // very strangely: // unknownPtr05 - unknownPtr04 = dataSize // unknownPtr04 is in the data ptr, it is sometimes equal to it // unknownPtr05 is outside when unknownPtr04 > (*dataHandle) // the data ptr is just dataSize long everytime. long dataSize; long unknownLong07; // usually 0x00000064 long* unknownPtr08; // usually 0x0C105AF4 long unknownLong09; long unknownLong10; long unknownLong11; long unknownLong12; long unknownLong13; long unknownLong14; long unknownLong15; long unknownLong16; SDictInfo** dictInfoHdl; // handle to *this* dictionary info. long unknownLong18; long unknownLong19; long unknownLong20; long unknownLong21; long unknownLong22; }; MacOS archive ============= The archive comes with the source for DictLib, some code to handle dictionaries records and to set the dictionary data. It also includes the source for DictFr which uses the dictionary part method. Notes ===== Michal S. Engber, Bit Parts, PIE Developers May 1994 can be found at: ftp://ftp.apple.com/developer/Newton_Development/articles/BitParts.rtf.txt ## ====================================================================== ## ## THE LESSER-KNOWN PROGRAMMING LANGUAGES #18: FIFTH ## ## ## ## FIFTH is a precision mathematical language in which the data types ## ## refer to quantity. The data types range from CC, OUNCE, SHOT, and ## ## JIGGER to FIFTH (hence the name of the language), LITER, MAGNUM and ## ## BLOTTO. Commands refer to ingredients such as CHABLIS, CHARDONNAY, ## ## CABERNET, GIN, VERMOUTH, VODKA, SCOTCH, and WHATEVERSAROUND. ## ## ## ## The many versions of the FIFTH language reflect the sophistication and ## ## financial status of its users. Commands in the ELITE dialect include ## ## VSOP and LAFITE, while commands in the GUTTER dialect include HOOTCH ## ## and RIPPLE. The latter is a favorite of frustrated FORTH programmers ## ## who end up using this language. ## ## ====================================================================== ##