text:
Copyright (c) 2012-2016 Hyperion Entertainment and contributors.
Difference between revisions of "Datatypes Library"
Steven Solie (Talk | contribs)
(→A Simple Datatypes Example)
Steven Solie (Talk | contribs)
(→Defining a DataType Descriptor)
|Line 1,712:
|Line 1,712:
4. The remaining fields must be filled out. Following is a table describing the fields and the information they require.
4. The remaining fields must be filled out. Following is a table describing the fields and the information they require.
{| class="wikitable"
{| class="wikitable"
! Name !! Description
! Name !! Description
Revision as of 23:06, 3 June 2013
- 1 Introduction to the Datatypes Library
- 2 Why Use the Datatypes Library?
- 3 Classes, Objects and Methods
- 4 Datatypes Class Attributes
- 5 Basic Functions of the Datatypes Library
- 6 Basic Structures of the Datatypes Library
- 7 Creating a DataType Object
- 8 Obtaining Environment Information for a DataType
- 9 Adding a DataType Object to a Window
- 10 Removing a DataType Object from a Window
- 11 Setting an Existing DataType Object's Attributes
- 12 Getting a DataType Object's Attributes
- 13 A Simple Datatypes Example
- 14 Embedding DataTypes
- 15 Determining Data Type
- 16 A Picture Class Example
- 17 Writing A Sub-Class
- 18 Defining a DataType Descriptor
Introduction to the Datatypes Library
The purpose of the datatypes library is to provide software tools for handling data in an object-oriented way. The object-oriented approach means that your application can work with numerous data file standards without having to worry about the complex details of each one. Instead you need only understand the simple conventions of the datatypes library.
The datatypes library is built on Intuition's BOOPSI facility (BOOPSI is an acronym for Basic Object-Oriented Programming System for Intuition). Although not required, it is very helpful to know a little about how BOOPSI works before trying to use the datatypes library. For information on BOOPSI, refer to BOOPSI. Some familiarity with object-oriented theory and practice is also helpful, though not required.
Since the datatypes library uses the TagItem structure for passing parameters to functions, you will have to understand how TagItems work before you can call the functions in the datatypes library. For more information on TagItems refer to the Utility Library.
Why Use the Datatypes Library?
One practical benefit of the datatypes library is that it allows you to quickly add support for IFF data files (this article will show you how). However, the goals of the datatypes library are much more ambitious than that. Here's a summary:
- Consistent, simple handling of multiple data standards - Most of the details of dealing with the various data standards are hidden. Once you have learned how to handle one type of data with the datatypes library, you will find that the other types are handled in much the same way.
- Extensible - You can add your own types of data objects to those already supported by the datatypes library. Datatypes has functions that allow other applications to find out about and work with your data object, without having to understand the internal details of the data.
- Automatic support of IFF and clipboard - The initial version of the datatypes library (V39) provides support for 8SVX sound data and ILBM graphic data. These are the two most widely used data file standards on the Amiga. Developers who want to support these IFF standards no longer have to become IFF experts. Similarly, the datatypes library provides a consistent and easy-to-use interface to the Amiga's clipboard device to encourage data sharing between applications.
- Intuition gadget support - Because the datatypes library is implemented with BOOPSI, the data objects it handles can also be treated as gadgets. Gadget operations can be performed on data objects within Intuition's task context, the same as other BOOPSI gadgets.
- Automatic conversion from one format to another - Future versions of the datatypes library will support other types of data objects. Conversion from one format to another will be automatically handled by the library.
- Validation - Datatypes lets you easily check if a given file is a valid instance of one of the data objects it supports. For example, you can check to see if a file is a valid ILBM or not.
Classes, Objects and Methods
The jargon used to describe the datatypes library may be a little confusing if you have never worked with object-oriented systems before. For instance, the kinds of data supported by the library are divided into classes and sub-classes. The term class is used here in a familiar way; the members of a class simply have a common set of properties. The members of a sub-class have all the properties of the parent class and additional properties specific to the sub-class. (Each sub-class could be further broken down into sub-sub-classes and so on.)
|Has hooves, can run.
|Has udder, can be milked (also has hooves and can run).
|An instance of class Cow; can run and can be milked.
An actual instance of a class or sub-class is referred to as an object. The term object is appropriate because in general we want to ignore the details of each individual case and concentrate instead on what we can do with an object based on its class. In the example above the Daisy object can run and can be milked. The operations that can be performed with an object are referred to as methods and the object is said to inherit the methods and other attributes of its parent class (which in turn inherits the methods and attributes of its parent class, if it has one).
The datatypes.library implements datatypesclass from which all other datatype classes inherit from. The following BOOPSI class diagram illustrates how the various datatypes classes relate to each other.
|Object Classes
|Autodoc File Showing the Methods Supported
|Type of Data Object
|Picture class
|IFF graphic image file
|Sound class
|IFF audio sample file
|Text class
|ASCII characters
|AmigaGuide class
|Hypertext databases
|Animation class
|Animations containing graphics and sound
The examples programs listed below demonstrate how to perform some basic methods on ILBM and 8SVX class objects.
Datatypes Class Attributes
Datatype library classes have other attributes in addition to the methods (operations) that they support. For each attribute, there is a corresponding TagItem defined in the datatypes library that you can use to examine or set that attribute in a particular object
For example, picture objects have a display mode attribute. The tag that controls this attribute is named PDTA_ModeID and is described in the Autodoc file picture_dtc.doc. See the Autodoc files for each class (as shown in Table 1) for a complete list of all class attributes.
The class attribute descriptions in the include files also have a set of codes that indicate the applicability of the attribute. The codes are as follows:
|I - Initialize
|You can initialize the attribute when the object is created
|S - Set
|You can set the attribute to a new value after the object is created
|G - Get
|You can get the value of the attribute after the object is created
|N - Notify
|Changing the attribute triggers the object to send notification
|U - Update
|Attribute can be set using the object's OM_UPDATE method
These codes may seem a little mysterious until you have actually tried using the datatypes library. The N and U codes in particular are for special applications that want to implement their own object classes, an advanced topic beyond the scope of this article.
Basic Functions of the Datatypes Library
If all these new concepts seem a little daunting, rest assured; the datatypes library uses conventional C language function calls to get the job done. The calls you will be using most often are listed below. Notice that for each of these basic functions of datatypes library there is an equivalent BOOPSI call in the Intuition Library.
|Create a datatype object in memory from a file or clip
|Free an object created earlier with NewDTObject() (or NewObject() )
|Get attributes of a datatype object
|Set attributes for a datatype object
|Perform the given method (operation) with a datatype object
There are also additional functions used to access DataType objects.
|Function Name
|Add a DataType object to a window.
|Refresh the rendering of a DataType object.
|Remove a DataType object from a window.
|Get a list of the methods that a DataTypes object supports. Write, Copy, and Select are examples of methods that an object may support.
|Get a list of the trigger methods that a DataType object supports. An action like Play, Pause, and Resume are examples of trigger methods that an object may support.
|Asynchronously print a DataType object.
|Get the localized text string for a DataTypes text id. Useful for obtaining localized error messages.
In a typical application the sequence of calls might be performed like this:
- Use NewDTObject() to create an object in memory from given data.
- Get (or perhaps set) attributes of the object using GetDTAttr() (or SetDTAttrs() ).
- Perform methods (operations) with the object using DoDTMethod().
- Free the object and any memory or other resources it was using with the DisposeDTObject() call.
Basic Structures of the Datatypes Library
There are a lot of structures used with datatypes library function calls; too many to summarize in this article. However, here's a listing of the relevant include files that contain the structure definitions of interest to class users.
|Group IDs, error numbers plus library overhead
|Defines datatype methods and associated structures
|Structures specific to the picture class
|Structures specific to the sound class
|Structures specific to the text class
|Structures and methods for AmigaGuide databases
|Defines general BOOPSI object methods
|Defines gadget methods and associated structures
The two most important definitions in these include files appear in <intuition/classusr.h>. The objects used with datatypes library functions (and the BOOPSI functions in Intuition) are defined as follows:
typedef ULONG Object; /* abstract handle */
Since we want to treat objects as black boxes and don't really care how they are implemented, this definition is very appropriate. When a method is performed with an object, the parameter used to identify the method is a Msg structure defined as follows:
typedef struct { ULONG MethodID; /* method-specific data goes here */ } *Msg;
Some methods require more information than just the method identifier. Such methods have a custom structure defined in the include files. All method structures, however, begin with a field that contains the method ID.
Creating a DataType Object
The DataTypes function NewDTObjectA() must be used to create a new DataType object.
Object *dto = IDataTypes->NewDTObjectA (APTR name, struct TagItem *attrs);
The pointer that NewDTObjectA() returns is a pointer to a BOOPSI object. Like other BOOPSI objects, DataType objects are "black boxes" and are not to be peeked and poked without using the provided interface.
To create a DataType object, NewDTObjectA() needs to know the where to obtain the data used to create the object. By default the name is treated as file name.
The attrs tag list is a list of tag/value pairs, each of which contains an initial value for an attribute. There are a number of attributes defined in <datatypes/datatypesclass.h> that can be used at creation time.
- DTA_SourceType
- Specify the type of the source data. The default is DTST_FILE.
DTST_RAM Source data is in RAM. DTST_FILE Source data is a file. Name is the name of the file. DTST_CLIPBOARD Source data is in the clipboard. Name is the unit number. For example, (APTR)0, for clipboard unit zero. DTST_HOTLINK Reserved for future use.
- DTA_Handle
- Can be used instead of the name field. If the source type is DTST_FILE then handle must be a valid BPTR file handle. If the source type is DTST_CLIPBOARD then handle must be a valid IFFHandle.
- DTA_DataType
- Can be used to specify the class for handling the data. Data must be a pointer to a valid DataType. This should only be used when attempting to create a new object that doesn't have source data, or could be handled by multiple classes (for example, could be used to force an object to be handled by the AmigaGuide class).
- DTA_GroupID
- If this tag is present, then the data must be of the specified type, or the object creation will fail with ERROR_OBJECT_WRONG_TYPE. This can be used by a Sound editor to ensure that only sounds can be loaded, for example.
There are additional attributes that can specified at creation time, but are dependant on the data type of the object being created. See the header files <datatypes/#?class.h> for more attributes.
The following attributes, which are defined in <intuition/gadgetclass.h>, are also valid.
|Specify the left edge of the gadget.
|Specify the left edge of the gadget being relative to the right edge of the containing window.
|Specify the top edge of the gadget.
|Specify the top edge of the gadget being relative to the bottom edge of the containing window.
|Specify the width of the gadget.
|Specify the width of the gadget being relative to the width of the containing window.
|Specify the heigh of the gadget.
|Specify the heigh of the gadget being relative to the height of the containing window.
|Specify a ID associated with the gadget.
|Attach application data to the gadget.
|Indicate that the application should be notified of gadget down events for this gadget.
|Indicate that the application should be notified of gadget up events for this gadget.
|For adding the gadget to a list of gadgets.
|A pointer to a struct DrawInfo.
In order for the application to receive information from the DataType object, it must set up a target for the notification attributes that the object sends out.
- Specify a target for the notification attributes that the DataType object sends out.
- Specify an attribute mapping for the notification attributes that the DataType object sends out.
The usual method to obtain notification is to set up an ICA_TARGET of ICTARGET_IDCMP so that the application will receive the attributes via the IDCMP_IDCMPUPDATE Intuition message class. But it is also possible to set up another BOOPSI object as the receiver.
If NewDTObjectA() is successful, it returns a pointer to a DataType object. Otherwise it returns NULL and the reason for failure can be obtained using IoErr(). See the Autodocs for datatypes.library for more information.
Obtaining Environment Information for a DataType
In order to embed a DataType object in a window, it is neccessary to ask the object what its minimum environment is. For example, since the remap code doesn't handle remapping HAM pictures, they must be shown on a HAM screen, and therefore can't be added to a window that is on a non-HAM screen.
ULONG modeid = INVALID_ID; LONG nomwidth, nomheight; BOOL useScreen = FALSE; struct dtFrameBox dtf; struct FrameInfo fri; /* Get the attributes that we are interested in */ IDataTypes->GetDTAttrs(dto, /* Get the mode ID */ PDTA_ModeID, &modeid, /* Get the desired size */ DTA_NominalHoriz, &nomwidth, DTA_NominalVert, &nomheight, TAG_END); /* Clear the structures */ IUtility->ClearMem(&dtf, sizeof (struct dtFrameBox)); IUtility->ClearMem(&fri, sizeof (struct FrameInfo)); /* Fill in the message */ dtf.MethodID = DTM_FRAMEBOX; dtf.dtf_FrameInfo = &fri; dtf.dtf_ContentsInfo = &fri; dtf.dtf_SizeFrameInfo = sizeof (struct FrameInfo); /* Perform the frame method */ if (IDataTypes->DoDTMethodA (dto, NULL, NULL, (Msg) &dtf)) { /* Check to see if the object requires a HAM screen */ if (fri.fri_PropertyFlags & DIPF_IS_HAM) { IDOS->Printf ("HAM\n"); useScreen = TRUE; } /* Check to see if the object requires an ExtraHalfBrite screen */ else if (fri.fri_PropertyFlags & DIPF_IS_EXTRAHALFBRITE) { IDOS->Printf ("ExtraHalfBrite\n"); useScreen = TRUE; } /* A safety check to see if a screen is required */ else if ((fri.fri_PropertyFlags == 0) && (modeid & 0x800) && (modeid != INVALID_ID)) { IDOS->Printf ("ModeID=0x%08lx\n", modeid); useScreen = TRUE; } } else { /* No special environment required, can be attached to any screen mode */ }
Adding a DataType Object to a Window
A DataType object must be added to a window using the AddDTObject() function of DataTypes.
LONG AddDTObject (struct Window *w, struct Requester *r, Object *dto, LONG pos)
This function will add a DataTypes object to the existing gadget list for the specified window. The recommended value for pos is -1 which will cause the DataType object to be added to the end of the list.
DataType objects should not be added using the WA_Gadgets attribute to OpenWindowTagList() or by using the AddGList() function. There is special information that DataTypes requires that will not obtained if any method other than AddDTObject() is used.
When the DataType object is added to the window, the layout method for the object will be invoked. It is possible that the layout will take a while to perform, in that case the object will spawn a process to handle the layout asynchronously. In order to refresh the object's visual information, it is necessary to obtain IDCMP_IDCMPUPDATE messages from the object and refresh the object when a DTA_Sync attribute is received.
The following code fragment illustrates adding a DataType object to a window.
Object *dto; struct IntuiMessage *imsg; struct Window *win; ULONG sigr; struct TagItem *tstate, *tags; ULONG tidata; ULONG errnum; BOOL going = TRUE; /* Set the pertinent attributes of the DataType object */ IDataTypes->SetDTAttrs (dto, NULL, NULL, /* Set the dimensions of the object */ GA_Left, win->BorderLeft, GA_Top, win->BorderTop, GA_Width, win->Width - win->BorderLeft - win->BorderRight, GA_Height, win->Height - win->BorderTop - win->BorderBottom, /* Make sure we receive IDCMP_IDCMPUPDATE messages from * the object */ ICA_TARGET, ICTARGET_IDCMP, TAG_END); /* Add the object to the window */ IDataTypes->AddDTObject (win, NULL, dto, -1); /* Refresh the DataType object */ IDataTypes->RefreshDTObjects (dto, win, NULL, NULL); /* Keep going until we're told to stop */ while (going) { /* Wait for an event */ sigr = IExec->Wait ((1L << win->UserPort->mp_SigBit) | SIGBREAKF_CTRL_C); /* Did we get a break signal */ if (sigr & SIGBREAKF_CTRL_C) going = FALSE; /* Pull Intuition messages */ while (imsg = (struct IntuiMessage *) IExec->GetMsg (win->UserPort)) { /* Handle each message */ switch (imsg->Class) { case IDCMP_IDCMPUPDATE: /* Get a pointer to the attribute list */ tstate = tags = (struct TagItem *) imsg->IAddress; /* Step through the attribute list */ while (tag = IUtility->NextTagItem (&tstate)) { tidata = tag->ti_Data; switch (tag->ti_Tag) { /* Change in busy state */ case DTA_Busy: if (tidata) IIntuition->SetWindowPointer (win, WA_BusyPointer, TRUE, TAG_END); else IIntuition->SetWindowPointer (win, WA_Pointer, NULL, TAG_END); break; /* Error message */ case DTA_ErrorLevel: if (tidata) { errnum = IUtility->GetTagData (DTA_ErrorNumber, NULL, tags); IDOS->PrintErrorMsg (errnum, (STRPTR) options[OPT_NAME]); } break; /* Time to refresh */ case DTA_Sync: /* Refresh the DataType object */ IDataTypes->RefreshDTObjects (dto, win, NULL, NULL); break; } } break; } /* Done with the message, so reply to it */ IExec->ReplyMsg ((struct Message *) imsg); } }
Removing a DataType Object from a Window
A DataType object must be removed from the window using the RemoveDTObject() function.
LONG RemoveDTObject (struct Window *w, Object *dto)
This function removes the DataType object from the window's gadget list.
This is the only way that a DataType object should be removed from the window list. Using RemoveGList() is not supported, nor is removing the object manually.
Setting an Existing DataType Object's Attributes
An objects attributes are not necessarily static. An application can ask an object to set certain attributes using the SetDTAttrs() function.
ULONG SetDTAttrsA (Object *dto, struct Window *w, struct Requester *r, struct TagItem *attrs)
The return value is DataType object specific, but generally a non-zero value means that the object needs to be visually refreshed.
The following fragment illustrates how to set the current top values for a DataType object, using the VarArgs version of SetDTAttrsA().
IDataTypes->SetDTAttrs(dto, window, NULL, DTA_TopVert, 0, DTA_TopHoriz, 0, TAG_END);
This will cause the DataType object to update its vertical and horizontal top values. If the object has been added to a window, then the display will be updated accordingly.
Note that it is not OK to call SetGadgetAttrs() or SetAttrs() on a DataType object.
Getting a DataType Object's Attributes
The DataTypes function GetDTAttrsA() is used to obtain the values for a list of attributes from a DataType object.
ULONG GetDTAttrsA (Object *dto, struct TagItem *attrs)
Where dto is a pointer to a DataType object returned by NewDTObjectA().
And attrs is a TAG_END terminated array of attributes. Where the data element of each pair contains the address of the storage variable for that attribute.
This function will return a number that indicates that number of attributes that it was able to obtain. For example if four attributes asked for and GetDTAttrs returns a four, then all the attributes were obtained.
The following code fragment illustrates how to get the current top values for a DataTypes object using the VarArgs form of GetDTAttrsA().
LONG topv, toph; if (IDataTypes->GetDTAttrs (dto, DTA_TopVert, &topv, DTA_TopHoriz, &toph, TAG_END) == 2) { IDOS->Printf ("Top: vertical=%ld, horizontal=%ld\n", topv, toph); } else { IDOS->Printf ("couldn't obtain the top values\n"); }
A Simple Datatypes Example
The example program listed here should clarify some of the concepts discussed so far. Suppose you have a communications program and want to add the capability of playing back a user-specified 8SVX sample file for the bell sound (Ctrl-G). The program below shows how to play a sound with the datatypes library.
In this program, objects are of class 8SVX (a sub-class of the sound datatype). The method performed with the object is named DTM_TRIGGER (described in the Autodoc file sound_dtc.doc). The DTM_TRIGGER method (with type set to STM_PLAY) causes a sampled sound to be played on the Amiga's audio hardware. Since the DTM_TRIGGER method requires other information in addition to the method ID, a dtTrigger structure is used. This structure is defined in <datatypes/datatypesclass.h>.
Note that if the sound datatype is enhanced to support other types of sound files in a future version of the Amiga OS, the code given here will automatically support the new type. This example expects the file name and path to a sound file.
/* Run from CLI only. */ #include <exec/types.h> #include <datatypes/datatypesclass.h> /* This includes other files we need */ #include <proto/exec.h> /* Prototypes for system functions */ #include <proto/intuition.h> #include <proto/datatypes.h> #include <proto/dos.h struct IntuitionIFace *IIntuition = NULL; struct DataTypesIFace *IDataTypes = NULL; int main(int argc, char **argv) { APTR dtobject = NULL /* Pointer to a datatypes object */ struct dtTrigger mydtt; /* A trigger structure for the DTM_TRIGGER method */ if(argc <= 1 ) /* CLI only, at least one argument please. */ { IDOS->Printf("Give a file name too.\n"); return RETURN_FAIL; } struct Library *IntuitionBase = IExec->OpenLibrary("intuition.library", 50); IIntuition = (struct IntuitionIFace*)IExec->GetInterface(IntuitionBase, "main", 1, NULL); struct Library *DataTypesBase = IExec->OpenLibrary("datatypes.library", 50); IDataTypes = (struct DataTypesIFace*)IExec->GetInterface(DataTypesBase, "main", 1, NULL); if (IIntuition != NULL && IDataTypes != NULL) { /* Attempt to make an 8svx sound object from the file name the user */ /* specified in the command line. For a list of possible error */ /* returns, see the Autodocs for NewDTObjectA(). The group ID tag */ /* will allow only sound datatype files to be accepted for the call.*/ if (dtobject = IDataTypes->NewDTObject(argv[1], DTA_GroupID, GID_SOUND, TAG_END) ) { mydtt.MethodID = DTM_TRIGGER; /* Fill in the dtTrigger struct */ mydtt.dtt_GInfo = NULL; mydtt.dtt_Function = STM_PLAY; mydtt.dtt_Data = NULL; /* The return value of the DTM_TRIGGER method used with the 8svx */ /* sound datatype is undefined in V39. This is likely to change */ /* in future versions of the Amiga operating system. */ uint32 dores = IDataTypes->DoDTMethodA(dtobject, NULL, NULL, &mydtt); /* Let the 8svx sound finish playing. Currently there is */ /* no programmatic way to find out when it is finished playing. */ IExec->Wait(SIGBREAKF_CTRL_C); IDataTypes->DisposeDTObject(dtobject); } else IDOS->Printf("Couldn't create new object or not a sound data file\n"); } else IDOS->Printf("Can't open interfaces\n"); IExec->DropInterface((struct Interface*)IDataTypes); IExec->CloseLibrary(DataTypesBase); IExec->DropInterface((struct Interface*)IIntuition); IExec->CloseLibrary(IntuitionBase); return 0; }
In addition to playing back a sampled sound, the datatypes library allows sound objects to become gadgets (the library includes default imagery for a sound gadget). Since all datatypes object classes are implemented as a sub-class of the BOOPSI gadget class, they all support the methods of gadget objects as described in the BOOPSI chapter of the Libraries manual.
Embedding DataTypes
Since DataType objects are a sub-class of the Intuition Gadget class, DataType objects can be attached to an Intuition window in a similiar way that gadgets can be added to a window. DataTypes use a parallel set of functions because it requires additional information that the Intuition functions weren't able to provide.
Currently the handling of the data is limited to reading, writing, printing, viewing (audio or visual), and clipboard access. The MultiView utility is an example of an application that embeds DataType objects.
Determining Data Type
One of the main features of the DataTypes system is its ability to determine the data type of a block of data. This data block can reside in a file or the clipboard.
The following functions are used to determine the DataType of a data block:
|Obtain the DataType descriptor for a data block.
|Release the DataType descriptor for a data block.
The data type detection functions use the DataType structure.
struct DataType { struct Node dtn_Node1; struct Node dtn_Node2; struct DataTypeHeader *dtn_Header; struct List dtn_ToolList; STRPTR dtn_FunctionName; struct TagItem *dtn_AttrList; ULONG dtn_Length; };
The DataType structure is read-only. The only pertinent field is the dtn_Header field, which points to a DataTypeHeader structure.
struct DataTypeHeader { STRPTR dth_Name; STRPTR dth_BaseName; STRPTR dth_Pattern; WORD *dth_Mask; ULONG dth_GroupID; ULONG dth_ID; WORD dth_MaskLen; WORD dth_Pad; UWORD dth_Flags; WORD dth_Priority; };
The DataTypeHeader structure fields are as follows:
- dth_Name
- Descriptive name of the data type. For example, the description for an ILBM data type could possibly be "Amiga BitMap Picture".
- dth_BaseName
- This is the base name for the data type and is used to obtain the class that handles this data type.
- dth_GroupID
- This indicates the main type data that the object contains. Following are the possible values:
GID_SYSTEM Fonts, Executables, Libraries, Devices, etc... GID_TEXT Formatted or unformatted text. GID_DOCUMENT Formatted text with embedded DataTypes (such as pictures). GID_SOUND Audio samples. GID_INSTRUMENT Audio samples used for playing music. GID_MUSIC Musical scores. GID_PICTURE Graphic picture or brush. GID_ANIMATION Moving picture or cartoon. GID_MOVIE Moving picture or cartoon with sound.
- dth_ID
- This is an individual indentifier for the DataType. For IFF files it is the same as the FORM type, for example ILBM for an Amiga BitMap picture. For non-IFF files, it is the first four characters of dth_Name.
- dth_Flags
- The flags field contains, among other information, the coarse type of data. The type can be obtained by ANDing DTF_TYPE_MASK with this field.
DTF_IFF Interchange File Format DTF_BINARY Non-readable characters DTF_ASCII Readable characters DTF_MISC Disks and drawers
- dth_Pattern
- dth_Mask
- dth_MaskLen
- dth_Priority
- These fields are used by the detection code in datatypes.library for determining the data type. See the "Defining a DataType Descriptor" section for more information.
Following is a code fragment that shows how to determine the data type of a file. This fragment uses functions from datatypes.library, dos.library, and iffparse.library.
STRPTR name = "somefilename"; BPTR lock; struct DataTypeHeader *dth; struct DataType *dtn; UBYTE idesc[5]; STRPTR tdesc; STRPTR gdesc; UWORD ttype; /* Obtain a lock on the file that we want information on */ if (lock = IDOS->Lock (name, ACCESS_READ)) { /* Get a pointer to the appropriate DataType structure */ if (dtn = IDataTypes->ObtainDataTypeA (DTST_FILE, (APTR)lock, NULL)) { /* Get a pointer to the DataTypeHeader structure */ dth = dtn->dtn_Header; /* Get the coarse type */ ttype = dth->dth_Flags & DTF_TYPE_MASK; /* Get a pointer to the text strings */ tdesc = IDataTypes->GetDTString (ttype + DTMSG_TYPE_OFFSET); gdesc = IDataTypes->GetDTString (dth->dth_GroupID); /* Convert the ID to a string. */ IIFFParse->IDtoStr (dth->dth_ID, idesc); /* Display the information */ IDOS->Printf (" Description: %s\n", dth->dth_Name); IDOS->Printf (" Base Name: %s\n", dth->dth_BaseName); IDOS->Printf (" Type: %d - %s\n", ttype, tdesc); IDOS->Printf (" Group: %s\n", gdesc); IDOS->Printf (" ID: %s\n", idesc); /* Release the DataType structure now that we are done with it */ IDataTypes->ReleaseDataType (dtn); } /* Release the DOS lock on the file */ IDOS->UnLock (lock); }
A Picture Class Example
Here is a second, more complex example showing how to use all the datatypes library functions described so far. In this example, the objects used are of class ILBM, a sub-class of picture.
Two methods will be performed with the object, DTM_PROCLAYOUT and DTM_FRAMEBOX. Both these methods have associated structures (gpLayout and dtFrameBox respectively). DTM_PROCLAYOUT makes the object available within the context of your application task (as opposed to Intuition's). DTM_FRAMEBOX queries the display environment required by the picture.
Other attributes of the picture are obtained with a call to GetDTAttrs() and then a matching Intuition screen is created and the ILBM object is displayed. This example expects the file and path name of a picture file.
; /* Compiled with SAS/C 6.56. Run from CLI only. sc DATA=NEAR NMINC STRMERGE NOSTKCHK IGNORE=73 dtpic.c slink from lib:c.o dtpic.o TO dtpic LIBRARY lib:sc.lib lib:amiga.lib quit ; */ #include <exec/types.h> #include <datatypes/datatypes.h> /* Datatypes definitions we need */ #include <datatypes/pictureclass.h> #include <stdio.h> #include <clib/exec_protos.h> /* Prototypes for system functions */ #include <clib/intuition_protos.h> #include <clib/alib_protos.h> #include <clib/datatypes_protos.h> #include <clib/graphics_protos.h> #ifdef LATTICE int CXBRK(void) { return(0); } /* Disable SAS/C CTRL-C handling */ int chkabort(void) { return(0); } #endif struct Library *IntuitionBase=NULL; /* System library bases */ struct Library *GfxBase=NULL; struct Library *DataTypesBase=NULL; VOID main(int argc, char **argv) { APTR dtobject=NULL; /* Pointer to a datatypes object */ ULONG res; /* Variable for function return values */ struct dtFrameBox mydtFrameBox; /* Use this with DTM_FRAMEBOX method */ struct FrameInfo myFrameInfo; /* For info returned from DTM_FRAMEBOX */ struct gpLayout mygpLayout; /* Use this with DTM_PROCLAYOUT method */ ULONG modeID = INVALID_ID; /* Variables for storing the display */ struct Screen *myScreen=NULL; /* environment information obtained */ struct BitMap *bm = NULL; /* the datatype object. */ ULONG *cregs = NULL; ULONG i,r,g,b,numcolors; if (IntuitionBase=OpenLibrary("intuition.library",39L)) { if (GfxBase=OpenLibrary("graphics.library",39L)) { if(DataTypesBase=OpenLibrary("datatypes.library",0L)) { if(argc > 1 ) /* CLI only, at least one argument please. */ { /* Attempt to create a picture object in memory from the file */ /* name given by the user in the command line. If we wanted to */ /* show the picture in a screen set up ahead of time, we could */ /* set PDTA_Remap to TRUE and provide a pointer to the screen */ /* with the PDTA_Screen tag (datatypes.library handles the rest).*/ /* However in this case we want to first find out the attributes */ /* of the picture object and set up a matching screen and do the */ /* remapping later. Therefore PDTA_Remap is set to false. */ /* The group ID tag ensures that we get only a picture file type.*/ if (dtobject = NewDTObject(argv[1], PDTA_Remap, FALSE, DTA_GroupID, GID_PICTURE, TAG_END) ) { /* Here we want to find the display environment required by */ /* this picture. To do that, perform the DTM_FRAMEBOX method */ /* on the object. The datatypes library fills in the struct */ /* FrameBox you give it with the info on the display needed. */ mydtFrameBox.MethodID = DTM_FRAMEBOX; mydtFrameBox.dtf_GInfo = NULL; mydtFrameBox.dtf_ContentsInfo = NULL; mydtFrameBox.dtf_FrameInfo = &myFrameInfo; mydtFrameBox.dtf_SizeFrameInfo= sizeof (struct FrameInfo); mydtFrameBox.dtf_FrameFlags = 0L; /* The return value from DTM_FRAMEBOX is currently undefined */ res = DoMethodA(dtobject, &mydtFrameBox); /* OK, now do the layout (remap) of the object on our process */ mygpLayout.MethodID = DTM_PROCLAYOUT; mygpLayout.gpl_GInfo = NULL; mygpLayout.gpl_Initial= 1L; /* The return value of DTM_PROCLAYOUT is non-zero for success */ if( res = DoMethodA(dtobject, &mygpLayout) ) { /* Get the attributes of this picture object. You could */ /* use a series of GetAttr() function calls here instead. */ res = GetDTAttrs(dtobject, PDTA_ModeID, &modeID, PDTA_CRegs, &cregs, PDTA_BitMap, &bm, TAG_END); /* Did we get all threee attributes? */ if( (modeID!=INVALID_ID) && (cregs) && (bm) ) { /* Open a screen that matches the picture object */ if( myScreen = OpenScreenTags( NULL, SA_Width, myFrameInfo.fri_Dimensions.Width, SA_Height, myFrameInfo.fri_Dimensions.Height, SA_Depth, myFrameInfo.fri_Dimensions.Depth, SA_DisplayID, modeID, SA_BitMap, bm, TAG_END) ) { /* Now fill in the color registers for this screen */ numcolors = 2<<(myFrameInfo.fri_Dimensions.Depth-1); for( i=0; i < numcolors; i++ ) { r = cregs[i * 3 + 0]; g = cregs[i * 3 + 1]; b = cregs[i * 3 + 2]; SetRGB32(&myScreen->ViewPort, i, r, g, b); } printf("Ctrl-C in this window to quit\n"); /* Wait for the user to have a look... */ Wait(SIGBREAKF_CTRL_C); CloseScreen(myScreen); } else printf("Couldn't open required screen\n"); } else printf("Couldn't get picture attributes\n"); DisposeDTObject(dtobject); } else printf("Couldn't perform PROC_LAYOUT\n"); } else printf("Couldn't create new object or not a picture file\n"); } else printf("Give a file name too.\n"); CloseLibrary(DataTypesBase); } else printf("Can't open datatypes library\n"); CloseLibrary(GfxBase); } else printf("Can't open V39 graphics\n"); CloseLibrary(IntuitionBase); } else printf("Can't open V39 Intuition\n"); }
As with 8SVX objects, the datatypes library allows ILBM objects to be treated as gadgets. Remember that all datatypes object classes a sub-class of the BOOPSI gadget class and therefore support the gadget methods described in the BOOPSI section.
Writing A Sub-Class
For each of the DataType categories, there is a class that handles the data. Handlers for explicit data are sub-classes under the appropriate class. For example, a class that handles ILBM pictures would be a sub-class of the Picture class.
In order to fully understand the class concept used by DataTypes it helps to have a basic understanding of BOOPSI.
A sub-class must provide an OM_NEW method that converts the source data into the data format required by the super-class. The sub-class must optionally have a OM_DISPOSE method that discards any of the data constructed in the OM_NEW method. All other methods must be passed to the super-class.
Following is a listing of a example class dispatcher for a sub-class of the picture class:
uint32 Dispatch(Class *cl, Object *o, Msg msg) { struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData; uint32 retval; switch (msg->MethodID) { case OM_NEW: if (retval = IIntuition->IDoSuperMethodA(cl, o, msg)) { /* Convert the source data to required data format */ if (!GetObjectData (cb, cl, (Object *)retval, ((struct opSet *) msg)->ops_AttrList)) { /* Force disposal of the object */ IIntuition->ICoerceMethod (cl, (Object *) retval, OM_DISPOSE); retval = NULL; } } break; /* Let the superclass handle everything else */ default: retval = (uint32) IIntuition->IDoSuperMethodA (cl, o, msg); break; } return (retval); }
Obtaining a Handle to the Source Data
The first step that a class has to perform in order to convert the source data, is to get a handle on the data. This is obtained by passing the DTA_Handle tag to the super-class using the OM_GET method. For example:
Object *o; BPTR fh; IDataTypes->GetDTAttrs(o, DTA_Handle, &fh, TAG_END);
If the source Type is DTF_IFF, then DTA_Handle points to a struct IFFHandle that is already initialized and opened for reading, otherwise the handle points to a BPTR file handle.
Handling Errors
Whenever an error occurs and the class is unable to continue converting the data, then it must set an appropriate error using the DOS SetIoErr() function and the <dos/dos.h> error codes or the error codes defined in <datatypes/datatypes.h>.
For example, if the class is unable to allocate memory:
if (buf = IExec->AllocVecTags(size, AVT_ClearWithValue, 0, TAG_END)) { ... continue with conversion ... } else { IDOS->SetIoErr (ERROR_NO_FREE_STORE);
Data Format
The following sections outline the required data format for each of the main object types.
Picture Class
The picture class is the super-class for any static graphic classes. The structures and tags used by this class are defined in <datatypes/pictureclass.h>.
A picture sub-class must fill out a BitMapHeader structure as well as provide a Mode ID, a BitMap and a ColorMap during the OM_NEW method of the class. There is no need to provide any other methods, as the remainder is handled by the picture class itself.
The picture sub-class needs to fill in any fields of the BitMapHeader structure that the class has data for. This will ensure that the picture data can then be saved to a file or copied to the clipboard.
struct BitMapHeader *bmh; /* Obtain a pointer to the BitMapHeader structure from the picture class */ if (IDataTypes->GetDTAttrs (dto, PDTA_BitMapHeader, &bmh, TAG_END) && bmh) { /* Fill in some fields */ bmh->bmh_Width = 640; bmh->bmh_Height = 200; bmh->bmh_Depth = 2; }
Before manipulating any color information, the picture sub-class must first tell the picture class how many colors it has, so that the information required for color remapping can be established.
IDataTypes->SetDTAttrs (dto, PDTA_NumColors, ncolors, TAG_END);
After the number of colors have been established, the palette information can be filled in for the picture. The following fragment illustrates filling in the palette information.
struct ColorRegister *cmap; int16 n, ncolors; int32 *cregs; /* Get a pointer to the color registers that need to be * filled in */ IDataTypes->GetDTAttrs (dto, PDTA_ColorRegisters, &cmap, PDTA_CRegs, &cregs, TAG_END); /* Set the color information */ for (n = 0; n < ncolors; n++) { if (IDOS->Read (fh, &rgb, QSIZE) == QSIZE) { /* Set the master color table */ cmap->red = rgb.rgbRed; cmap->green = rgb.rgbGreen; cmap->blue = rgb.rgbBlue; cmap++; /* Set the color table used for remapping */ cregs[n * 3 + 0] = rgb.rgbRed << 24; cregs[n * 3 + 1] = rgb.rgbGreen << 24; cregs[n * 3 + 2] = rgb.rgbBlue << 24; } else { /* Indicate that we encountered an error. DOS Read * will have already filled in the IoErr() value */ return FALSE; } }
The picture class must get the actual picture information in standard Amiga bitmap format. If the bitmap is allocated using the graphics AllocBitMap() function, then the picture class can dispose of the bitmap at OM_DISPOSE time.
struct BitMap *bm; if (bm = IGraphics->AllocBitMap (bmh->bmh_Width, bmh->bmh_Height, bmh->bmh_Depth, BMF_CLEAR, NULL)) { /* Tell the picture class about the picture data */ IDataTypes->SetDTAttrsA (dto, PDTA_BitMap, bm, TAG_END); } else { /* Indicate the error and that we encountered an error */ IDOS->SetIoErr (ERROR_NO_FREE_STORE); return FALSE; }
A picture sub-class needs to provide the following fields to the super-class, during the OM_NEW method:
|(int32) Set to the width of the picture.
|(int32) Set to the height of the picture.
|(uint32) A valid mode ID for the BitMap.
|(STRPTR) The name, or title, of the picture
|(STRPTR) The author of the picture.
|(STRPTR) Notes on the picture.
|(STRPTR) Copyright notice for the picture.
|(STRPTR) Version of the picture.
If a picture sub-class uses something other than AllocBitMap() to allocate the bitmap, then it must free the bitmap itself. This is done by implementing an OM_DISPOSE method for the sub-class.
uint32 Dispatch (Class *cl, Object *o, Msg msg) { struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData; struct localData *lod; uint32 retval; switch (msg->MethodID) { case OM_NEW: /* ... */ break; case OM_DISPOSE: /* Get a pointer to our object data */ lod = INST_DATA (cl, o); /* Tell the picture class that it doesn't have a * bitmap to free any more */ IDataTypes->SetDTAttrs (o, PDTA_BitMap, NULL, TAG_END); /* Free the bitmap ourself */ myfreebitmap (lod->lod_BitMap); /* Let the superclass handle everything else */ default: retval = (uint32) IIntuition->DoSuperMethodA (cl, o, msg); break; } return retval; }
Sound Class
The sound class is the super-class for any sampled audio classes. The structures and tags used by this class are defined in <datatypes/soundclass.h>.
A sound sub-class needs to provide the following fields to the super-class, during the OM_NEW method:
|(uint8 *) 8-bit sound data. The sound class will FreeVec() the sample data.
|(uint32) Number of 8-bit bytes in the sound data.
|(uint16) Number ranging from 0 being the quietest to 64 being the loudest.
|(uint16) Amount of time to play the sound.
|(uint16) Number of times to play the sound. 0 being an infinite loop.
|(STRPTR) The name, or title, of the sound
|(STRPTR) The author of the sound.
|(STRPTR) Notes on the sound.
|(STRPTR) Copyright notice for the sound.
|(STRPTR) Version of the sound.
No methods other OM_NEW are need, as the remainder is handled by the sound class itself.
The sound sub-class also needs to fill in any fields of the VoiceHeader structure that the class has data for. This will ensure that the sound data can then be saved to a file or copied to the clipboard.
struct VoiceHeader *vh; /* Obtain a pointer to the VoiceHeader structure from the sound class */ if (IDataTypes->GetDTAttrs (dto, SDTA_VoiceHeader, &vh, TAG_END) && vh) { /* Fill in some fields */ vh->vh_Octaves = 1; vh->vh_Compression = 0; vh->vh_Volume = 63; }
If a sound sub-class uses something other than AllocVec() to allocate the sound data, then it must free the sample itself. This is done by implementing an OM_DISPOSE method for the sub-class.
uint32 Dispatch (Class *cl, Object *o, Msg msg) { struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData; struct localData *lod; uint32 retval; switch (msg->MethodID) { case OM_NEW: /* ... */ break; case OM_DISPOSE: /* Get a pointer to our object data */ lod = INST_DATA (cl, o); /* Tell the sound class that it doesn't have a * sample to free any more */ IDataTypes->SetDTAttrs (o, SDTA_Sample, NULL, TAG_END); /* Free the sample ourself */ IExec->FreeVec(lod->lod_Sample); /* Let the superclass handle everything else */ default: retval = (uint32) IIntuition->IDoSuperMethodA (cl, o, msg); break; } return retval; }
Text Class
The text class is the super-class for any formatted or non-formatted text classes. The structures and tags used by this class are defined in <datatypes/textclass.h>.
The text class provides the sub-class with a buffer that contains the text data. The sub-class must then provide the text class with a list of Line segments during the layout method. This Line list should only be created at gpl_Initial time, unless the TDTA_WordWrap attribute is TRUE.
struct Line { struct MinNode ln_Link; STRPTR ln_Text; ULONG ln_TextLen; UWORD ln_XOffset; UWORD ln_YOffset; UWORD ln_Width; UWORD ln_Height; UWORD ln_Flags; BYTE ln_FgPen; BYTE ln_BgPen; ULONG ln_Style; APTR ln_Data; };
The Line structure fields are as follows:
- ln_Link
- MinNode used to link to the line list.
- ln_Text
- Pointer to the text for this line segment.
- ln_TextLen
- Number of bytes of text in this line segment.
- ln_XOffset
- Left pixel offset from the left edge of the object for this line segment.
- ln_YOffset
- Top pixel offset from the top edge of the object for this line segment.
- ln_Width
- Width of the line segment in pixels.
- ln_Height
- Height of the line segment in pixels.
- ln_Flags
- Control flags for this line segment.
- LNF_LF -- Used to indicate that this segment is the end of a line.
- ln_FgPen
- Pen to use for the foreground (the text color) for this line segment.
- ln_BgPen
- Pen to use for the background color for this line segment.
- ln_Style
- Text attribute soft style to use for this line segment.
As each Line segment is allocated it must be added to the Line list.
struct List *linelist; struct Line *line; /* Get a pointer to the line list */ if (IDataTypes->GetDTAttrs (o, TDTA_LineList, (uint32) &linelist, TAG_END) && linelist) { /* Create a Line segment */ if (line = AllocVecTags(sizeof (struct Line), AVT_ClearWithValue, 0, TAG_END)) { /* Add it to the list */ IExec->AddTail (linelist, (struct Node *)&line->ln_Link); } }
Currently, this is the hardest class to sub-class, due to the number of methods that must be implemented. Following is the shell for a dispatcher and the layout method for a text sub-class.
struct localData { VOID *lod_Pool; uint32 lod_Flags; }; uint32 Dispatch (Class * cl, Object * o, Msg msg) { struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData; struct localData *lod; struct List *linelist; uint32G retval = 0; switch (msg->MethodID) { case OM_NEW: if (retval = IIntuition->IDoSuperMethodA (cl, o, msg)) { uint32 len, estlines, poolsize; BOOL success = FALSE; STRPTR buffer; /* Get a pointer to the object data */ lod = INST_DATA (cl, (Object *) retval); /* Get the attributes that we need to determine memory pool size */ IDataTypes->GetDTAttrs ((Object *) retval, TDTA_Buffer, &buffer, TDTA_BufferLen, &len, TAG_END); /* Make sure we have a text buffer */ if (buffer && len) { /* Estimate the pool size that we will need */ estlines = (len / 80) + 1; estlines = (estlines > 200) ? 200 : estlines; poolsize = sizeof (struct Line) * estlines; /* Create a memory pool for the line list */ lod->lod_Pool = IExec->AllocSysObjectTags(ASOT_MEMPOOL, ASOPOOL_MFlags, MEMF_SHARED | MEMF_CLEAR, ASOPOOL_Puddle, poolsize, ASOPOOL_Threshold, poolsize, TAG_END); if (lod->lod_Pool != NULL) success = TRUE; else IDOS->SetIoErr (ERROR_NO_FREE_STORE); } else { /* Indicate that something was missing that we needed */ IDOS->SetIoErr (ERROR_REQUIRED_ARG_MISSING); } if (!success) { IIntuition->ICoerceMethod (cl, (Object *) retval, OM_DISPOSE); retval = NULL; } } break; case OM_UPDATE: case OM_SET: /* Pass the attributes to the text class and force a refresh if we need it */ if ((retval = IIntuition->IDoSuperMethodA (cl, o, msg)) && (OCLASS (o) == cl)) { struct RastPort *rp; /* Get a pointer to the rastport */ if (rp = IGraphics->ObtainGIRPort (((struct opSet *) msg)->ops_GInfo)) { IIntuition->DoRender(o, ((struct opSet *) msg)->ops_GInfo, GREDRAW_UPDATE); /* Release the temporary rastport */ IGraphics->ReleaseGIRPort (rp); } retval = 0; } break; case GM_LAYOUT: /* Tell everyone that we are busy doing things */ notifyAttrChanges (o, ((struct gpLayout *) msg)->gpl_GInfo, NULL, GA_ID, G(o)->GadgetID, DTA_Busy, TRUE, TAG_END); /* Let the super-class partake */ retval = (uint32) IIntuition->IDoSuperMethodA (cl, o, msg); /* We need to do this one asynchronously */ retval += IDataTypes->DoAsyncLayout (o, (struct gpLayout *) msg); break; case DTM_PROCLAYOUT: /* Tell everyone that we are busy doing things */ notifyAttrChanges (o, ((struct gpLayout *) msg)->gpl_GInfo, NULL, GA_ID, G(o)->GadgetID, DTA_Busy, TRUE, TAG_END); /* Let the super-class partake and then fall through to our layout method */ retval = (uint32) IDataTypes->DoSuperMethodA (cl, o, msg); case DTM_ASYNCLAYOUT: /* Layout the text */ retval = layoutMethod (cb, cl, o, (struct gpLayout *) msg); break; case OM_DISPOSE: /* Get a pointer to our object data */ lod = INST_DATA (cl, o); /* Don't let the super class free the line list */ if (IIntuition->GetDTAttrs (o, TDTA_LineList, &linelist, TAG_END) && linelist) IExec->NewList (linelist); /* Delete the line pool */ IExec->FreeSysObject(ASOT_MEMPOOL, lod->lod_Pool); /* Let the superclass handle everything else */ default: retval = (uint32) IIntuition->DoSuperMethodA (cl, o, msg); break; } return (retval); } uint32 layoutMethod (struct ClassBase *cb, Class * cl, Object * o, struct gpLayout * gpl) { struct DTSpecialInfo *si = (struct DTSpecialInfo *) G (o)->SpecialInfo; struct localData *lod = INST_DATA (cl, o); uint32 visible = 0, total = 0; struct RastPort trp; uint32 hunit = 1; uint32 bsig = 0; /* Switches */ BOOL linefeed = FALSE; BOOL newseg = FALSE; BOOL abort = FALSE; /* Attributes obtained from super-class */ struct TextAttr *tattr; struct TextFont *font; struct List *linelist; struct IBox *domain; uint32 wrap = FALSE; uint32 bufferlen; STRPTR buffer; STRPTR title; /* Line information */ uint32 num, offset, swidth; uint32 anchor, newanchor; uint32 style = FS_NORMAL; struct Line *line; uint32 yoffset = 0; uint8 fgpen = 1; uint8 bgpen = 0; uint32 tabspace; uint32 numtabs; uint32 i, j; uint32 nomwidth, nomheight; /* Get all the attributes that we are going to need for a successful layout */ if (IDataTypes->GetDTAttrs (o, DTA_TextAttr, &tattr, DTA_TextFont, &font, DTA_Domain, &domain, DTA_ObjName, &title, TDTA_Buffer, &buffer, TDTA_BufferLen,&bufferlen, TDTA_LineList, &linelist, TDTA_WordWrap, &wrap, TAG_END) == 8) { /* Lock the global object data so that nobody else can manipulate it */ IExec->ObtainSemaphore (&(si->si_Lock)); /* Make sure we have a buffer */ if (buffer) { /* Initialize the temporary RastPort */ IGraphics->InitRastPort (&trp); IGraphics->SetFont (&trp, font); /* Calculate the nominal size */ nomheight = (ULONG) (24 * font->tf_YSize); nomwidth = (ULONG) (80 * font->tf_XSize); /* Calculate the tab space */ tabspace = font->tf_XSize * 8; /* We only need to perform layout if we are doing word wrap, or this * is the initial layout call */ if (wrap || gpl->gpl_Initial) { /* Delete the old line list */ while (line = (struct Line *) IExec->RemHead (linelist)) IExec->FreePooled (lod->lod_Pool, line, sizeof (struct Line)); /* Step through the text buffer */ for (i = offset = num = numtabs = 0; (i <= bufferlen) && (bsig == 0) && !abort; i++) { /* Check for end of line */ if (buffer[i]==13 && buffer[i+1]==10) { newseg = linefeed = TRUE; newanchor = i + 2; i++; } /* Check for end of page */ else if (buffer[i] == 12) { newseg = linefeed = TRUE; newanchor = i + 1; } /* Check for tab */ else if (buffer[i] == 9) { /* See if we need to terminate a line segment */ if ((numtabs == 0) && num) newseg = TRUE; numtabs++; } else { /* See if we have any TABs that we need to finish out */ if (numtabs) { offset += (((offset / tabspace) + 1) * tabspace) - offset; num = numtabs = 0; anchor = i; } /* Compute the width of the line. */ swidth = IGraphics->TextLength (&trp, &buffer[anchor], num+1); if (offset + swidth > domain->Width) { /* Search for a whitespace character */ for (j = i; (j >= anchor) && !newseg; j--) { if (buffer[j] == ' ') { num -= (i - j); newseg = TRUE; i = j + 1; } } newseg = linefeed = TRUE; newanchor = i; i--; } else { num++; } } /* Time for a new text segment yet? */ if (newseg) { /* Allocate a new line segment from our memory pool */ if (line = IExec->AllocPooled (lod->lod_Pool, sizeof (struct Line))) { swidth = IGraphics->TextLength (&trp, &buffer[anchor], num); line->ln_Text = &buffer[anchor]; line->ln_TextLen = num; line->ln_XOffset = offset; line->ln_YOffset = yoffset + font->tf_Baseline; line->ln_Width = swidth; line->ln_Height = font->tf_YSize; line->ln_Flags = (linefeed) ? LNF_LF : NULL; line->ln_FgPen = fgpen; line->ln_BgPen = bgpen; line->ln_Style = style; line->ln_Data = NULL; /* Add the line to the list */ IExec->AddTail (linelist, (struct Node *) line); /* Increment the line count */ if (linefeed) { yoffset += font->tf_YSize; offset = 0; total++; } else { /* Increment the offset */ offset += swidth; } } else { abort = TRUE; } /* Clear the variables */ newseg = linefeed = FALSE; anchor = newanchor; num = 0; /* Check to see if layout has been aborted */ bsig = IDOS->CheckSignal (SIGBREAKF_CTRL_C); } } } else { /* No layout to perform */ total = si->si_TotVert; } } /* Compute the lines and columns type information */ si->si_VertUnit = font->tf_YSize; si->si_VisVert = visible = domain->Height / si->si_VertUnit; si->si_TotVert = total; si->si_HorizUnit = hunit = 1; si->si_VisHoriz = (int32) domain->Width / hunit; si->si_TotHoriz = domain->Width; /* Release the global data lock */ IExec->ReleaseSemaphore (&si->si_Lock); /* Were we aborted? */ if (bsig == 0) { /* Not aborted, so tell the world of our newest attributes */ notifyAttrChanges (o, gpl->gpl_GInfo, NULL, GA_ID, G(o)->GadgetID, DTA_VisibleVert, visible, DTA_TotalVert, total, DTA_NominalVert, nomheight, DTA_VertUnit, font->tf_YSize, DTA_VisibleHoriz, (uint32) (domain->Width / hunit), DTA_TotalHoriz, domain->Width, DTA_NominalHoriz, nomwidth, DTA_HorizUnit, hunit, DTA_Title, title, DTA_Busy, FALSE, DTA_Sync, TRUE, TAG_END); } } return total; }
Defining a DataType Descriptor
DataTypes uses a simple descriptor to determine what type of data a file contains and what class, if any, is used to handle that data.
The DTDesc utility is used to define a DataType descriptor. The following steps describe how to use this utility to define a descriptor.
1. Load several sample files of the type being defined. This can be done by dropping their icons into the DTDesc window or by using the "Extras/Load Samples..." menu item.
2. The view area in the bottom right side of the DTDesc window will show the first 64 characters of the files. This area is used to define the Mask. The characters that don't match will be blotted out and only the similar characters will be shown. If more characters are shown as similar than really are, then they can easily be blotted out by rubbing over them.
3. DataTypes can be broken out into several different categories. Use the Group menu to select the category that the DataType descriptor belongs in.
4. The remaining fields must be filled out. Following is a table describing the fields and the information they require.
Name Description File Type User description of the DataType. Base Name The base name of the DataType. The class library name is derived from this. Name Pattern The name of the file can be used to indicate the DataType. AmigaDOS wildcards can be used to specify the file name. Function A function can be used to further define a data type. This function must be a stand-alone executable that uses the DataType Descriptor Function Interface. Case Sensitive? The Mask can be either case sensitive or not. Priority Descriptors are sorted by Type, Function, Name Pattern and Mask. The priority field allows a DataType descriptor to be assigned a different priority than a similar DataType descriptor. Type This is a read-only field and is used to indicate what basic type a DataType is. Types include IFF, Binary and ASCII.
5. Once a DataType descriptor has been defined, it must be saved. Select the "Project/Save As..." menu item for the file requester used to save a DataType descriptor. The default name for a DataType descriptor is the text entered into File Type field.
6. In order for a new DataType descriptor to be loaded, the datatypes.library must be flushed from the system. This can either be done with the Expunge command included in the SDK. Another way that the new DataType descriptor can be loaded is by using the AddDataTypes command with the REFRESH option.
DataType Descriptor Function Interface
Sometimes the fields within the DTDesc utility are not enough to define a DataType descriptor. In this case it is necessary to use a Function to further narrow down a DataType.
A Function is a stand-alone executable that expects the following arguments.
BOOL retval = Function(struct DTHookContext *dthc);
The function must return TRUE if the data matches, FALSE if it doesn't.
The DTHookContext structure contains the fields that are necessary for narrowing down the DataType. Following is a listing of the DTHookContext structure.
struct DTHookContext { struct Library *dthc_SysBase; struct Library *dthc_DOSBase; struct Library *dthc_IFFParseBase; struct Library *dthc_UtilityBase; /* File context */ BPTR dthc_Lock; /* Lock on the file */ struct FileInfoBlock *dthc_FIB; /* Pointer to a FileInfoBlock */ BPTR dthc_FileHandle; /* Pointer to the file handle (may be NULL) */ struct IFFHandle *dthc_IFF; /* Pointer to an IFFHandle (may be NULL) */ STRPTR dthc_Buffer; /* Buffer */ ULONG dthc_BufferLength; /* Length of the buffer */ ULONG dthc_Length; /* size of this structure */ struct ExecIFace * dthc_IExec; struct DOSIFace * dthc_IDOS; struct IFFParseIFace * dthc_IIFFParse; struct UtilityIFace * dthc_IUtility; };
The DTHookContext structure fields are as follows:
- dthc_SysBase
- dthc_DOSBase
- dthc_IFFParseBase
- dthc_UtilityBase
- These are library bases that your function can utilize. It will need to open any other libraries that it needs.
- dthc_Lock
- If the source data is a DOS file, then this is a lock on the file.
- dthc_FIB
- If the source data is a DOS file, then this is a filled in FileInfoBlock for the file.
- dthc_FileHandle
- If the source data is a DOS file, then this is the file handle for the file otherwise the handle will be NULL. The file is guaranteed to be at the beginning.
- dthc_IFF
- If the source data is IFF, then this is the IFFHandle for accessing the data, otherwise the handle will be NULL. The position is guaranteed to be at the beginning of the data. The DOS file fields must not be accessed if the data is IFF.
- dthc_Buffer
- This buffer contains the first dthc_BufferLength bytes of data.
- dthc_BufferLength
- Indicates the number of bytes in dthc_Buffer, up to 64.
- dthc_Length
- Size in bytes of struct DTHookContext
- dthc_IExec
- dthc_IDOS
- dthc_IIFFParse
- dthc_IUtility
- These are interface pointers that your function can utilize.
The following example shows how to write a simple DataTypes Descriptor Function.
/* This example must not be linked with any startup code so that * DTHook is the entry point for the executable. * */ #include <exec/types.h> #include <dos/dos.h> #include <dos/dosextens.h> #include <datatypes/datatypes.h> #include <proto/exec.h> #include <proto/dos.h> #include <proto/utility.h> BOOL DTHook (struct DTHookContext * dthc) { BOOL retval = FALSE; uint32 i; uint8 ch; /* Make sure we have a buffer */ if (dthc->dthc_Buffer) { for (i = 0; (i < dthc->dthc_BufferLength) && !retval; i++) { ch = dthc->dthc_Buffer[i]; /* Look at the data... */ } } return retval; }
The next example shows how to write a DataTypes Descriptor that looks into an IFF file for needed chunk information.
/* This example must not be linked with any startup code * so that DTHook is the entry point for the executable. */ #include <exec/types.h> #include <dos/dos.h> #include <dos/dosextens.h> #include <datatypes/datatypes.h> #include <datatypes/pictureclass.h> #include <libraries/iffparse.h> #include <proto/exec.h> #include <proto/dos.h> #include <proto/iffparse.h> #include <proto/utility.h> #define BMH_SIZE (sizeof (struct BitMapHeader)) BOOL DTHook(struct DTHookContext * dthc) { struct BitMapHeader bmh; struct ContextNode *cn; struct IFFHandle *iff; BOOL retval = FALSE; /* Make sure that this is an IFF data type */ if (iff = dthc->dthc_IFF) /* Stop on the BitMapHeader (type, id) */ if (dthc->dthc_IIFFParse->StopChunk (iff, ID_ILBM, ID_BMHD) == 0) /* Scan through the IFF handle */ if (dthc->dthc_IIFFParse->ParseIFF (iff, IFFPARSE_SCAN) == 0L) /* Make sure we have a current chunk */ if (cn = dthc->dthc_IIFFParse->CurrentChunk (iff)) /* Make sure the current chunk is ILBM BMHD */ if ((cn->cn_Type == ID_ILBM) && (cn->cn_ID == ID_BMHD)) /* Read the chunk data */ if (dthc->dthc_IIFFParse->ReadChunkBytes (iff, &bmh, BMH_SIZE) == BMH_SIZE) /* See if the depth is set to 24 */ if (bmh.bmh_Depth == 24) retval = TRUE; return (retval); }


text:
Trane Worldwide Sites
The one stop access for new systems solutions from Trane
Applications expertise in multiple market sectors
Quickly and easily select equipment and controls
Evaluate performance under customer-defined parameters
Parts, supplies and technical information for your research and repairs.Learn More
Multi-pipe unit for heating and cooling buildings
This Engineers Newsletter focuses on showing the potential benefits of a multi-pipe unit for heating and cooling a building and the impact it can have on energy running costs.
See how Trane is Making a Difference!
View our Case Studies.Learn More

subset: commoncrawl


text:
The other week I was in Sephora, I had to return my MUFE HD Foundation cause I didn't like the consistency of it and just wasn't happy with it. I think people hyped it up too much. Anyway, I was past my 30 days so I had store credit. I bought yet another hyped up product.
Lola by Marc Jacobs the "it" fragrance , don't get me wrong... I loved it BUT for some reason my body quickly absorbs it. WOMP so now I have to return it *sighs* . I need to find a winter/spring fragrance that stays on me and won't leave. If you have any suggestions, please drop them in the cmmnt box!
For now Victoria's Secret Sweet Daydream is holding me down. I frickin' love it... It's a mix of apple, raspberry and vanilla. yumm ♥


text:
We Appreciate Everything
Thank you all so much for your kindness in looking after our little Rosie we appreciate
everything. Thank you again so much.
Carol, Bonnie, Jacey and Eve.
View more kind words…
Contact Us
Kind Words
Trotter Rest Sunnyfields Road
High Garrett, Braintree
Essex CM7 5PQ
01376 552 535
01376 529 137
07557 435 054
Copyright © 2019 Sunnyfields Pet Crematorium
Email Address:
Thank you for a wonderful professional service that you provided for our beautiful dog Meg. The
dignity that your services provided for our wonderful dog meant so much to us.
Sunnyfields Pet Crematorium is approved by DEFRA and The Secretary of State. Reg No's 1774/2002


text:
Designer: Lisa Peck, Lilu Interiors, Minneapolis, www.liluinteriors.com.
Holiday style: "Bubbly, light and happy," said Peck. "There's a little retro feel." Holiday decorations are more visually appealing when they flow with the existing decor of your rooms, said Peck, who chose a color palette of mainly silver, gold with ivory and black accents for her 1920s bungalow. "I already had gray, yellow and white for the rest of the year, so silver and gold work well with that."
Tree jewelry: Peck hung faux and authentic vintage brooches throughout her holiday tree, inspired by the cherished costume jewelry passed down to her from her grandmother. She wired together several brooches for more sparkle and sewed them onto ribbon. Other ornaments resemble dangling earrings. "Everyone has Christmas brooches they never wear," she said. "Use them to dress up your tree."
Tie a cream ribbon around the tree. "A cream ribbon with silver and gold makes the tree feel lighter, which works better in smaller spaces," she said. The only heavy element is oversized black balls, which add depth and drama.
Mixed-metal mantel: Peck designed an asymmetrical arrangement of apothecary jars filled with silver, gold and pewter-hued balls of different textures and finishes illuminated by tiny "fairy lights." She trimmed the mantel with shiny tinsel garland and ornaments wrapped in cream ribbon. "Common elements tie the tree and mantel together," she said. To create layers, she advised first placing the heavier elements, such as the jars and tinsel garland, and building around them.
Ornaments take center stage: "Highlight special memory ornaments inside clear glass cloches," said Peck, who arranges them atop her heirloom piano. "Mirrors at the base give them sparkle."
Festive flourishes: Peck attaches a dressy ornament with a pin to the back of each upholstered dining-room chair, tosses sparkly pillows on living room chairs and replaces framed family photos with holiday-themed versions. Battery-operated twinkle lights illuminate a glass candy bowl that holds white and silver balls. "I don't like a room to be overly cloying," she said. "I like it to be festive, but I keep it simple so it doesn't feel like a department store."
Ever-changing tree: Peck's Christmas tree is a thoughtful composition of color, texture, shape and style. "I'm a designer, but I'm also a mom," she said. "My children will get to hang their ornaments on the tree when it gets closer to Christmas."
Designer: Rob Edman, Edman Hill Interior Design, Minneapolis, www.edmanhill.com.
Holiday style: Edman's childhood roots in small-town northern Minnesota influence his decor in his 1930s Tudor-style bungalow in Minneapolis. "I've always liked woodsy, organic things," he said, "but with a little modern edge." Edman also combines vintage collectibles with cherished decorations passed down from his grandmother, including a whimsical wooden Scandinavian elf peering from a window.
Bird lovers' tree: Edman filled his Douglas fir tabletop tree with silver, white and nature-themed ornaments accented with a touch of red in the wood berry garland. He mixed a birdseed concoction (for the recipe, go to http://bit.ly/1bdYbG1) and pressed it into holiday cookie cutters to make birdseed ornaments, which he hung from the tree with garden twine. "After Christmas, I'll set the tree in the back yard and the birds can eat them," he said. His version of a tree skirt is an old menswear-patterned blanket wrapped around the base. A West Elm twig ornament with a "modern, organic shape" tops the tree. "With a real tree, you don't have to hang as many ornaments," said Edman. "They're pretty just the way they are."
Grandmother's houses: Edman displayed his collection of miniature red wooden houses from his grandmother on a kitchen windowsill. "I mostly like to decorate with things that have some meaning," he said. "But a little bit of retail doesn't hurt."
Ghosts of Christmas past: Edman scours estate and garage sales for holiday decor that "lots of people think is trash but adds vintage interest," he said. His finds include 1940s plastic tiny reindeer, metal cookie cutters, a wooden "Merry Christmas" sign and old glass ornaments placed inside pedestal bowls for pops of color.
Stocking stuffers: You won't find Edman's holiday stockings in a Pottery Barn catalog. He hangs antique metal sock dryers, which he's amassed over the years, above the fireplace. "I like them for their simplicity," he said. "That's how you dried your socks before gas dryers."
Repeat a theme. Edman placed pieces from his white pottery collection across his mantel and on an antique sideboard surrounded by pine boughs. On the mantel, he tucked pheasant feathers inside pots for height. Near a window, he lined pots with foil and planted paperwhites and amaryllis bulbs.
Simple citrus centerpiece: For the table, Edman filled an earthy wooden bowl with lemons, limes and oranges and tucked in fresh greens. For a more traditional look, he suggested a glass pedestal bowl or soup tureen. For the final flourish, he set a clear acrylic antler next to the bowl. "It's a modern take on a rustic shape," he said.
Designer: Bridget Connell, Haute Flower Boutique (www.hauteflowerboutique.com) and Romens Interiors (www.romensinteriors.com), Eden Prairie.
Holiday style: "Eclectic. A little traditional, with a little quirkiness, which is kind of like me," Connell said. "I like glitter and jewelry and basic black."
Double decorating: Connell decorates on two fronts in her Minneapolis home, with two distinct strategies. On the main floor, the look is more formal and traditional, with black accents to play off the animal prints in her decor, plus lots of mirror ornaments to reflect light.
Downstairs, it's all about the family. Connell created a wall of nine personalized wreaths: one for each of her two preschool children, her husband, herself and one for each of the four grandparents, plus a center wreath framing a family photo. "It's a good option if you're in a condo and don't have room for a tree," she said. Because she does have room, she also created a Minnesota Wild-themed Christmas tree, decorated with hockey skates, sticks and topped with a helmet. (Connell's husband, Pat, and son, Sam, 4, both play the game.) "It's convenient that the Wild colors are red and green," Connell said. She fashioned a tree skirt out of jerseys, and Pat added a tinfoil-wrapped "Stanley Cup." The Wild tree was a big hit with Sam. "He told me he was very proud of me," Connell said.
Themed trees are a fun way to celebrate a child's favorite thing, whether it's a ballet tree for a tiny dancer or a superhero tree for a fervent fan, she said. "As any mom or dad knows, when your kid loves something, you have enough stuff to do a tree."
Decor tip: Connell gift-wraps boxes to complement her decor, wrapping the lids separately. The boxes remain empty until Christmas Eve, which helps her kids resist the temptation to poke curious little fingers into packages, she said. "When Santa comes, we fill them," she said. And the boxes can be re-used year after year.
Go-to elements: For her holiday table, Connell dresses up her everyday white dishes with festive linens and vintage glassware, and spreads fresh cedar greenery. "It's easy and inexpensive," she said. Candles are a must. "I love them — the smell, the light. I don't have a fireplace, so they're a good way to give a fireplace-y warm feeling inside." She favors groupings of votives in mercury glass because the light is soft and flattering.
Worth the effort: Even though she spends her days doing design for other people, Connell enjoys pulling out all the stops at home for the holidays. "I still love it," she said. "I see design as something fun, that makes a house comfortable and yours. And holiday is the one time we can go over the top."


text:
I'll admit it: even I kinda wished I wasn't going to the baseball game. Especially when we got there and it was still something like 900 degrees outside, but it was pouring rain and this is what it looked like out on the field.
Not to mention that even though Friday was Hockey for Hope/Autism Awareness Night for the Bowie Baysox, Sunday is Cowboy Monkey Rodeo night.
Cowboy monkeys. Riding DOGS.
We clearly chose the wrong night to attend.
Except we didn't, because Jack and the other diehard Cheetahs players (and some players from a couple other local teams) who attended got to go out on the field and be cheered on by all 16 people in attendance.
It was really cool. Jack and the other players were totally into it. Jack did his flexed muscles pose and then he stood out there with his thumb in the air. He cracks me up.
So, those unidentifiable creatures are Louie (the green...thing) and Rocko (the rockfish? I think?). Evidently Louie is the original mascot and Rocko is a new secondary mascot. Because all minor league baseball teams need two mascots. I'm thinking of getting a secondary mascot myself. You know, to help Algernon out.
We ended up having a really fun time. The kids ate a lot of junk food, including 12 dollars worth of ice.
I think the Baysox won, which is great. We didn't find out because we bailed after the second inning when it started thundering and then rain started pouring down. I actually wish we could have stayed longer because I was having a lot of fun, which is strange considering I find baseball to be, by far, the most boring of the sports.
But you don't argue with a sky like this:
It's funny, because even though I don't like baseball, I feel like that's all I've been talking about lately. In fact, I have a report from an Orioles game we went to a while back that I haven't posted yet either. That'll come soon. Interestingly, it poured rain that night too.
And now I have to go because we have an early baseball practice tomorrow. See? All baseball, all the time. Enjoy your weekend!


text:
Lady Gaga may be serving as both host and musical guest on this weekend's "Saturday Night Live," but as Kenan Thompson points out in one of several new promos, Mother Monster isn't the only one who lives for the applause.
In particular, Tinker Bell.
"If you don't clap, she dies," Thompson explains.
U.S. & World
"Well, then I'll clap," replies Gaga before putting her hands together.
But when Thompson proceeds to wave around a flashlight, the singer says, "No, no, Kenan. That's a flashlight."
However, he quickly convinces Gaga otherwise, much to her delight.
NEWS: Lady Gaga open to having a threesome with boyfriend Taylor Kinney
The other promos find Thompson trying to impress Gaga with his meat watch, mistaking a lamp with a blonde wig on it for the Grammy winner as well as coming to the shocking realization that Lady Gaga is not her real name.
Oh yeah, and there's some throwing up involved, too.
Meanwhile, Gaga expressed her excitement about her upcoming "SNL" appearance when she tweeted the following on Tuesday: "AH! I've been envisioning this since I was 4 and 3/4rs!"
(E! and NBC are both part of the NBCUniversal family.)


text:
Evolutionary Systems: Biological and Epistemological Perspectives on Selection and Self-Organization
G. Vijver, Stanley N. Salthe, M. Delpos
Springer Netherlands, Oct 31, 1998 - Philosophy - 438 pages
The three well known revolutions of the past centuries - the Copernican, the Darwinian and the Freudian - each in their own way had a deflating and mechanizing effect on the position of humans in nature. They opened up a richness of disillusion: earth acquired a more modest place in the universe, the human body and mind became products of a long material evolutionary history, and human reason, instead of being the central, immaterial, locus of understanding, was admitted into the theater of discourse only as a materialized and frequently out-of-control actor. Is there something objectionable to this picture? Formulated as such, probably not. Why should we resist the idea that we are in certain ways, and to some degree, physically, biologically or psychically determined? Why refuse to acknowledge the fact that we are materially situated in an ever evolving world? Why deny that the ways of inscription (traces of past events and processes) are co-determinative of further "evolutionary pathways"? Why minimize the idea that each intervention, of each natural being, is temporally and materially situated, and has, as such, the inevitable consequence of changing the world? The point is, however, that there are many, more or less radically different, ways to consider the "mechanization" of man and nature. There are, in particular, many ways to get the message of "material and evolutionary determination", as well as many levels at which this determination can be thought of as relevant or irrelevant.
From inside the book
23 pages matching Callebaut in this book
Where's the rest of this book?
Results 1-3 of 23
What people are saying - Write a review
We haven't found any reviews in the usual places.
Model or metaphor?
STANLEY N SALTHE The role of natural selection theory in understanding
Prospects for conver
25 other sections not shown
Other editions - View all
Evolutionary Systems: Biological and Epistemological Perspectives on ...
G. Vijver,Stanley N. Salthe,M. Delpos
No preview available - 2010
Evolutionary Systems: Biological and Epistemological Perspectives on ...
G. Vijver,Stanley N. Salthe,M. Delpos
No preview available - 2014
Common terms and phrases
adaptation adaptationism adaptationist alleles Aristotle attractors Autopoiesis behavior B�nard cells biological systems Buddhist Callebaut Cambridge Cartesian circle causal cells cognitive complex systems components concept constraints construction context Cs�nyi Darwinian Darwinism defined Depew described developmental dynamics ecological effects emergence energy entities environment epigenetic epistemic equation evolution evolutionary epistemology Evolutionary Systems evolving example explain external final cause formal formal cause function genes genetic genotypic hierarchical human idea identity interactions internal descriptive internal measurement interpretation Kampis Kornwachs laws Lewontin lineage living systems material mathematical Maynard Smith means mechanisms molecules mutation natural selection neo-Darwinism objects observer operators optimality organization origin Pattee perception perspective phenomena phenotype Philosophy physical pleiotropic population possible potential pragmatic information principle problem properties relation replication Salthe self-organization semantic semiotic sense species Spinoza structure Swenson symbols syntactic thermodynamic traits University Press Vijver Weber Wimsatt


text:
Although peach pie is a summer classic, we wanted to try and highlight a few of our other favorite summer fruits in a simple pie for two. Nectarines can be every bit as intoxicating as peaches when ripe, and they're even easier to prepare—no fussy peeling necessary. Raspberries add a tart-sweet counterpoint to the nectarines, and when cooked, they break down slightly, creating a thick and vibrant filling. Even ripe nectarines, however, vary in juiciness from season to season and from nectarine to nectarine, making it difficult to know just how much thickener or sweetener a pie will need. We wanted to create a filling that was juicy but not swimming in liquid, its flavors neither muscled out by spices nor overwhelmed by thickeners. And we wanted a double crust, one that would be buttery, flaky, and well browned. If you don't have a food processor, see note below regarding Hand Mixing Pie Dough.–The Editors of America's Test Kitchen
LC Improv Note
How utterly charming is the notion of pie for just two? (Or, in the case of large appetites, pie for just one.) And how perfectly impractical should you lack the 6-inch pie plate this clever notion requires! But wait. Instead, drape the pie crust in your smallest cast-iron skillet or casserole, your largest ramekin, even a modest-size stoneware or other heatproof bowl. Worse comes to worse, simple roll each portion of crust out on parchment paper into a largeish circle. Either spoon the filling a little off to the side fashion a hand pie by folding the dough over and crimping the edges to create a half moon shape or create a rustic galette by dumping the filling in the center of the dough and folding the edges back onto the filling so as to leave the outer parts covered but the center of the filling exposed. Comedians have their take on improv. We home cooks have ours.
Raspberry-Nectarine Pie
- Quick Glance
- Serves 2
Special Equipment: 6-inch pie plate
IngredientsEmail Grocery List
- For the pie dough
- 1 1/4 cups (6 1/4 ounces) unbleached all-purpose flour
- 1 tablespoon sugar
- 1/2 teaspoon salt
- 3 tablespoons vegetable shortening, cut into 1/2-inch pieces and chilled
- 5 tablespoons unsalted butter, cut into 1/4-inch pieces and chilled
- For the filling
- 2 nectarines, pitted and sliced 1/3 inch thick
- 1 cup (5 ounces) fresh raspberries
- 1/4 to 1/3 cup (1 3/4 to 2 1/3 ounces) plus 1 teaspoon sugar
- 2 teaspoons cornstarch
- 3/4 teaspoon fresh lemon juice
- 1/4 teaspoon freshly grated lemon zest
- Pinch salt
- 1 large egg white, lightly beaten
- Make the pie dough
- 1. Process the flour, sugar, and salt together in a food processor until combined. Scatter the shortening over the top and process until the mixture resembles coarse cornmeal, about 10 seconds. Scatter the butter pieces over the top and pulse until the mixture resembles coarse crumbs, about 10 pulses. Transfer the mixture to a medium bowl.
- 2. Sprinkle 4 tablespoons of the ice water over the mixture. Stir and press the dough together, using a stiff rubber spatula, until the dough sticks together. If the dough does not come together, stir in the remaining water, 1 tablespoon at a time, until it does.
- 3. Divide the dough into 2 even pieces. Turn each piece of dough onto a sheet of plastic wrap and flatten each into a 3-inch disk. Wrap each piece tightly in the plastic wrap and refrigerate for 1 hour. Before rolling out the dough, let it sit on the counter to soften slightly, about 10 minutes. (The wrapped dough can be refrigerated for up to 2 days or frozen for up to 1 month. If frozen, let the dough thaw completely on the counter before rolling it out.)
- 4. Roll out one disk of dough into a 9-inch circle on a lightly floured counter, then fit it into a 6-inch pie plate, letting the excess dough hang over the edge; cover with plastic wrap and refrigerate until firm, about 30 minutes. Roll out the other disk of dough into a 9-inch circle on a lightly floured counter, then transfer to a parchment paper–lined plate; cover with plastic wrap and refrigerate until firm, about 30 minutes.
- 5. Adjust an oven rack to the lowest position, place a foil-lined rimmed baking sheet on the rack, and heat the oven to 425°F (220°C).
- Make the filling
- 6. Meanwhile, toss the nectarines, raspberries, and 1/4 cup of the sugar together in a medium bowl, and let sit, tossing occasionally, until the fruit releases its juice, about 20 minutes.
- 7. Drain the fruit thoroughly through a colander, reserving 1 tablespoon of the juice. In a medium bowl, toss the drained fruit, reserved juice, cornstarch, lemon juice, lemon zest, and salt together until well combined. (If the fruit tastes tart, add up to 1 1/2 tablespoons more sugar.)
- 8. Spread the fruit in the dough-lined pie plate, mounding it slightly in the middle. Following the photos, gently arrange the second piece of pie dough over the pie. Trim, fold, and crimp the edges, and cut 3 vent holes in the top. Brush the crust with the egg white and sprinkle with the remaining 1 teaspoon sugar.
- 9. Place the pie on the heated baking sheet and bake until the top crust is golden brown, about 20 minutes. Reduce the oven temperature to 375°F (190°C), rotate the baking sheet, and continue to bake until the juices are bubbling and the crust is deep golden brown, 20 to 25 minutes longer. Let the pie cool on a wire rack until the filling has set, about 1 1/2 hours. Serve slightly warm or at room temperature.
If you make this recipe, snap a photo and hashtag it #LeitesCulinaria. We'd love to see your creations on Instagram, Facebook, and Twitter.


text:
I recently played a game of Mahjong on the internet, and I had gotten this hand
[2 Characters] [3 Characters] [North Wind] [North Wind]
[4 Characters] <- Drawn Tile
[Melded Pon of 2 Bamboo] [Melded Chi of 3-5 Bamboo] [Melded Kan of 1 Characters]
but it wouldn't let me declare Tsumo. I had a few possible reasons why I couldn't but I don't know the game that well. Can you not have a pair of Winds to complete your hand? Or is my hand invalid in some way?
Here is my discards, it might serve some purpose -
[Characters] 7 [Bamboo] 4, 3, 1 [Dragons] Red, Green, White [Winds] East, West


text:
Rocker Jack White has ruled out ever reforming The White Stripes.
The duo split in February last year and White will be releasing his debut solo album, Blunderbuss, next month.
And he's emphatically ruled out ever reuniting with The White Stripes drummer – his ex-wife Meg White – insisting he would have to be penniless to even contemplate a comeback.
White tells NME magazine, "Absolutely no chance. I couldn't see any reason to ever do that. I'm not the kind of person that would retire from baseball and come out of retirement the next year. I mean, if we went to all the trouble of telling people we're done, we meant it, you know?
"If we were forced to change our mind about that, I can only imagine being the reason (sic), like if for some reason we went bankrupt or something or needed the cash, which would be a really sad thing, I would probably be issuing an apology along with the announcement of the show dates!"


text:
Join us for an intimate chat between Beverly Gologorsky and Elizabeth Strout about the novel Stop Here. They the discuss story and the process behind creating a book.
Buy the books here:
Stop Here tells the stories of the hard-working employees of a roadside diner in Long Island who struggle to make ends meet, to deal with the aftermath of the first Iraq war and the family destruction of the second Iraq war, and to find meaning in the crumbling façades that mask the turmoil of their lives. In the novel, Beverly Gologorsky crafts strong, resilient female characters who represent the pillar of strength in their families' lives. The diner connects the fascinating story of each character. Beverly is also the author of the New York Times notable book The Things We Do to Make It Home, which was a Los Angeles Times Best Fiction selection, and received a star review with Publishers Weekly.
Elizabeth Strout won the Pulitzer Prize for fiction with her collection Olive Kitteridge, and her most recent novel which debuted in March of this year is The Burgess Boys.


text:
©2019 Daybreak Game Company LLC. Daybreak, the Daybreak logo, PlanetSide 2, and the PlanetSide 2 logo are trademarks or registered trademarks of Daybreak Game Company LLC. The ratings icon is a registered trademark of the Entertainment Software Association. All rights reserved.
As part of our transition to Daybreak Games, we've updated our Privacy Policy, Cookie Policy, and Terms of Service effective March 13, 2015. By continuing to use our websites and play our games, you are agreeing to these updated terms and policies.
Daybreak Game Company uses cookies to help improve your online experience. By continuing to use our websites without changing your cookie preferences we will assume that you are agreeing to our use of cookies. A list of our websites is available here. For more information, or to change your cookie preferences, visit our cookie policy.


text:
UNIVERSITY PARK, Pa. -- Kathleen Keller, the Mark T. Greenberg Early Career Professor in the Department of Nutritional Sciences at Penn State, has been selected by the American Society of Nutrition (ASN) as the recipient of the 2014 Norman Kretchmer Memorial Award in Nutrition and Development. The award is given to a young investigator for a substantial body of independent research in the field of nutrition and development with a potential relevance to improving child health.
Keller will be presented with the award -- an inscribed plaque supported by Abbott Nutrition Institute and a monetary gift of $1,500 -- at the ASN Awards Ceremony on Sunday, April 27, in San Diego, Calif. The awards ceremony is part of the ASN Scientific Sessions and Annual Meeting at Experimental Biology 2014.
Keller was nominated for the award by members of the Department of Nutritional Sciences at Penn State. Her nominators wrote that her "innovative studies on the influence of common taste genes on children's eating behaviors have already had a huge impact on the field of child obesity and positioned her to become an outstanding future leader in the field of pediatric nutrition."
Keller was the first to test the interaction of genetic differences in bitter taste perception with measures of the build environment assessed Geographical Information Software (GIS). Her work demonstrates that genetic taste susceptibility interacts with the food environment to determine vegetable preferences and body weight in children.
Keller also is applying functional magnetic resonance imaging to determine the neurobiological mechanisms underlying eating behaviors in children. Her studies will be some of the first to measure eating behavior in the laboratory and make connections to neural activation in lean and obese children. These studies will be instrumental in helping to develop new prevention and treatment strategies for childhood nutritional problems and obesity.
Keller serves on the editorial board for the International Journal of Obesity and on the program committee for the Society of the Study of Ingestive Behavior. She has served on the membership committee for The Obesity Society and recently became the ASN's representative on the Advisory Committee Meeting of the Federation of American Societies for Experimental Biology. She earned a Ph.D. degree at Rutgers University in 2002 and joined the faculty at Penn State in 2012.


text:
The panel leading the debate included a nuclear-engineering professor and an industrial ecologist. The nuclear expert was in a winning mood, proclaiming an inevitable nuclear-power renaissance. He enthused about next-generation safe and ultimately fail-safe reactor designs being developed for rapid worldwide dissemination.
The ecologist offered an overview of traditional strategic materials such as copper, and "modern" ones, including lithium, neodymium and dysprosium. He talked about possible future shortages in different materials and how this could affect life. Copper availability is crucial in the global efforts in increasing wind and other renewables generation, which requires major electrical network infrastructure expansion.
He emphasised China's global market dominance in rare earths, with specific elements needed for high-tech usage in telecommunication equipment. Neodymium and dysprosium-based alloys are base materials for powerful permanent magnets used in many different devices from halogen lights and smartphones to permanent-magnet generators (PMGs) in wind turbines and electric motors for hybrid and electric vehicles.
The ecologist claimed that the future of wind power was threatened by the industry's heavy reliance on PMGs, believing this to be a standard turbine fitting. I explained this was incorrect and that conventional generators, including induction and doubly-fed induction generators, dominate the wind industry.
Overtaken by events
Japan's Fukushima nuclear disaster happened only months later and turned nuclear renaissance hopes into a nuclear nightmare.. It made Germany decide to close several nuclear plants, marking the start of a radical transition towards renewable energy.
During roughly the same period, China imposed stringent quotas on rare-earth and magnet material exports, prompting a price hike in early 2011. This led to a rethink by the wind industry on the future of direct-drive PMG and speeded up efforts to develop medium-speed systems with much-reduced demand for magnets.
Today's rare-earth situation is different. New mines are being opened outside China to help meet demand and reduce price fluctuation risks and single-market dependency. In parallel, materials made by combining specific elements could start to offer an alternative to "traditional" rare earths, and international recycling efforts also look increasingly promising. Initial industry fears for continuous high price levels and limited availability seem to have largely faded away.
Negative publicity
One remaining threat to rare-earths use in wind turbines is the ongoing negative publicity surrounding unhealthy and environmentally damaging mining practices in China. In 2011 the German media linked neodymium-mining with wind-turbine generator use, calling it "the dirty side of a clean wind industry". The issue triggered much public debate, and among the accused was major German manufacturer Enercon, even though the company makes turbines incorporating "classic" electrically excited direct-drive generators, a principle that does not incorporate permanent magnets.
More recently an anti-wind group published an "updated" 2011 article offering a detailed account of neodymium-mining practices in China's Baotou region in Inner Mongolia. It describes how neodymium fraction is separated from radioactive uranium and thorium fractions. The latter are than dumped in lakes and open basins, together with poisonous chemicals, causing disease and premature death through heavy pollution of soil, water and air, affecting humans, flora and fauna.
The authors asked whether their findings would mean an end to wind power. This sounds ridiculous, because permanent magnet technology is far too elegant and valuable to be wasted. But the global wind industry must address two major issues. One is to actively promote clean, safe mining practices everywhere. The other is to communicate to both wind turbine clients and the general public the great value of permanent magnet technology and the wind industry's determination to link their advanced clean-power generating hardware with sound rare-earths mining and processing practices.
Failure to act gives anti-wind groups a powerful weapon with which to attack wind power for offering false promises. Most importantly, wind power only qualifies as clean and sustainable when the entire supply chain respects people and their environment.
Eize de Vries is Windpower Monthly's technology and market trends consultant


text:
The cause and manner of the death of a 7-year-old boy with autism in northeast D.C. is still pending after a preliminary autopsy, police said Tuesday afternoon.
More tests will be done.
The intense search for Michael Kingsbury began Sunday morning after his sister saw him walking in an alley close to their home in the 1700 block of West Virginia Avenue. Michael's mother, Katrina Kingsbury, told The Washington Post that Michael threw a light fixture out of an open window while playing in his room Sunday morning. She says he went after it, leaving the home through a back door. He was last seen between 9 a.m. and 9:30 a.m.
U.S. & World
At the time, he was believed to be wearing a pull-up diaper, and possibly a red shirt.
After the family looked for Michael without success, they called police about 10 a.m., and after a thorough search of the home, police broadcast a lookout for the boy at 10:06 a.m. and set up a crticial missing person command post at the scene. Police contacted area hospitals and the medical examiner's office and used a helicopter in canvassing the area. Police began tweeting about the boy's disappearance about 11 a.m.
A K-9 unit led to an unoccupied home several blocks south, police said, and police searched the campus of Gallaudet University.
The search for Michael continued until about 5:50 p.m. Monday, when a sudden rush of police officers converged on a car in the alley. Sources told News4's Pat Collins that a veteran detective assigned to the search happened on the car and noticed something peculiar inside.
The reaction at the scene was immediate, reported Jackie Bensen. People were heard screaming and crying, and police quickly increased their perimeter around the event. Michael was recovered from a car without tags, parked on private property, just two doors down from his home. His body was found face-down on the floor of the locked car, Collins reported.
A police officer had looked in the locked car about 1:30 p.m. Sunday and did not see the body. Nor did at least two other officers -- one working the midnight shift and one searching during the day Monday. Even the family said they looked inside of the car because Michael had once before hid inside of a parked car.
Police had to break a window of the car to get in and recover Michael's body.
"We need to figure out when exactly [Michael] got in the car," Assistant D.C. Police Chief Peter Newsham said. "It's too early to see if someone missed something."
The medical examiner found no signs of trauma to Michael's body and couldn't give an approximate time of death, police said, but there was obvious decomposition to the body.
Homicide detectives were among those who responded to the scene, Bensen reported. However, it is not unusual to have homicide respond to a death investigation.
Police have not ruled out anything.
Michael's mother spoke with Bensen Monday night.
"I'd like to thank everyone who came out to look for my son," Kingsbury said.
The family had been distraught throughout the search for Michael, as police searched abandoned buildings and sheds Sunday and Monday. Kingsbury said it wan't like her son to wander away.
"It's unusual for him to leave. It's never happened," she said. "As many times as he's been out here and played, he's never left the backyard. He knows not to go into the street."
Neighbor Damian Bascon, who helped search for Michael, could onlly talk of what could have been Tuesday.
"Everybody told me if they would've saw that boy walking, they would've protected him and kept him until his parents or someone came out," Bascon said.
As the investigation into Michael's death continues, police are looking into at least one tip from a woman who said she'd seen Michael on a Metro train with a heavyset man. The woman told Michael's mother the boy had been playing with colorful pipe cleaners, The Post reports. Michael fascination with pipe cleaners had not previously been released to the public.
On Tuesday, NBC4's Tom Sherwood spoke with D.C. Mayor Vincent Gray who expressed confidence in the police department, adding he expects a full report from Chief Cathy Lanier.


text:
I have been puzzled by John and Maria Read and their son for a long time now. John and Maria married in 1832 and had their son, also called John in 1832. The marriage and baptism are in the same place that both John and Maria are from.
Despite how much I have searched, I have found no burials for any of them, no other children or found anything about John and Maria anywhere. I cannot find them in the Censuses or other parish records.
It seems most odd that once they married and their son was born, they completely disappear.
I was informed that around this time there was a mass emigration exodus for the county of Buckinghamshire so thought that would be something to look into. But where do I start? Did they go to Australia/New Zealand or America/Canada or somewhere else altogether.
I have searched throughout Buckinghamshire in case they just moved away, and still have a bit more searching to do, but just haven't found anything to do with them anywhere.
My discoveries will be reported here!!


text:
Sept. 25, 2005
Sept. 24, 2005 - Both Lipscomb University cross-country teams placed in the top third of their meets at the Greater Louisville Classic at E.P. "Tom" Sawyer Park on Saturday.
In spite of inclement weather in their south Texas homes, Lone Star Bisons runners prevailed in the midst of adversity.
Zac Yanis, senior captain, led the stampeding Bisons to a fifth place finish against 15 teams. He was able to focus despite destructive forces in his home town of El Campo, Texas. Yanis's time of 27:35 placed eighth overall in the race.
Similarly, freshman, Clint Carter from Angelton, Texas overcame anxieties about home to place second for the Bisons with a time of 28:42.
In women's competition junior Samantha Wood scored points to assist the women in a 10th place finish out of 32 talented teams though turmoil has ensued in her El Campo residence.
"I am so proud of the resilience and strength of spirit these runners possess," said Coach Karen Robichaud. "They inspire the rest of us."