home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 April: Mac OS SDK / Dev.CD Apr 00 SDK1.toast / Development Kits / Mac OS / Translation Manager / Sample Code / Development Shell (old) / SampleFileTranslationExt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-05  |  16.5 KB  |  381 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        SampleFileTranslationExt.c 
  3.  
  4.     Contains:    Sample code shell for writing a File Translation Extension.
  5.     
  6.     Copyright:    © 1991-1992 by Apple Computer, Inc., all rights reserved.
  7.  
  8. */
  9.  
  10.  
  11.  
  12. #include <Resources.h>
  13. #include <Files.h>
  14. #include <Errors.h>
  15. #include "Components.h"
  16. #include "TranslationExtensions.h"
  17.  
  18.  
  19.  
  20. /*
  21.     Notes:    
  22.     
  23.         Errors:
  24.             All routines return OSErr's.  If they succeed they should return noErr.
  25.             The component manager requires all routines to return a ComponentResult
  26.             which is a 32-bit long to simplify dispatching.  If your code returns an OSErr
  27.             the compiler will automatically promote it to a long (ComponentResult).
  28.             
  29.         Globals:
  30.             Your routines can not use globals.  There really is no reason they should
  31.             need to use globals.  The three routines are separate and self contained.
  32.             If you persist and try to use PC relative globals, be warned that the 
  33.             ComponentMgr may purge and reload your code resource.  Therefore all
  34.             PC relative globals must be preinitailized at compile time (not load time).
  35.             Also, the ComponentMgr routine SetComponentInstanceStorage can not be
  36.             used, because InstanceStorage is already used by the TranslationMgr. 
  37.             
  38.         Memory allocation:
  39.             When one of your three routines is called, the default heap is a zone that 
  40.             the TranslationMgr allocated.  You should do all allocation in that heap.
  41.             Any leaks will be reclaimed when the heap is destroyed when your routine
  42.             returns.  WARNING: Do not leave any resource files open.  Their maps
  43.             will be left in the heap and trashed.  The ResourceMgr will soon croak.
  44.             
  45.         Resources:
  46.             If you need to access resources from your Translation Extension file, you
  47.             will need to use OpenComponentResFile() and CloseComponentResFile().
  48.             The open routine requires the ComponentInstance parameter supplied to 
  49.             your routine.
  50.         
  51.         Capabilities:
  52.             There are two kinds of translations: file and scrap.  There are three routines
  53.             for each.  In order to tell the TranslationMgr which kinds your extension
  54.             supports, you need to set the flags in the 'thng' resource.  The bit masks are
  55.             kSupportsFileTranslation and kSupportsScrapTranslation.
  56.             
  57. */
  58.  
  59.  
  60.  
  61. /***********************************************************************************************
  62. *
  63. *    The purpose of DoGetFileTranslationList is to tell the TranslationMgr what file formats 
  64. *    this extension can translate between.
  65. *    
  66. *    You are given the list that you built for the TranslationMgr last time, or if this is
  67. *    the first time you've been called, the list if empty (groupCount = 0, modDate = 0).
  68. *    
  69. *    You need to figure out if the file formats we can translate between has changed.  For
  70. *    example, the user has installed more translators. One way to check this is to compare
  71. *    the modDate of the list with the modDate of the file/folder of the translators.
  72. *    If it has not changed, you just return without changing the list.
  73. *    
  74. *
  75. *    Catalog information about your available translators 
  76. *    
  77. *    Divide the translators into groups.  Within each group, any of the 'src' formats
  78. *    can used with an of the 'dst' formats (any reader can be connected to any writer).
  79. *    
  80. *    Resize the translationList handle to hold all the information about each group.
  81. *    Fill in the translationList.  
  82. *    
  83. *    Use the modDate field as a "version" of the list.  When you are called again, you can
  84. *    use it to quickly check if the list needs to be rebuilt.  The TranslationMgr checks the
  85. *    modDate of the list before and after call you DoGetFileTranslationList.  If the modDate
  86. *    has changed, the TranslationMgr updates its internal tables of translation info and saves
  87. *    the new list to disk for use next time that DoGetFileTranslationList is called.
  88. *        
  89. *    The groupCount field is the number of groups in the list.
  90. *    Each group consists of a list of 'src' and 'dst' FileTypeSpec's. Each FileTypeSpec
  91. *    contains the FileType of the file format that will be read or written, a 32-bit hint,
  92. *    translation attributes, and the canonical HFS type and creator.
  93. *    This hint is for use by your File Translation Extension.  It is intended to be used to
  94. *    quickly locate the required translator.  
  95. *
  96. *    An example translationList that converts from WriteNow™ to MacWrite™ 5.0 documents would
  97. *    look list this:  
  98. *    
  99. *        0xA5BC1234        ; modDate 
  100. *        1                ; only 1 group
  101. *        1                ; 1 source type
  102. *        20                ; size of each entry = sizeof(FileTypeSpec)
  103. *        'nX^d'            ; WriteNow FileType
  104. *        0                ; hint for WriteNow FileType (0=unused)
  105. *        0                ; no attributes
  106. *        'nX^d'            ; HFS type of WriteNow documents
  107. *        'nX^n'            ; HFS creator of WriteNow documents
  108. *        1                ; 1 destination type
  109. *        20                ; size of each entry = sizeof(FileTypeSpec)
  110. *        'WORD'            ; MacWrite 5.0 FileType
  111. *        0                ; hint for MacWrite 5.0 FileType (0=unused)
  112. *        0                ; no attributes
  113. *        'WORD'            ; HFS type of MacWrite 5.0 documents
  114. *        'MACA'            ; HFS creator of MacWrite 5.0 documents
  115. *
  116. *
  117. *    If you return an error, the TranslationMgr will ignore your translation list.  This will 
  118. *    effectively disable your extension from being called.  When the machine is restarted,
  119. *    your DoGetFileTranslationList will get called again.   
  120. *    
  121. ************************************************************************************************/
  122. pascal ComponentResult DoGetFileTranslationList(ComponentInstance self, 
  123.                                                 FileTranslationListHandle translationList)
  124. {
  125. #pragma unused(self)
  126. #pragma unused(translationList)
  127.     return noErr;
  128. }
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136. /***********************************************************************************************
  137. *
  138. *    The purpose of DoIdentifyFile is to look at the data in a file and determine its FileType.
  139. *
  140. *    When a file needs to be translated, all installed File Translation Extensions are called 
  141. *    to identify the file.  If a Translation Extension can identify the file, the translation
  142. *    list for that extension is searched for the FileType as which it recognized the file.
  143. *    
  144. *    Thus, a Translation Extension is guaranteed that DoIdentifyFile will be called to recognize 
  145. *    a file before DoTranslateFile is called to convert it.
  146. *
  147. *    return noTypeErr if you do not recognize the document format.
  148. *    
  149. ************************************************************************************************/
  150. pascal ComponentResult DoIdentifyFile(ComponentInstance self, const FSSpec* theDoc, FileType* docKind)
  151. {
  152. #pragma unused(self)
  153. #pragma unused(theDoc)
  154. #pragma unused(docKind)
  155.     return noTypeErr;
  156. }
  157.  
  158.  
  159.  
  160.  
  161. #define progressAdvertismentResID    150
  162.  
  163. /***********************************************************************************************
  164. *
  165. *    The purpose of DoTranslateFile is to translate a file from one format to a file of another format.
  166. *    
  167. *    progressRefNum is a refum passed to the progress call back routines.
  168. *    srcDoc is the source document from which to read and translate.  
  169. *    srcType is the FileType of the source document as verified by DoIdentifyFile.
  170. *    srcTypeHint is the hint that was paired with srcType in your FileTranslationList.
  171. *    dstDoc is the destination document to which to write the translated file.
  172. *    dstType is the desired FileType of the translated file.
  173. *    dstTypeHint is the hint that was paired with dstType in your FileTranslationList.
  174. *    
  175. *    A note about 'hints'.  They are only hints.  Your extension must be able to operate without 
  176. *    them or if they are incorrect. 
  177. *    
  178. *    You can use all the standard File Manager and Memory Manager routines to accomplish the translation. 
  179. *    
  180. *    The first thing you should do is call SetTranslationAdvertisement.  It will draw the progress
  181. *    dialog window.  The PicHandle parameter is a handle to the PICT that will be drawn in 
  182. *    in the top of the progress dialog.  If it is NIL, no advertisment will be drawn, and the
  183. *    dialog will be shrunk down to eliminate the blank space. Note, this shrinking will also
  184. *    happen if you call UpdateTranslationProgress before SetTranslationAdvertisement.  The
  185. *    TranslationMgr will DisposeHandle the PICT when the translation is done.  Therefore,
  186. *    the PICT should be a non-purgable, non-resource handle.  If you store it as a resource 
  187. *    in your Translation Extension, use OpenComponentResFile and DetachResource.
  188. *
  189. *    You must periodically call the progress "call back" routine UpdateTranslationProgress.  
  190. *    You pass to it a number from one to one hundred that represents the chronological
  191. *    percentage of the translation that has been completed.
  192. *    The progress routine updates the progress status bar and handles the events a user can 
  193. *    do to cancel the translation.  If the user does cancel, that fact is returned to you by the
  194. *    progress routine.  You should abort the translation, clean up anything you have allocated
  195. *    and return userCancelErr.
  196. *
  197. ************************************************************************************************/
  198. pascal ComponentResult DoTranslateFile(ComponentInstance self, TranslationRefNum progressRefNum,
  199.                                             const FSSpec* srcDoc, FileType srcType, long srcTypeHint, 
  200.                                             const FSSpec* dstDoc, FileType dstType, long dstTypeHint)
  201. {
  202. #pragma unused(srcDoc)
  203. #pragma unused(srcType)
  204. #pragma unused(srcTypeHint)
  205. #pragma unused(dstDoc)
  206. #pragma unused(dstType)
  207. #pragma unused(dstTypeHint)
  208.  
  209.     // first thing to do is display progress dialog and show advertisment
  210.     {
  211.         Handle     advert;
  212.         short    myResFile;
  213.         
  214.         myResFile = OpenComponentResFile((Component)self);
  215.         if (myResFile != -1)
  216.         {
  217.             advert = GetResource('PICT', progressAdvertismentResID);
  218.             DetachResource(advert);
  219.             SetTranslationAdvertisement(progressRefNum, (PicHandle)advert);
  220.             CloseComponentResFile(myResFile);
  221.         };
  222.     }
  223.  
  224.  
  225.     return invalidTranslationPathErr;
  226. }
  227.  
  228.  
  229.  
  230.  
  231.  
  232.  
  233.  
  234. /***********************************************************************************************
  235. *
  236. *    The purpose of DoGetScrapTranslationList is to tell the TranslationMgr what scrap formats 
  237. *    this extension can translate between.
  238. *    
  239. *    You are given the list that you built for the TranslationMgr last time, or if this is
  240. *    the first time you've been called, the list if empty (groupCount = 0, modDate = 0).
  241. *    
  242. *    You need to figure out if the scrap formats you can translate between has changed.  For
  243. *    example, the user has installed more translators. One way to check this is to compare
  244. *    the modDate of the list with the modDate of the file/folder of the translators.
  245. *    If it has not changed, you just return without changing the list.
  246. *    
  247. *
  248. *    Catalog information about your available translators 
  249. *    
  250. *    Divide the translators into groups.  Within each group, any of the 'src' formats
  251. *    can used with an of the 'dst' formats (any reader can be connected to any writer).
  252. *    
  253. *    Resize the translationList handle to hold all the information about each group.
  254. *    Fill in the translationList.  
  255. *    
  256. *    Use the modDate field as a "version" of the list.  When you are called again, you can
  257. *    use it to quickly check if the list needs to be rebuilt.  The TranslationMgr checks the
  258. *    modDate of the list before and after call you DoGetFileTranslationList.  If the modDate
  259. *    has changed, the TranslationMgr updates its internal tables of translation info and saves
  260. *    the new list to disk for use next time that DoGetFileTranslationList is called.
  261. *        
  262. *    The groupCount field is the number of groups in the list.
  263. *    Each group consists of a list of 'src' and 'dst' ScrapTypeSpec's. Each ScrapTypeSpec
  264. *    contains the ScrapType of the format that will be read or written and a 32-bit hint.
  265. *    This hint is for use by your Scrap Translation Extension.  It is intended to be used to
  266. *    quickly locate the required translator.  
  267. *
  268. *    An example translationList that converts from MacDrawII scrap to a PICT would
  269. *    look list this:  
  270. *    
  271. *        0xA5BC1234        ; modDate 
  272. *        1                ; only 1 group
  273. *        8                ; size of each entry = sizeof(ScrapTypeSpec)
  274. *        1                ; 1 source type
  275. *        'MDPL'            ; MacDrawII ScrapType
  276. *        0                ; hint for MacDrawII ScrapType (0=unused)
  277. *        1                ; 1 destination type
  278. *        8                ; size of each entry = sizeof(ScrapTypeSpec)
  279. *        'PICT'            ; PICT ScrapType
  280. *        0                ; hint for PICT ScrapType (0=unused)
  281. *
  282. *
  283. *    Styled text is handled is a special manner.  The problem is that Styled Text requires two
  284. *    formats 'styl' and 'TEXT'.  The solution is an intermediate format 'stxt'.  It is a 'TEXT'
  285. *    handle concatenated onto the end of a 'styl' handle.  A translation extension that converts
  286. *    RTF to styled text would list 'RTF ' as a source format and 'stxt' as a destination format.
  287. *    The Translation Mgr deals with unpacking 'stxt' to get 'styl' or 'TEXT', as needed.
  288. *
  289. *
  290. *    If you return an error, the TranslationMgr will ignore your translation list.  This will 
  291. *    effectively disable your extension from being called.  When the machine is restarted,
  292. *    your DoGetFileTranslationList will get called again.   
  293. *    
  294. ************************************************************************************************/
  295. pascal ComponentResult DoGetScrapTranslationList(ComponentInstance self, ScrapTranslationListHandle list)
  296. {
  297. #pragma unused(self)
  298. #pragma unused(list)
  299.     return paramErr;
  300. }
  301.  
  302.  
  303.  
  304. /***********************************************************************************************
  305. *
  306. *    The purpose of DoIdentifyScrap is to look at the data in a buffer and determine its ScrapType.
  307. *
  308. *    When data needs to be translated, if an installed Scrap Translation Extensions says it can
  309. *    translate an existing ScrapType into a ScrapType that is required, the Translation Extension
  310. *    is called to verify the format of the data in the buffer.  
  311. *    
  312. *    Thus, a Translation Extension is guaranteed that DoIdentifyScrap will be called to recognize 
  313. *    data before DoTranslateScrap is called to convert it.
  314. *
  315. *    return noTypeErr if the data in the buffer is not the format you can translated.
  316. *    
  317. ************************************************************************************************/
  318. pascal ComponentResult DoIdentifyScrap(ComponentInstance self, const void* dataPtr, Size dataLength, ScrapType* dataFormat)
  319. {
  320. #pragma unused(self)
  321. #pragma unused(dataPtr)
  322. #pragma unused(dataLength)
  323. #pragma unused(dataFormat)
  324.     return paramErr;
  325. }
  326.  
  327.  
  328. /***********************************************************************************************
  329. *
  330. *    The purpose of DoTranslateScrap is to translate a buffer from one format to a buffer of another format.
  331. *    
  332. *    progressRefNum is a refum passed to the progress call back routines.
  333. *    srcDataPtr is a pointer to the source data from which to read and translate. 
  334. *    srcDataLength is the length of source data.
  335. *    srcType is the ScrapType of the source document as verified by DoIdentifyScrap.
  336. *    srcTypeHint is the hint that was paired with srcType in your FileTranslationList.
  337. *    dstData is the buffer into which to resize and write the translated data.
  338. *    dstType is the desired ScrapType of the translated file.
  339. *    dstTypeHint is the hint that was paired with dstType in your FileTranslationList.
  340. *    
  341. *    A note about 'hints'.  They are only hints.  Your extension must be able to operate without 
  342. *    them or if they are incorrect. 
  343. *    
  344. *    You can use all the standard toolbox routines to accomplish the translation. 
  345. *    
  346. *    The first thing you should do is call SetTranslationAdvertisement.  It will draw the progress
  347. *    dialog window.  The PicHandle parameter is a handle to the PICT that will be drawn in 
  348. *    in the top of the progress dialog.  If it is NIL, no advertisment will be drawn, and the
  349. *    dialog will be shrunk down to eliminate the blank space. Note, this shrinking will also
  350. *    happen if you call UpdateTranslationProgress before SetTranslationAdvertisement.  The
  351. *    TranslationMgr will DisposeHandle the PICT when the translation is done.  Therefore,
  352. *    the PICT should be a non-purgable, non-resource handle.  If you store it as a resource 
  353. *    in your Translation Extension, use OpenComponentResFile and DetachResource.
  354. *
  355. *    You must periodically call the progress "call back" routine UpdateTranslationProgress.  
  356. *    You pass to it a number from one to one hundred that represents the chronological
  357. *    percentage of the translation that has been completed.
  358. *    The progress routine updates the progress status bar and handles the events a user can 
  359. *    do to cancel the translation.  If the user does cancel, that fact is returned to you by the
  360. *    progress routine.  You should abort the translation, clean up anything you have allocated
  361. *    and return userCancelErr.
  362. *
  363. ************************************************************************************************/
  364. pascal ComponentResult DoTranslateScrap(ComponentInstance self, TranslationRefNum progressRefNum,
  365.                                         const void* srcDataPtr, Size srcDataLength, ScrapType srcType, long srcTypeHint,
  366.                                         Handle dstData, ScrapType dstType, long dstTypeHint)
  367. {
  368. #pragma unused(self)
  369. #pragma unused(progressRefNum)
  370. #pragma unused(srcDataPtr)
  371. #pragma unused(srcDataLength)
  372. #pragma unused(srcType)
  373. #pragma unused(srcTypeHint)
  374. #pragma unused(dstData)
  375. #pragma unused(dstType)
  376. #pragma unused(dstTypeHint)
  377.     return paramErr;
  378. }
  379.  
  380.  
  381.