Legacy Documentclose button

Important: The information in this document is obsolete and should not be used for new development.

Previous Book Contents Book Index Next

Inside Macintosh: More Macintosh Toolbox /
Chapter 7 - Translation Manager / Writing a Translation Extension


Dispatching to Translation Extension-Defined Routines

As explained in the previous section, the code stored in the translation extension component should be contained in a resource of type 'xlat'. The Component Manager expects that the entry point in this resource is a function having this format:

FUNCTION TranslateEntry (VAR params: ComponentParameters;
                         storage: Handle): ComponentResult;
The Component Manager calls your extension by passing TranslateEntry a request code in the params.what field of the components parameter record passed in the params parameter; TranslateEntry must interpret the request code and possibly dispatch to some other routine in the resource. Your extension must be able to handle the required request codes, defined by these constants:

CONST
   kComponentOpenSelect                   = -1;
   kComponentCloseSelect                  = -2;
   kComponentCanDoSelect                  = -3;
   kComponentVersionSelect                = -4;
For complete details on required request codes, see the chapter "Component Manager" in this book.

In addition, your extension must be able to respond to translation-specific request codes. Currently, Macintosh Easy Open defines these six request codes:

CONST
   kTranslateGetFileTranslationList       = 0;
   kTranslateIdentifyFile                 = 1;
   kTranslateTranslateFile                = 2;
   kTranslateGetScrapTranslationList      = 10;
   kTranslateIdentifyScrap                = 11;
   kTranslateTranslateScrap               = 12;
You can respond to these request codes by calling the Component Manager routine CallComponentFunctionWithStorage, passing it a pointer to a translation extension-defined routine. Listing 7-5 illustrates how to define a file translation extension entry point routine.

Listing 7-5 Handling Component Manager request codes

FUNCTION TranslateEntry (VAR params: ComponentParameters; 
                         storage: Handle): ComponentResult;
TYPE
   LongPtr     =  ^LongInt;
   LongHandle  =  ^LongPtr;
VAR
   mySelf:        ComponentInstance;
   myHandle:      Handle;
   selector:      Integer;
BEGIN
   CASE params.what OF
      kComponentOpenSelect:                  {component is opening}
         BEGIN
            mySelf := ComponentInstance(params.params[0]);
            myHandle := NewHandle(SizeOf(ComponentInstance));
            IF myHandle <> NIL THEN
            BEGIN
               LongHandle(myHandle)^^ := ORD4(mySelf);
               SetComponentInstanceStorage(mySelf, myHandle);
               TranslateEntry := noErr;
            END
            ELSE
               TranslateEntry := MemError;
         END;
      kComponentCloseSelect:                 {component is closing; clean up}
         BEGIN
            IF storage <> NIL THEN
               DisposeHandle(storage);
            TranslateEntry := noErr;
         END;
      kComponentCanDoSelect:                 {return known selectors}
         BEGIN
            selector := Integer((Ptr(params.params)^));
            IF (((kComponentVersionSelect <= selector) 
                  AND (selector <= kComponentOpenSelect))
               OR ((kTranslateGetFileTranslationList <= selector) 
                  AND (selector <= kTranslateTranslateFile))) THEN
               TranslateEntry := 1
            ELSE
               TranslateEntry := 0;
         END;
      kComponentVersionSelect:               {provide version number}
         TranslateEntry := kMyTranslateVersionNumber;
      kTranslateGetFileTranslationList:      {give file translation list}
         TranslateEntry := CallComponentFunctionWithStorage
                              (Handle(storage^^), params, 
                              ComponentFunction(@DoGetFileTranslationList));

      kTranslateIdentifyFile:                {identify a file}
         TranslateEntry := CallComponentFunctionWithStorage
                              (Handle(storage^^), params, 
                              ComponentFunction(@DoIdentifyFile));
      kTranslateTranslateFile:               {translate a file}
         TranslateEntry := CallComponentFunctionWithStorage
                              (Handle(storage^^), params, 
                              ComponentFunction(@DoTranslateFile));
      OTHERWISE                              {unrecognized selector}
         TranslateEntry := badComponentSelector;
   END; {CASE}
END;
As you can see, the TranslateEntry function defined in Listing 7-5 simply
inspects the params.what field to determine which request code to handle. For translation-specific request codes, it dispatches to the appropriate function in
the translation extension. See the following three sections for more details on handling translation-specific request codes.

Your extension can be dynamically loaded or unloaded at any time. When Macintosh Easy Open first discovers the extension, it loads it into memory and then asks it to return a list specifying which file or scrap types it can translate into which other types. Your extension is also called during a translation to identify files or scraps and, if necessary, to translate them.

Macintosh Easy Open loads your extension into a subheap of some existing heap. In all likelihood, your extension is loaded into either the system heap or temporary memory. In some cases, however, your extension might be loaded into an application's heap. Your extension is guaranteed 32 KB of available heap space. You should do all allocation in that heap using normal Memory Manager routines. Any memory leaks are reclaimed when your routine returns and the heap is destroyed.

There is no support for using global variables in the dispatcher defined in Listing 7-5. In general, the routines you need to implement are separate and self-contained, and so you shouldn't need to use global variables. You can, however, have your dispatcher set up an A5 world that contains global variables.

WARNING
If you use PC-relative global variables (that is, data addressed relative to the program counter), be warned that the Component Manager may purge and reload your code resource. Therefore, all PC-relative global variables must be preinitialized at compile time (not at load time).
If you need to access resources that are stored in your translation extension, you should use OpenComponentResFile and CloseComponentResFile. The open routine requires the ComponentInstance parameter supplied to your routine. See Listing 7-7 on page 7-33 for an example. You should not call the Resource Manager routines such as OpenResFile or CloseResFile.

WARNING
Do not leave any resource files open when your translation extension exits. Their maps will be left in the subheap when the subheap is freed, causing the Resource Manager to crash.
The following sections show how to respond to the kTranslateGetFileTranslationList, kTranslateIdentifyFile,
and kTranslateTranslateFile request codes by defining the three file translation extension functions DoGetFileTranslationList, DoIdentifyFile, and DoTranslateFile. You would handle scrap translation in a similar manner.


Previous Book Contents Book Index Next

© Apple Computer, Inc.
6 JUL 1996