This section collects together various miscellaneous bits of information to do with programming the Macintosh, that dont seem to be very well-known.
Speech Manager: capturing speech to a sound file (Macintalk Pro voices only).
UserDelay: smooth acceleration
without scrolling out of control.
Selecting programmatically from the application menu.
Controlling the default applications that the Finder uses for documents whose creators cant be found.
A description of the 68K MPW Object Code Format.
The format of Finder clipping files.
Description of the Appearance Managers .Keyboard font.
The Macintalk Pro synthesizer has a semi-documented feature that allows you
to retrieve direct sound samples corresponding to a given piece of text. To
use it, you need to make a GetSpeechInfo call with the xtnd
selector, and pass a pointer to a structure that looks like this:
GTXtndConvertData = (* Extended info for conversion selectors. *)
RECORD
(* input values *)
synthID : OSType; (* soGalaSynthID ('gala'). *)
selector : OSType; (* Extended selector ('cval' or 'cvwv'). *)
inputBuffer : ADDRESS; (* Address of the data to convert. *)
inputLen : LONGCARD; (* Length of the data to convert. *)
controlFlags : (*long*) SpeechControlFlags;
(* 0 (for last buffer) or kNoEndingProsody. *)
outputBuffer : Handle;
(* Handle to buffer for the output *)
(* return values *)
outputLen : LONGCARD; (* Returns the size of the output. *)
moreOutput : BOOLEAN;
(* Returns true if outputBuffer is too small for
all the output at once *)
unused : Byte
END (*RECORD*);
In the synthID field, pass the value gala (hex 67616C61). In the
selector field, pass cvwv (hex 63767776) to perform a
text-to-sound-sample conversion. Pass a pointer to the text in
inputBuffer, and its length in inputLen. Pass
a handle to contain the sound samples in outputBuffer.
The output handle will be resized and filled with 16-bit twos-complement
sound samples, at a fixed sample rate of 22254 Hz. If you want to turn this
into a snd resource, for example, then you will need to prepend a
suitably-constructed ExtSoundHeader structure onto it.
As Ive mentioned, this call works only with the Macintalk Pro voices. Also, it was clearly done as an interim hack, so it could very well stop working in a future release of Macintalk Pro. Use at your own risk.
This call is used internally by TrackControl in order to
implement smooth acceleration when the user holds the mouse button down on an
arrow in a scrollbar. It can also be useful if you implement your own controls
that perform some repeated increment/decrement action as long as the user holds
the mouse button down. Heres the interface to it:
PROCEDURE UserDelay
(
StartTicks : LONGCARD;
CurrTicks : LONGCARD;
Limit : ShortCard
) : OSErr;
CODE
0303CH, 00500H, (* move.w #$500, d0 *)
0A84CH; (* _UserDelay *)
The idea is that you set StartTicks to the TickCount
at the start of the loop, while CurrTicks is updated each time
round the loop; the difference between these two values is used to gradually
decrease the delay time according to one of two different formulas, depending
on whether Limit is zero or not.
Note that the function never actually returns an error; its OSErr
result is always noErr.
The precise algorithm is to delay until the user releases the mouse button, or until
TickCount() >= CurrTicks + k1 + 108 DIV (CurrTicks - StartTicks + k2)If Limit = 0, then k1 = 0 and k2 = 9; if Limit is nonzero, then k1 = 3 and k2 = 12.
TrackControl always passes 0 for Limit.
Heres an example code sequence that outlines how to use UserDelay,
once youve determined that a mouse-down event has occurred within the appropriate
part of your control:
StartTicks := TickCount();
HiliteTheControl(TRUE);
Hilited := TRUE;
REPEAT
(* while the mouse is down *)
LastTicks := TickCount();
GetMouse(MouseWhere);
IF WithinControl(MouseWhere) THEN
(* turn highlighting on if off *)
IF NOT Hilited THEN
Hilited := TRUE;
HiliteTheControl(TRUE)
END (*IF*)
ELSE
(* turn highlighting off if on *)
IF Hilited THEN
Hilited := FALSE;
HiliteTheControl(FALSE)
END (*IF*)
END (*IF*);
IF Hilited THEN
InvokeControlAction;
Err := UserDelay
(
(*StartTicks :=*) StartTicks,
(*CurrTicks :=*) LastTicks,
(*Limit :=*) 0
)
END (*IF*)
UNTIL
NOT WaitMouseUp();
IF Hilited THEN
HiliteTheControl(FALSE)
END (*IF*)
In this example, HiliteTheControl turns control highlighting
on and off, WithinControl checks whether the mouse is still within
the appropriate part of the control, and InvokeControlAction
invokes whatever action is to be performed while the user holds the mouse button
down.
You can invoke any of the items from the System 7 application menu (the one
that drops from the application icon at the righthand end of the menu bar) by
using the SystemMenu call. The ID of this menu is -16489. In
particular, item number 1 hides the frontmost application; item 2 hides all
but the frontmost application; and item 3 shows all applications. These functions
work even when invoked from an application that is not the frontmost one.
Controlling the default applications for documents whose creators cant be found
When you double-click on a document for which no creator application can be found on any mounted volume, and the document is of one of a particular set of types (including text files and QuickDraw picture files), the Finder will ask you if you want to open the document using a particular application, usually SimpleText.
The nice thing is, the set of file types, and the choice of application to open them, are not hard-coded into the Finder, but are stored in a resource with a simple format. This is the Finders fmap resource with ID 17010.
The format is a simple sequence of eight-byte entries, terminated by eight bytes of zeroes. Each entry consists of an OSType file type, followed by the OSType signature of the application to use to open a file of that type if the original creator cannot be found. For example, here is what the standard set of mappings looks like in Finder 7.5.1:
54455854 74747874 -- TEXT ttxt -- open text files with SimpleText 50494354 74747874 -- PICT ttxt -- open QuickDraw picture files with SimpleText 6C747472 6C617032 -- lttr lap2 -- open PowerTalk letters with AppleMail 736A6F62 74747874 -- sjob ttxt -- open QuickDraw GX print files with SimpleText 726A6F62 74747874 -- rjob ttxt -- open QuickDraw GX print files with SimpleText 716A6F62 74747874 -- qjob ttxt -- open QuickDraw GX print files with SimpleText 00000000 00000000 -- end of list
You can change, add and remove entries, so long as you keep the all-zero entry at the end.