home *** CD-ROM | disk | FTP | other *** search
/ The Best of Mecomp Multimedia 2 / MECOMP-CD-II.iso / amiga / datatypes / dtconvert / dtconvert.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-20  |  60.0 KB  |  1,896 lines

  1.  
  2. /*
  3. **
  4. **  $VER: DTConvert.c 1.8 (20.3.98)
  5. **  datatypes.library/Examples/DTConvert
  6. **
  7. **  Converts file into another format using datatypes
  8. **
  9. **  Main program and startup code
  10. **
  11. **  Written 1996-1998 by Roland 'Gizzy' Mainz
  12. **
  13. */
  14.  
  15. /* project includes */
  16. #include "DTConvert.h"
  17. #include "gui.h"
  18.  
  19. /* version string */
  20. #include "DTConvert_rev.h"
  21.  
  22. /*****************************************************************************/
  23.  
  24. /* list of datatypes, used in gadtools listview gadget */
  25. struct DTList
  26. {
  27.     struct List dtl_List;
  28.     UWORD       dtl_NumNodes;
  29.     APTR        dtl_Pool;
  30. };
  31.  
  32. /* single dtlist node */
  33. struct DTNode
  34. {
  35.     struct Node dtn_Node;
  36.     STRPTR      dtn_DTName;
  37.     /* dynamic bufferspace follows here */
  38. };
  39.  
  40.  
  41. /*****************************************************************************/
  42. /* shared libraries */
  43.  
  44. struct Library       *UtilityBase    = NULL;
  45. struct GfxBase       *GfxBase        = NULL;
  46. struct IntuitionBase *IntuitionBase  = NULL;
  47. struct Library       *GadToolsBase   = NULL;
  48. struct Library       *DataTypesBase  = NULL;
  49. struct Library       *AslBase        = NULL;
  50. struct Library       *IconBase       = NULL;
  51. struct Library       *WorkbenchBase  = NULL;
  52.  
  53. /*****************************************************************************/
  54.  
  55. /* version_string */
  56. STRPTR versionstring = VERSTAG;
  57.  
  58. /*****************************************************************************/
  59.  
  60. /* local prototypes */
  61. static                 void                 DefaultSettings( void );
  62. static                 void                 ClearRDA( void );
  63. static                 void                 ScanRDA( void );
  64. static                 void                 ScanToolTypes( TEXT ** );
  65. static                 void                 FreeInitProjectResult( void );
  66. static                 void                 ReadENVPrefs( void );
  67.  
  68. static                 BOOL                 CreateBasicResources( void );
  69. static                 void                 DeleteBasicResources( void );
  70.  
  71. static                 BOOL                 OpenLibStuff( void );
  72. static                 void                 CloseLibStuff( void );
  73.  
  74. static                 void                 RunTool( STRPTR );
  75.  
  76. static                 BOOL                 NewProject( STRPTR, STRPTR, STRPTR, BOOL, STRPTR );
  77.  
  78. static                 struct DTList       *CreateDTDescrList( BPTR, ULONG );
  79. static                 void                 FreeDTDescrList( struct DTList * );
  80. static                 struct DTNode       *FindDTNodeByName( struct DTList *, STRPTR );
  81.  
  82. static                 void                 LockGUI( void );
  83. static                 void                 UnlockGUI( void );
  84.  
  85. static                 STRPTR               StringSave( STRPTR );
  86. static                 STRPTR               AllocStringBuff( ULONG );
  87. static                 STRPTR               UpdateString( STRPTR *, STRPTR );
  88. static                 void                 FreeString( STRPTR );
  89.  
  90. static                 struct DiskObject   *GetToolDiskObject( STRPTR );
  91.  
  92. static                 ULONG                SumString( STRPTR );
  93.  
  94.  
  95. /*****************************************************************************/
  96.  
  97. long main_retval,
  98.      main_retval2;
  99.  
  100. static struct RDArgs  *startuprda;
  101.  
  102. /* mempool for strings */
  103. static APTR StringPool;
  104.  
  105. /*****************************************************************************/
  106.  
  107. /* template for ReadArgs */
  108. #define STARTUP_TEMPLATE "FROM=NAME=SRCNAME,"          \
  109.                          "DESTDATATYPE=DATATYPE=DTN,"  \
  110.                          "TO=DESTNAME,"                \
  111.                          "GUI/S,"                      \
  112.                          "PUBSCREEN/K"
  113.  
  114. #define ENV_TEMPLATE STARTUP_TEMPLATE /* equal because there are no /A switches */
  115.  
  116. static
  117. struct
  118. {
  119.     STRPTR  srcname;
  120.     STRPTR  destdatatype;
  121.     STRPTR  destname;
  122.     long   *gui;
  123.     STRPTR  pubscreen;
  124. } result;
  125.  
  126. static
  127. struct
  128. {
  129.     STRPTR  srcname;
  130.     STRPTR  destdatatype;
  131.     STRPTR  destname;
  132.     BOOL    gui;
  133.     STRPTR  pubscreen;
  134. } project;
  135.  
  136. /*****************************************************************************/
  137.  
  138. /****** DTConvert/DTConvert **************************************************
  139. *
  140. *    NAME
  141. *       DTConvert -- DataTypes-based conversion tool
  142. *
  143. *    FORMAT
  144. *       DTConvert [FROM|NAME|SRCNAME <file>]
  145. *                 [DESTDATATYPE|DATATYPE|DTN <datatype>]
  146. *                 [TO|DESTNAME <file>] [GUI] [PUBSCREEN <public screen>]
  147. *
  148. *    TEMPLATE
  149. *       FROM=NAME=SRCNAME,DESTDATATYPE=DATATYPE=DTN,TO=DESTNAME,GUI/S,
  150. *       PUBSCREEN/K
  151. *
  152. *    PURPOSE
  153. *       Convert data from one format into another format using datatypes
  154. *       classes.
  155. *
  156. *    DESCRIPTION
  157. *       DTConvert converts data from one format into another format,
  158. *       e.g. picture -> picture,
  159. *            animation -> anmation,
  160. *            movie -> movie,
  161. *            sound -> sound,
  162. *            text -> text (n/a)
  163. *
  164. *      You simply have to set the souce file name (SRCNAME), the
  165. *      datatype to convert to (DATATYPE) and the destination file name (TO).
  166. *
  167. *      The datatype option accepts the format names as they are written in
  168. *      DEVS:DataTypes, e.g. if you ant to save a mpeg video stream,
  169. *      you've to set DATATYPE="MPEG Video".
  170. *      If you want to use the base class (to save the incoming data to a 
  171. *      matching IFF format, simply specify the base class name, e.g.
  172. *      "picture" for picture.datatype, "sound" for sound.datatype, 
  173. *      "animation" for animation.datatype and so on.
  174. *
  175. *      If you miss one of the options or if you set the GUI switch, a small
  176. *      GUI will appear where you can set the options.
  177. *      If ou're done with setting all neccesary things in the GUI, the
  178. *      "Convert"-button gets enabled.
  179. *      Selection of the "Convert"-button starts the encoding job...
  180. *
  181. *    BUGS
  182. *      - picture.datatype V43 interface not implemented.
  183. *        This causes that any encoder only runs in V42 mode any may
  184. *        only encode 8 bit data.
  185. *
  186. *      - path names are limitted to 1024 chars, larger filenames may cause
  187. *        mailfunctions. But: Who uses so long path names ?
  188. *
  189. *      - datatypes.library versions V45.3 and V45.4 have a bug in
  190. *        NewDTObjectA which causes that a descriptor is unlocked too often,
  191. *        which results in an Alert( 3500000 ). >= V45.5 fixes this.
  192. *
  193. *    NOTES
  194. *      - picture.datatype V43 pixmap interface not supported.
  195. *
  196. *      - text conversion not supported yet.
  197. *
  198. *      - DTConvert prints a message if a subclass does not
  199. *        implement a local encoder. This was only done to get rid
  200. *        of mails like "your DTConvert has a bug: IFF ILBM -> PNG does
  201. *        not work...". These mails should go to the authors of the
  202. *        datatype classes, not to me. Sorry, but...
  203. *
  204. *    TODO
  205. *      - picture.datatype V43 compatibility
  206. *
  207. *      - text conversion (GID_TEXT -> GID_TEXT), e.g. IFF FTXT <-> Ascii
  208. *
  209. *      - document conversion (GID_DOCUMENT -> GID_DOCUMENT), after
  210. *        Stefan Ruppert and I finsished the document.datatype concepts.
  211. *
  212. *    HISTORY
  213. *       V1.1:
  214. *         - First release to dta@amigawolrd.com mailinglist.
  215. *
  216. *       V1.2:
  217. *         - Added support for animation.datatype subclasses
  218. *
  219. *       V1.3:
  220. *         - Minor fixes.
  221. *
  222. *       V1.4
  223. *         - Added support for sound.datatype V40 subclasses, partial support
  224. *           for suggested sound.datatype V41 interface.
  225. *
  226. *         - Added some usefull comments.
  227. *
  228. *         - WriteAnimClass/WriteSoundClass now sets
  229. *           SetIoErr( ERROR_REQUIRED_ARGUMENT_MISSING ); if something goes
  230. *           wrong (this should abort the encoder; only ERROR_OBJECT_NOT_FOUND
  231. *           is accepted here).
  232. *
  233. *         - Fixed some holes in the error handling.
  234. *
  235. *         - GUI added.
  236. *
  237. *         - Added WB support
  238. *
  239. *         - Added ENV variable support; a local or global (ENV) variable
  240. *           "DTConvert" takes the same arguments as the shell template.
  241. *           Variable settings can be overridden by any argument.
  242. *
  243. *         - Project split in seperate sources (e.g. main, GUI, converters)
  244. *
  245. *       V1.5
  246. *         - Added the feature that the datatypes selection requester shows
  247. *           only entries which match the source group IDs
  248. *           (if a source has been already selected).
  249. *
  250. *         - Added kluge which alows the conversion between GID_MOVIE
  251. *           and GID_ANIMATION datatypes (both are based on
  252. *           animation.datatype, here we have the same interface :-)
  253. *
  254. *         - Fixed the bug that ConvertAnimation function did not deal
  255. *           with truecolor bitmaps (e.g. CyberGFX bitmaps for example,
  256. *           truecolor bitmaps are indicated by ADTA_NumColors == 0.
  257. *           Fixed.
  258. *
  259. *       V1.6
  260. *         - Fixed the bug that ObtainDataTypeA was called for each
  261. *           INTUITICK if the datatype selection requester was open.
  262. *           Fixed.
  263. *
  264. *       V1.7
  265. *         - Fixed the bug that a descriptor was unlocked too often
  266. *           in some cases. See BUGS section above about a matching bug
  267. *           in datatypes.library V45.3 and V45.4 (V45.5 fixes this).
  268. *           Fixed (both "datatypes.library" and "DTConvert").
  269. *
  270. *         - The datatypes requester now accepts ESC as "Cancel" and
  271. *           RETURN as OK.
  272. *
  273. *         - The tool can now be aborted by SIGBREAKF_CTRL_C.
  274. *
  275. *         - Fixed the bug that somtimes an error return code
  276. *           was overwritting by the Message() function.
  277. *
  278. *         - Fixed the bug that the IFF comandline switch did not work
  279. *           (the GUI prompted everytimes in this case). But IFF and
  280. *           GUI switches does currently not co-operate :-(
  281. *
  282. *         - Fixed a bug in the WB startup code which caused that a project
  283. *           without an icon wasn't processed. The code now uses
  284. *           GetDiskObjectNew instead of GetDiskObject to fix this.
  285. *           Fixed.
  286. *
  287. *         - If launched from WB, "DTConvert" now opens a console window
  288. *           manually. Previously, the default WB output channel was used
  289. *           (which was NIL:).
  290. *           Same for project childs.
  291. *
  292. *         - Added output which prints a message if a subclass does not
  293. *           implement a local encoder. This was only done to get rid
  294. *           of mails like "your DTConvert has a bug: IFF ILBM -> PNG does
  295. *           not work...". These mails should go to the authors of the
  296. *           datatype classes, not to me. Sorry, but...
  297. *
  298. *         - If more than one project icon is given at WB startup, "DTConvert"
  299. *           now launches the matching number of projects instead
  300. *           of processing the given icons in sequence.
  301. *
  302. *         - Fixed problems with WB project startup and the current directory.
  303. *
  304. *         - The icon now contains the (possible) options and sets the
  305. *           stack size up to 16384 bytes.
  306. *
  307. *       V1.8
  308. *         - Shame on me. 
  309. *           In the last minutes of the V1.7 release build I
  310. *           decided to make "DTConvert" resident (using cres.o), which
  311. *           bombs out any __saved marked code has used by the animation
  312. *           converter section.
  313. *           Fixed.
  314. *
  315. *         - Completly removed the IFF switch because it was really
  316. *           unneccesary. If you want to save in the base class format,
  317. *           simply specify the name of the base class, e.g.
  318. *           "document" for documents,
  319. *           "text" for texts,
  320. *           "picture" for pictures,
  321. *           "sound" for sample data,
  322. *           "animation" for animation (and movies, due lack of a
  323. *               movie.datatype subclass)
  324. *           and so on...
  325. *           And the same from the GUI.
  326. *
  327. *         - The "no encoder"-message is now avoided if a base class did the
  328. *           encoder job.
  329. *
  330. *         - Added stack checking code. Now "DTConvert" forces the user
  331. *           to use at least 16k stack to et rid of stack related problems...
  332. *
  333. *         - Minor code cleanup.
  334. *
  335. *
  336. *    AUTHOR's REQUEST
  337. *        By  releasing  this program I do  not  place any obligations on you,
  338. *        feel free to share this program with your  friends (and enemies).
  339. *
  340. *        If you want to blame me, report any bugs, or wants a new version
  341. *        send your letter to:
  342. *                        Roland Mainz
  343. *                        Hohenstaufenstraße 8
  344. *                        52388 Nörvenich
  345. *                        GERMANY
  346. *
  347. *        Phone: (+49)(0)2426/901568
  348. *        Fax:   (+49)(0)2426/901569
  349. *
  350. *        EMAIL is also available:
  351. *        GISBURN@w-specht.rhein-ruhr.de
  352. *
  353. *        If you want to send me attachments larger than 1MB (up to 5MB,
  354. *        more with my permission):
  355. *        Up to April 1998 I'm reachable using this email address, too:
  356. *        Reinhold.A.Mainz@KBV.DE
  357. *
  358. *        | Please put your name and address in your mails !
  359. *        | German mailers should add their phone numbers.
  360. *        | See BUGS section above when submitting bug reports.
  361. *
  362. *        Sorry, but I can only look once a week for mails.
  363. *        If you don't hear something from me within three weeks, please
  364. *        send your mail again (but watch about new releases) (problems with
  365. *        this email port are caused by reconfigurations, hackers, network
  366. *        problems etc.).
  367. *
  368. *        The  entire  "DTConvert"  package may  be  noncommercially
  369. *        redistributed, provided  that  the package  is always  distributed
  370. *        in it's complete  form (including it's documentation).  A small copy
  371. *        fee for media costs is okay but any kind of commercial distribution
  372. *        is strictly forbidden! Comments  and  suggestions  how  to  improve
  373. *        this program  are generally appreciated!
  374. *
  375. *        Thanks to Matt Dillon for his DICE, David Junod for this datatypes
  376. *        environment and Olaf 'Olsen' Barthel for his help, ideas and some
  377. *        text clips from his documentations.
  378. *
  379. *    SEE ALSO
  380. *
  381. ******************************************************************************
  382. *
  383. */
  384.  
  385.  
  386. #ifdef _DCC
  387. /* disable CTRL_C break support (DICE CTRL_C abort function) */
  388. void chkabort( void )
  389. {
  390. }
  391.  
  392.  
  393. /* DICE workbench entry */
  394. long wbmain( struct WBStartup *wbstartup )
  395. {
  396.     /* Call main like SAS-C */
  397.     return( (int)main( 0L, (STRPTR *)wbstartup ) );
  398. }
  399. #endif /* _DCC */
  400.  
  401.  
  402. int main( int ac, STRPTR *av )
  403. {
  404.     LONG               numArgs,
  405.                        x;
  406.     struct WBStartup  *wbstartup;
  407.     struct WBArg      *wbarg;
  408.     struct DiskObject *tooldobj,
  409.                       *projectdobj;
  410.     BPTR               oldToolLock    = NULL,
  411.                        oldProjectLock = NULL;
  412.     BPTR               oldOutput      = NULL;
  413.  
  414.     main_retval2 = 0L;
  415.     main_retval  = RETURN_OK;
  416.  
  417.     if( CreateBasicResources() )
  418.     {
  419.       DefaultSettings();
  420.  
  421.       /* check if something goes wrong (ENV error etc.) */
  422.       if( main_retval == RETURN_OK )
  423.       {
  424. /* Workbench */
  425.         if( ac == 0L )
  426.         {
  427.           BPTR newOutput;
  428.  
  429.           /* Add "stdout" for Message() function...  */
  430.           if( newOutput = Open( "CON:////" NAME "/auto/wait/close", MODE_READWRITE ) )
  431.           {
  432.             oldOutput = SelectOutput( newOutput );
  433.           }
  434.  
  435.           wbstartup = (struct WBStartup *)av;
  436.  
  437.           numArgs = wbstartup -> sm_NumArgs;
  438.           wbarg   = wbstartup -> sm_ArgList;
  439.  
  440.           if( *(wbarg[ 0 ] . wa_Name) )
  441.           {
  442.             if( wbarg[ 0 ] . wa_Lock )
  443.             {
  444.               oldToolLock = CurrentDir( (wbarg[ 0 ] . wa_Lock) );
  445.             }
  446.  
  447.             if( tooldobj = GetToolDiskObject( (wbarg[ 0 ] . wa_Name) ) )
  448.             {
  449.               /* two possible cases when started from workbench ... */
  450.               if( numArgs < 2L )
  451.               {
  452.                 /* ... first case, only our tool icon is given, create one project here */
  453.  
  454.                 ScanToolTypes( (STRPTR *)(tooldobj -> do_ToolTypes) );
  455.  
  456.                 /* check if something goes wrong (parsing error, etc.) */
  457.                 if( main_retval == RETURN_OK )
  458.                 {
  459.                   RunTool( NULL );
  460.                 }
  461.  
  462.                 FreeInitProjectResult();
  463.               }
  464.               else
  465.               {
  466.                 /* ... second case, a couple of project icons are given, multiple projects will start from here */
  467.                 for( x = 1L ; x < numArgs ; x++ )
  468.                 {
  469.                   if( wbarg[ x ] . wa_Lock )
  470.                   {
  471.                     oldProjectLock = CurrentDir( (wbarg[ x ] . wa_Lock) );
  472.                   }
  473.  
  474.                   if( *(wbarg[ x ] . wa_Name) )
  475.                   {
  476.                     if( projectdobj = GetDiskObjectNew( (wbarg[ x ] . wa_Name) ) )
  477.                     {
  478.                       ScanToolTypes( (STRPTR *)(tooldobj -> do_ToolTypes) );
  479.                       ScanToolTypes( (STRPTR *)(projectdobj -> do_ToolTypes) );
  480.  
  481.                       /* check if something goes wrong (parsing error, etc.) */
  482.                       if( main_retval == RETURN_OK )
  483.                       {
  484.                         NewProject( ((project . srcname)?(project . srcname):((STRPTR)(wbarg[ x ] . wa_Name))),
  485.                                     (project . destdatatype),
  486.                                     (project . destname),
  487.                                     TRUE,
  488.                                     (project . pubscreen) );
  489.                       }
  490.  
  491.                       FreeInitProjectResult();
  492.                       DefaultSettings();
  493.  
  494.                       FreeDiskObject( projectdobj );
  495.                     }
  496.                   }
  497.  
  498.                   if( wbarg[ x ] . wa_Lock )
  499.                   {
  500.                     CurrentDir( oldProjectLock );
  501.                   }
  502.                 }
  503.               }
  504.  
  505.               FreeDiskObject( tooldobj );
  506.             }
  507.  
  508.             if( wbarg[ 0 ] . wa_Lock )
  509.             {
  510.               CurrentDir( oldToolLock );
  511.             }
  512.           }
  513.         }
  514.         else
  515.         {
  516. /* CLI/Shell */
  517.           if( startuprda = ReadArgs( STARTUP_TEMPLATE, (LONG *)(&result), NULL ) )
  518.           {
  519.             /* did we get a CTRL_C signal ? */
  520.             if( !CheckSignal( SIGBREAKF_CTRL_C ) )
  521.             {
  522.               ScanRDA();
  523.  
  524.               /* check if something goes wrong (parsing error, etc.) */
  525.               if( main_retval == RETURN_OK )
  526.               {
  527.                 RunTool( NULL );
  528.               }
  529.  
  530.               FreeInitProjectResult();
  531.             }
  532.             else
  533.             {
  534.               main_retval2 = ERROR_BREAK;
  535.               main_retval  = RETURN_WARN;
  536.             }
  537.  
  538.             FreeArgs( startuprda );
  539.           }
  540.           else
  541.           {
  542.             main_retval2 = IoErr();
  543.             main_retval  = RETURN_FAIL;
  544.           }
  545.         }
  546.       }
  547.  
  548.       DeleteBasicResources();
  549.     }
  550.  
  551.     PrintFault( main_retval2, NAME );
  552.  
  553.     /* Close WB stdout... */
  554.     if( oldOutput )
  555.     {
  556.       BPTR newOutput;
  557.  
  558.       newOutput = SelectOutput( oldOutput );
  559.  
  560.       (void)Close( newOutput );
  561.     }
  562.  
  563.     SetIoErr( main_retval2 );
  564.  
  565.     return( main_retval );
  566. }
  567.  
  568.  
  569. static
  570. void DefaultSettings( void )
  571. {
  572.     ClearRDA();
  573.  
  574.     memset( (void *)(&project), 0, sizeof( project ) );
  575.  
  576.     ReadENVPrefs();
  577. }
  578.  
  579.  
  580. static
  581. void ReadENVPrefs( void )
  582. {
  583.     struct RDArgs envvarrda =
  584.     {
  585.       NULL,
  586.       256L,
  587.       0L,
  588.       0L,
  589.       NULL,
  590.       0L,
  591.       NULL,
  592.       RDAF_NOPROMPT
  593.     };
  594.  
  595.     TEXT varbuff[ 258 ];
  596.  
  597.     envvarrda . RDA_Source . CS_Buffer = varbuff;
  598.  
  599.     if( GetVar( NAME, varbuff, 256L, 0UL ) != (-1L) )
  600.     {
  601.       strcat( varbuff, "\n" );
  602.  
  603.       if( ReadArgs( ENV_TEMPLATE, (LONG *)(&result), (&envvarrda) ) )
  604.       {
  605.         ScanRDA();
  606.  
  607.         FreeArgs( (&envvarrda) );
  608.       }
  609.       else
  610.       {
  611.         main_retval2 = IoErr();
  612.         main_retval  = RETURN_FAIL;
  613.       }
  614.     }
  615. }
  616.  
  617.  
  618. static
  619. void ClearRDA( void )
  620. {
  621.     memset( (void *)(&result), 0, sizeof( result ) );
  622. }
  623.  
  624.  
  625. static
  626. void ScanRDA( void )
  627. {
  628.     if( result . srcname )
  629.     {
  630.       UpdateString( (&(project . srcname)), (result . srcname) );
  631.     }
  632.  
  633.     if( result . destdatatype )
  634.     {
  635.       UpdateString( (&(project . destdatatype)), (result . destdatatype) );
  636.     }
  637.  
  638.     if( result . destname )
  639.     {
  640.       UpdateString( (&(project . destname)), (result . destname) );
  641.     }
  642.  
  643.     if( result . gui )
  644.     {
  645.       project . gui = TRUE;
  646.     }
  647.  
  648.     if( result . pubscreen )
  649.     {
  650.       UpdateString( (&(project . pubscreen)), (result . pubscreen) );
  651.     }
  652.  
  653.     ClearRDA();
  654. }
  655.  
  656.  
  657. static
  658. void ScanToolTypes( TEXT **tt )
  659. {
  660.     STRPTR s;
  661.  
  662.     if( s = FindToolType( tt, "FROM" ) )
  663.       result . srcname = s;
  664.  
  665.     if( s = FindToolType( tt, "NAME" ) )
  666.       result . srcname = s;
  667.  
  668.     if( s = FindToolType( tt, "SRCNAME" ) )
  669.       result . srcname = s;
  670.  
  671.     if( s = FindToolType( tt, "DESTDATATYPE" ) )
  672.       result . destdatatype = s;
  673.  
  674.     if( s = FindToolType( tt, "DATATYPE" ) )
  675.       result . destdatatype = s;
  676.  
  677.     if( s = FindToolType( tt, "DTN" ) )
  678.       result . destdatatype = s;
  679.  
  680.     if( s = FindToolType( tt, "TO" ) )
  681.       result . destname = s;
  682.  
  683.     if( s = FindToolType( tt, "DESTNAME" ) )
  684.       result . destname = s;
  685.  
  686.     if( s = FindToolType( tt, "GUI" ) )
  687.       result . gui = (long *)s;
  688.  
  689.     if( s = FindToolType( tt, "PUBSCREEN" ) )
  690.       result . pubscreen = s;
  691.  
  692.     ScanRDA();
  693. }
  694.  
  695.  
  696. static
  697. void FreeInitProjectResult( void )
  698. {
  699.     FreeString( (project . srcname) );
  700.     FreeString( (project . destdatatype) );
  701.     FreeString( (project . destname) );
  702.     FreeString( (project . pubscreen) );
  703. }
  704.  
  705.  
  706. static
  707. BOOL CreateBasicResources( void )
  708. {
  709.     if( OpenLibStuff() )
  710.     {
  711.       if( StringPool = CreatePool( (MEMF_PUBLIC | MEMF_CLEAR), 128UL, 128UL ) )
  712.       {
  713.         return( TRUE );
  714.  
  715. #ifdef COMMENTED_OUT
  716.         DeletePool( StringPool );
  717. #endif /* COMMENTED_OUT */
  718.       }
  719.  
  720.       CloseLibStuff();
  721.     }
  722.  
  723.     return( FALSE );
  724. }
  725.  
  726.  
  727. static
  728. void DeleteBasicResources( void )
  729. {
  730.     DeletePool( StringPool );
  731.     CloseLibStuff();
  732. }
  733.  
  734.  
  735. static
  736. BOOL OpenLibStuff( void )
  737. {
  738.     AttemptOpenLibrary( (&UtilityBase),                          NAME, "utility.library",     39UL );
  739.     AttemptOpenLibrary( (struct Library **)(&(GfxBase)),         NAME, "graphics.library",    39UL );
  740.     AttemptOpenLibrary( (struct Library **)(&(IntuitionBase)),   NAME, "intuition.library",   39UL );
  741.     AttemptOpenLibrary( (&GadToolsBase),                         NAME, "gadtools.library",    39UL );
  742.     AttemptOpenLibrary( (&DataTypesBase),                        NAME, "datatypes.library",   45UL );
  743.     AttemptOpenLibrary( (&IconBase),                             NAME, "icon.library",        39UL );
  744.     AttemptOpenLibrary( (&WorkbenchBase),                        NAME, "workbench.library",   39UL );
  745.     AttemptOpenLibrary( (&AslBase),                              NAME, "asl.library",         38UL );
  746.  
  747.     if( UtilityBase && GfxBase && IntuitionBase && GadToolsBase && DataTypesBase && IconBase && WorkbenchBase && AslBase  )
  748.     {
  749.       return( TRUE );
  750.     }
  751.  
  752.     CloseLibStuff();
  753.  
  754.     return( FALSE );
  755. }
  756.  
  757.  
  758. static
  759. void CloseLibStuff( void )
  760. {
  761.     CloseLibrary( AslBase );
  762.     CloseLibrary( WorkbenchBase );
  763.     CloseLibrary( IconBase );
  764.     CloseLibrary( DataTypesBase );
  765.     CloseLibrary( GadToolsBase );
  766.     CloseLibrary( (&(IntuitionBase -> LibNode)) );
  767.     CloseLibrary( (&(GfxBase -> LibNode)) );
  768.     CloseLibrary( UtilityBase );
  769. }
  770.  
  771.  
  772. static
  773. void RunTool( STRPTR srcname )
  774. {
  775.     struct Task *ThisTask  = FindTask( NULL );
  776.     ULONG        stacksize = (ULONG)(((UBYTE *)(ThisTask -> tc_SPReg)) - ((UBYTE *)(ThisTask -> tc_SPLower)));
  777.  
  778.     /* Enougth stack ? */
  779.     if( stacksize >= 8192UL )
  780.     {
  781.       STRPTR destname     = project . destname;
  782.       STRPTR datatypename = project . destdatatype;
  783.       BOOL   srcchanged   = FALSE;      /* srcname changed ? */
  784.       ULONG  srcsum       = SumString( srcname );
  785.  
  786.       if( project . srcname )
  787.       {
  788.         srcname = project . srcname;
  789.       }
  790.  
  791.       /* Check if datatype name is valid */
  792.       if( datatypename )
  793.       {
  794.         struct DataType *dtn;
  795.  
  796.         if( dtn = ObtainDataTypeA( DTST_RAM, (APTR)datatypename, NULL ) )
  797.         {
  798.           ReleaseDataType( dtn );
  799.         }
  800.         else
  801.         {
  802.           datatypename = NULL;
  803.         }
  804.       }
  805.  
  806.       /* GUI requested / required (some ares are missing and the user should fill them in) ? */
  807.       if( (project . gui) || (srcname == NULL) || (destname == NULL) || (datatypename == NULL) )
  808.       {
  809.         struct MsgPort *appport;
  810.         struct DTList  *dtl;
  811.         struct DTNode  *selecteddt;
  812.  
  813.         if( appport = CreateMsgPort() )
  814.         {
  815.           BPTR srclock = NULL;
  816.  
  817.           if( Strlen( srcname ) )
  818.           {
  819.             srclock = Lock( srcname, SHARED_LOCK );
  820.           }
  821.  
  822.           if( dtl = CreateDTDescrList( srclock, 0UL ) )
  823.           {
  824.             PubScreenName = project . pubscreen; /* set pubscreen name for GadToolsBox's windows */
  825.  
  826.             selecteddt = FindDTNodeByName( dtl, datatypename );
  827.  
  828.             if( !SetupScreen() )
  829.             {
  830.               struct FileRequester *SrcFileReq  = NULL,
  831.                                    *DestFileReq = NULL;
  832.  
  833.               if( !OpenDTConvert_MAINWindow() )
  834.               {
  835.                 BOOL                 done             = FALSE;
  836.                 struct IntuiMessage *imsg;
  837.                 ULONG                sigmask;
  838.                 BOOL                 get_source       = FALSE,
  839.                                      get_datatype     = FALSE,
  840.                                      get_destination  = FALSE;
  841.                 BOOL                 convert          = FALSE;
  842.                 BOOL                 convertable      = Strlen( srcname ) && selecteddt && Strlen( destname );
  843.                 struct AppWindow    *appwindow        = NULL;
  844.                 struct DiskObject   *appdobj          = NULL;
  845.                 struct AppIcon      *appicon          = NULL;
  846.  
  847.                 /* Running on WB screen ? */
  848.                 if( ((DTConvert_MAINWnd -> WScreen -> Flags) & SCREENTYPE) == WBENCHSCREEN )
  849.                 {
  850.                   appwindow = AddAppWindowA( 0UL, 0UL, DTConvert_MAINWnd, appport, NULL );
  851.                 }
  852.                 else
  853.                 {
  854.                   if( appdobj = GetDefDiskObject( WBPROJECT ) )
  855.                   {
  856.                     /* Not running on workbench screen ? - Create AppIcon for wb app support ! */
  857.                     appicon = AddAppIconA( 0UL, 0UL, NAME, appport, NULL, appdobj, NULL );
  858.                   }
  859.                 }
  860.  
  861.                 GT_SetGadgetAttrs( DTConvert_MAINGadgets[ GD_SOURCE ],      DTConvert_MAINWnd, NULL, GTST_String, srcname,                                                  TAG_DONE );
  862.                 GT_SetGadgetAttrs( DTConvert_MAINGadgets[ GD_DATATYPE ],    DTConvert_MAINWnd, NULL, GTTX_Text,   ((selecteddt)?(selecteddt -> dtn_Node . ln_Name):(NULL)), TAG_DONE );
  863.                 GT_SetGadgetAttrs( DTConvert_MAINGadgets[ GD_DESTINATION ], DTConvert_MAINWnd, NULL, GTST_String, destname,                                                 TAG_DONE );
  864.                 GT_SetGadgetAttrs( DTConvert_MAINGadgets[ GD_CONVERT ],     DTConvert_MAINWnd, NULL, GA_Disabled, (!convertable),                                           TAG_DONE );
  865.  
  866.                 /*******************
  867.                  * Main event loop *
  868.                  *******************/
  869.                 while( !done )
  870.                 {
  871.                   ULONG sigr;
  872.  
  873.                   sigmask = (1UL << (DTConvert_MAINWnd -> UserPort -> mp_SigBit)) |
  874.                             (1UL << (appport -> mp_SigBit))                       |
  875.                             SIGBREAKF_CTRL_C;
  876.  
  877.                   if( DTConvert_DATATYPEWnd )
  878.                   {
  879.                     sigmask |= (1UL << (DTConvert_DATATYPEWnd -> UserPort -> mp_SigBit));
  880.                   }
  881.  
  882.                   sigr = Wait( sigmask );
  883.  
  884. /* Main window */
  885.                   if( sigr & (1UL << (DTConvert_MAINWnd -> UserPort -> mp_SigBit)) )
  886.                   {
  887.                     while( imsg = GT_GetIMsg( (DTConvert_MAINWnd -> UserPort) ) )
  888.                     {
  889.                       switch( imsg -> Class )
  890.                       {
  891.                         case IDCMP_CLOSEWINDOW:
  892.                         {
  893.                             done = TRUE;
  894.                         }
  895.                             break;
  896.  
  897.                         case IDCMP_REFRESHWINDOW:
  898.                         {
  899.                             GT_BeginRefresh( (imsg -> IDCMPWindow) );
  900.                             GT_EndRefresh( (imsg -> IDCMPWindow), TRUE );
  901.                         }
  902.                             break;
  903.  
  904.                         case IDCMP_GADGETUP:
  905.                         {
  906.                             switch( G( (imsg -> IAddress) ) -> GadgetID )
  907.                             {
  908.                               case GD_SOURCE: break;   /* NOP */
  909.  
  910.                               case GD_DATATYPE: break; /* NOP */
  911.  
  912.                               case GD_DESTINATION: break; /* NOP */
  913.  
  914.                               case GD_GET_SOURCE:
  915.                               {
  916.                                   get_source = TRUE;
  917.                               }
  918.                                   break;
  919.  
  920.                               case GD_GET_DATATYPE:
  921.                               {
  922.                                   get_datatype = TRUE;
  923.                               }
  924.                                   break;
  925.  
  926.                               case GD_GET_DESTINATION:
  927.                               {
  928.                                   get_destination = TRUE;
  929.                               }
  930.                                   break;
  931.  
  932.                               case GD_CONVERT:
  933.                               {
  934.                                   convert = TRUE;
  935.                               }
  936.                                   break;
  937.  
  938.                               case GD_CANCEL:
  939.                               {
  940.                                   done = TRUE;
  941.                               }
  942.                                   break;
  943.                             }
  944.                         }
  945.                             break;
  946.  
  947.                         case IDCMP_VANILLAKEY:
  948.                         {
  949.                             switch( imsg -> Code )
  950.                             {
  951.                               case 's': /* Source */
  952.                                   ActivateGadget( DTConvert_MAINGadgets[ GD_SOURCE ], DTConvert_MAINWnd, NULL );
  953.                                   break;
  954.  
  955.                               case 'S': /* Get Source */
  956.                                   get_source = TRUE;
  957.                                   break;
  958.  
  959.                               case 't': /* datatype */
  960.                               case 'T': /* datatype */
  961.                                   get_datatype = TRUE;
  962.                                   break;
  963.  
  964.                               case 'd': /* Destination */
  965.                                   ActivateGadget( DTConvert_MAINGadgets[ GD_DESTINATION ], DTConvert_MAINWnd, NULL );
  966.                                   break;
  967.  
  968.                               case 'D': /* Get Destination */
  969.                                   get_destination = TRUE;
  970.                                   break;
  971.  
  972.                               case 'c': /* Convert */
  973.                               case 'C': /* Convert */
  974.                               {
  975.                                   convert = TRUE;
  976.                               }
  977.                                   break;
  978.  
  979.                               case 'a': /* Cancel */
  980.                               case 'A': /* Cancel */
  981.                               {
  982.                                   done = TRUE;
  983.                               }
  984.                                   break;
  985.                             }
  986.                         }
  987.                             break;
  988.                       }
  989.  
  990.                       GT_ReplyIMsg( imsg );
  991.                     }
  992.                   }
  993.  
  994. /* DataTypes requester */
  995.                   if( DTConvert_DATATYPEWnd )
  996.                   {
  997.                     if( sigr & (1UL << (DTConvert_DATATYPEWnd -> UserPort -> mp_SigBit)) )
  998.                     {
  999.                       BOOL  dtdone = FALSE;
  1000.                       BOOL  dtok   = FALSE;
  1001.                       LONG  oldselected,
  1002.                             selected;
  1003.  
  1004.                       GT_GetGadgetAttrs( DTConvert_DATATYPEGadgets[ GD_DATATYPEDT ], DTConvert_DATATYPEWnd, NULL,
  1005.                                          GTLV_Selected, (&oldselected),
  1006.                                          TAG_DONE );
  1007.  
  1008.                       selected = oldselected;
  1009.  
  1010.                       while( imsg = GT_GetIMsg( (DTConvert_DATATYPEWnd -> UserPort) ) )
  1011.                       {
  1012.                         switch( imsg -> Class )
  1013.                         {
  1014.                           case IDCMP_CLOSEWINDOW:
  1015.                           {
  1016.                               dtdone = TRUE;
  1017.                           }
  1018.                               break;
  1019.  
  1020.                           case IDCMP_REFRESHWINDOW:
  1021.                           {
  1022.                               GT_BeginRefresh( (imsg -> IDCMPWindow) );
  1023.                               GT_EndRefresh( (imsg -> IDCMPWindow), TRUE );
  1024.                           }
  1025.                               break;
  1026.  
  1027.                           case IDCMP_GADGETUP:
  1028.                           {
  1029.                               switch( G( (imsg -> IAddress) ) -> GadgetID )
  1030.                               {
  1031.                                 case GD_DATATYPEDT: break; /* NOP */
  1032.  
  1033.                                 case GD_OKDT:
  1034.                                 {
  1035.                                     dtdone = dtok = TRUE;
  1036.                                 }
  1037.                                     break;
  1038.  
  1039.                                 case GD_CANCELDT:
  1040.                                 {
  1041.                                     dtdone = TRUE;
  1042.                                 }
  1043.                                     break;
  1044.                               }
  1045.                           }
  1046.                               break;
  1047.  
  1048.                           case IDCMP_VANILLAKEY:
  1049.                           {
  1050.                               switch( imsg -> Code )
  1051.                               {
  1052.                                 case 'o':  /* Ok */
  1053.                                 case 'O':  /* Ok */
  1054.                                 case '\r': /* Ok */
  1055.                                     dtdone = dtok = TRUE;
  1056.                                     break;
  1057.  
  1058.                                 case 'c': /* Cancel */
  1059.                                 case 'C': /* Cancel */
  1060.                                 case  27: /* ESC == Cancel */
  1061.                                     dtdone = TRUE;
  1062.                                     break;
  1063.  
  1064.                                 case 'd': /* DT Selection down */
  1065.                                 {
  1066.                                     selected++;
  1067.                                 }
  1068.                                     break;
  1069.  
  1070.                                 case 'D': /* DT Selection up */
  1071.                                 {
  1072.                                     selected--;
  1073.                                 }
  1074.                                     break;
  1075.                               }
  1076.                           }
  1077.                               break;
  1078.  
  1079.                           case IDCMP_RAWKEY:
  1080.                           {
  1081.                               switch( imsg -> Code )
  1082.                               {
  1083.                                 case 76: /* up */
  1084.                                 {
  1085.                                     if( (imsg -> Qualifier) & (IEQUALIFIER_LALT | IEQUALIFIER_RALT) )
  1086.                                     {
  1087.                                       selected = 0L; /* top */
  1088.                                     }
  1089.                                     else
  1090.                                     {
  1091.                                       if( (imsg -> Qualifier) & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT) )
  1092.                                       {
  1093.                                         selected -= 5L; /* page up */
  1094.                                       }
  1095.                                       else
  1096.                                       {
  1097.                                         selected--; /* previous entry */
  1098.                                       }
  1099.                                     }
  1100.                                 }
  1101.                                     break;
  1102.  
  1103.                                 case 77: /* down */
  1104.                                 {
  1105.                                     if( (imsg -> Qualifier) & (IEQUALIFIER_LALT | IEQUALIFIER_RALT) )
  1106.                                     {
  1107.                                       selected = dtl -> dtl_NumNodes; /* bottom */
  1108.                                     }
  1109.                                     else
  1110.                                     {
  1111.                                       if( (imsg -> Qualifier) & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT) )
  1112.                                       {
  1113.                                         selected += 5L; /* page down */
  1114.                                       }
  1115.                                       else
  1116.                                       {
  1117.                                         selected++; /* next entry */
  1118.                                       }
  1119.                                     }
  1120.                                 }
  1121.                                     break;
  1122.                               }
  1123.                           }
  1124.                               break;
  1125.                         }
  1126.  
  1127.                         /* Check bounds */
  1128.                         if( selected < 0L )
  1129.                         {
  1130.                           selected = 0L;
  1131.                         }
  1132.                         else
  1133.                         {
  1134.                           if( selected > (LONG)(dtl -> dtl_NumNodes) )
  1135.                           {
  1136.                             selected = (LONG)(dtl -> dtl_NumNodes);
  1137.                           }
  1138.                         }
  1139.  
  1140.                         GT_ReplyIMsg( imsg );
  1141.                       }
  1142.  
  1143.                       if( selected != oldselected )
  1144.                       {
  1145.                         GT_SetGadgetAttrs( DTConvert_DATATYPEGadgets[ GD_DATATYPEDT ], DTConvert_DATATYPEWnd, NULL,
  1146.                                            GTLV_Selected,    selected,
  1147.                                            GTLV_MakeVisible, selected,
  1148.                                            TAG_DONE );
  1149.                       }
  1150.  
  1151.                       if( dtok )
  1152.                       {
  1153.                         if( selecteddt = (struct DTNode *)GetNumNode( (&(dtl -> dtl_List)), selected ) )
  1154.                         {
  1155.                           GT_SetGadgetAttrs( DTConvert_MAINGadgets[ GD_DATATYPE ], DTConvert_MAINWnd, NULL,
  1156.                                              GTTX_Text, (selecteddt -> dtn_Node . ln_Name),
  1157.                                              TAG_DONE );
  1158.                         }
  1159.                       }
  1160.  
  1161.                       if( dtdone )
  1162.                       {
  1163.                         CloseDTConvert_DATATYPEWindow();
  1164.                       }
  1165.                     }
  1166.                   }
  1167.  
  1168. /* appwindow / appicon port */
  1169.                   if( sigr & (1UL << (appport -> mp_SigBit)) )
  1170.                   {
  1171.                     struct AppMessage *amsg;
  1172.  
  1173.                     while( amsg = (struct AppMessage *)GetMsg( appport ) )
  1174.                     {
  1175.                       switch( amsg -> am_Type )
  1176.                       {
  1177.                         case AMTYPE_APPWINDOW:
  1178.                         case AMTYPE_APPICON:
  1179.                         {
  1180.                             if( amsg -> am_NumArgs )
  1181.                             {
  1182.                               LockGUI();
  1183.  
  1184.                                 if( (amsg -> am_NumArgs) == 1UL )
  1185.                                 {
  1186.                                   STRPTR name;
  1187.  
  1188.                                   if( name = GetLockName( (amsg -> am_ArgList[ 0 ] . wa_Lock), (amsg -> am_ArgList[ 0 ] . wa_Name) ) )
  1189.                                   {
  1190.                                     GT_SetGadgetAttrs( DTConvert_MAINGadgets[ GD_SOURCE ], DTConvert_MAINWnd, NULL, GTST_String, name, TAG_DONE );
  1191.  
  1192.                                     FreeVec( name );
  1193.                                   }
  1194.                                 }
  1195.                                 else
  1196.                                 {
  1197.                                   ULONG i;
  1198.  
  1199.                                   for( i = 0UL ; i < (amsg -> am_NumArgs) ; i++ )
  1200.                                   {
  1201.                                     BPTR oldProjectLock = NULL;
  1202.  
  1203.                                     if( amsg -> am_ArgList[ i ] . wa_Lock )
  1204.                                     {
  1205.                                       oldProjectLock = CurrentDir( (amsg -> am_ArgList[ i ] . wa_Lock) );
  1206.                                     }
  1207.  
  1208.                                     NewProject( (amsg -> am_ArgList[ 0 ] . wa_Name), ((selecteddt)?(selecteddt -> dtn_DTName):(NULL)), destname, TRUE, (project . pubscreen) );
  1209.  
  1210.                                     if( amsg -> am_ArgList[ i ] . wa_Lock )
  1211.                                     {
  1212.                                       (void)CurrentDir( oldProjectLock );
  1213.                                     }
  1214.                                   }
  1215.                                 }
  1216.  
  1217.                               UnlockGUI();
  1218.                             }
  1219.                         }
  1220.                             break;
  1221.                       }
  1222.  
  1223.                       ReplyMsg( (&(amsg -> am_Message)) );
  1224.                     }
  1225.                   }
  1226.  
  1227.                   /* Quit signal ? */
  1228.                   if( sigr & SIGBREAKF_CTRL_C )
  1229.                   {
  1230.                     done = TRUE;
  1231.                   }
  1232.  
  1233. /* process collected events */
  1234.                   if( get_source || get_datatype || get_destination )
  1235.                   {
  1236.                     LockGUI();
  1237.  
  1238.                       if( get_source )
  1239.                       {
  1240.                         if( SrcFileReq == NULL )
  1241.                         {
  1242.                           SrcFileReq = (struct FileRequester *)AllocAslRequestTags( ASL_FileRequest,
  1243.                                                                                     ASLFR_Screen,          (DTConvert_MAINWnd -> WScreen),
  1244.                                                                                     ASLFR_TitleText,       "Open File...",
  1245.                                                                                     ASLFR_InitialLeftEdge, ((DTConvert_MAINWnd -> LeftEdge) + (DTConvert_MAINWnd -> BorderLeft) + 1UL),
  1246.                                                                                     ASLFR_InitialTopEdge,  ((DTConvert_MAINWnd -> TopEdge)  + (DTConvert_MAINWnd -> BorderTop) + 1UL),
  1247.                                                                                     ASLFR_DoPatterns,      TRUE,
  1248.                                                                                     TAG_DONE );
  1249.                         }
  1250.  
  1251.                         if( SrcFileReq )
  1252.                         {
  1253.                           if( AslRequest( SrcFileReq, NULL ) )
  1254.                           {
  1255.                             ULONG  buffsize;
  1256.                             STRPTR filebuffer;
  1257.  
  1258.                             buffsize = Strlen( (SrcFileReq -> fr_Drawer) ) + Strlen( (SrcFileReq -> fr_File) ) + 10UL;
  1259.  
  1260.                             if( filebuffer = (STRPTR)AllocVec( buffsize, MEMF_PUBLIC ) )
  1261.                             {
  1262.                               strcpy( filebuffer, (SrcFileReq -> fr_Drawer) );
  1263.                               AddPart( filebuffer, (SrcFileReq -> fr_File), buffsize );
  1264.  
  1265.                               GT_SetGadgetAttrs( DTConvert_MAINGadgets[ GD_SOURCE ], DTConvert_MAINWnd, NULL, GTST_String, filebuffer, TAG_DONE );
  1266.  
  1267.                               FreeVec( filebuffer );
  1268.                             }
  1269.                           }
  1270.                         }
  1271.  
  1272.                         get_source = FALSE;
  1273.                       }
  1274.  
  1275.                       if( get_datatype )
  1276.                       {
  1277.                         if( DTConvert_DATATYPEWnd == NULL )
  1278.                         {
  1279.                           if( !OpenDTConvert_DATATYPEWindow() )
  1280.                           {
  1281.                             GT_SetGadgetAttrs( DTConvert_DATATYPEGadgets[ GD_DATATYPEDT ], DTConvert_DATATYPEWnd, NULL, GTLV_Labels, dtl, TAG_DONE );
  1282.                           }
  1283.                         }
  1284.  
  1285.                         get_datatype = FALSE;
  1286.                       }
  1287.  
  1288.                       if( get_destination )
  1289.                       {
  1290.                         if( DestFileReq == NULL )
  1291.                         {
  1292.                           DestFileReq = (struct FileRequester *)AllocAslRequestTags( ASL_FileRequest,
  1293.                                                                                      ASLFR_Screen,          (DTConvert_MAINWnd -> WScreen),
  1294.                                                                                      ASLFR_TitleText,       "Save File...",
  1295.                                                                                      ASLFR_InitialLeftEdge, ((DTConvert_MAINWnd -> LeftEdge) + (DTConvert_MAINWnd -> BorderLeft) + 1UL),
  1296.                                                                                      ASLFR_InitialTopEdge,  ((DTConvert_MAINWnd -> TopEdge)  + (DTConvert_MAINWnd -> BorderTop) + 1UL),
  1297.                                                                                      ASLFR_DoPatterns,      TRUE,
  1298.                                                                                      ASLFR_DoSaveMode,      TRUE,
  1299.                                                                                      TAG_DONE );
  1300.                         }
  1301.  
  1302.                         if( DestFileReq )
  1303.                         {
  1304.                           if( AslRequest( DestFileReq, NULL ) )
  1305.                           {
  1306.                             ULONG  buffsize;
  1307.                             STRPTR filebuffer;
  1308.  
  1309.                             buffsize = Strlen( (DestFileReq -> fr_Drawer) ) + Strlen( (DestFileReq -> fr_File) ) + 10UL;
  1310.  
  1311.                             if( filebuffer = (STRPTR)AllocVec( buffsize, MEMF_PUBLIC ) )
  1312.                             {
  1313.                               strcpy( filebuffer, (DestFileReq -> fr_Drawer) );
  1314.                               AddPart( filebuffer, (DestFileReq -> fr_File), buffsize );
  1315.  
  1316.                               GT_SetGadgetAttrs( DTConvert_MAINGadgets[ GD_DESTINATION ], DTConvert_MAINWnd, NULL, GTST_String, filebuffer, TAG_DONE );
  1317.  
  1318.                               FreeVec( filebuffer );
  1319.                             }
  1320.                           }
  1321.                         }
  1322.  
  1323.                         get_destination = FALSE;
  1324.                       }
  1325.  
  1326.                     UnlockGUI();
  1327.                   }
  1328.  
  1329. /* update */
  1330.                   GT_GetGadgetAttrs( DTConvert_MAINGadgets[ GD_SOURCE ], DTConvert_MAINWnd, NULL,
  1331.                                      GTST_String, (&srcname),
  1332.                                      TAG_DONE );
  1333.  
  1334.  
  1335.                   /* My quick hack to check if the src filename has been changed... */
  1336.                   srcchanged = (SumString( srcname ) != srcsum);
  1337.  
  1338.                   /* following block is experimental...  */
  1339.                   if( srcchanged )
  1340.                   {
  1341.                     struct DTList *old_dtl = dtl;
  1342.  
  1343.                     /* Update checksum... */
  1344.                     srcsum = SumString( srcname );
  1345.  
  1346.                     if( srclock )
  1347.                     {
  1348.                       UnLock( srclock );
  1349.                       srclock = NULL;
  1350.                     }
  1351.  
  1352.                     if( Strlen( srcname ) )
  1353.                     {
  1354.                       srclock = Lock( srcname, SHARED_LOCK );
  1355.                     }
  1356.  
  1357.                     dtl = CreateDTDescrList( srclock, 0UL );
  1358.  
  1359.                     if( selecteddt )
  1360.                     {
  1361.                       selecteddt = FindDTNodeByName( dtl, (selecteddt -> dtn_DTName) );
  1362.  
  1363.                       GT_SetGadgetAttrs( DTConvert_MAINGadgets[ GD_DATATYPE ], DTConvert_MAINWnd, NULL,
  1364.                                          GTTX_Text, ((selecteddt)?(selecteddt -> dtn_Node . ln_Name):("")),
  1365.                                          TAG_DONE );
  1366.                     }
  1367.  
  1368.                     /* update DataTypes selection gadget */
  1369.                     if( DTConvert_DATATYPEWnd )
  1370.                     {
  1371.                       GT_SetGadgetAttrs( DTConvert_DATATYPEGadgets[ GD_DATATYPEDT ], DTConvert_DATATYPEWnd, NULL, GTLV_Labels, dtl, TAG_DONE );
  1372.                     }
  1373.  
  1374.                     FreeDTDescrList( old_dtl );
  1375.                   }
  1376.  
  1377.                   GT_GetGadgetAttrs( DTConvert_MAINGadgets[ GD_DESTINATION ], DTConvert_MAINWnd, NULL,
  1378.                                      GTST_String, (&destname),
  1379.                                      TAG_DONE );
  1380.  
  1381.                   convertable = Strlen( srcname ) && selecteddt && Strlen( destname );
  1382.  
  1383.                   GT_SetGadgetAttrs( DTConvert_MAINGadgets[ GD_CONVERT ], DTConvert_MAINWnd, NULL,
  1384.                                      GA_Disabled, (!convertable),
  1385.                                      TAG_DONE );
  1386.  
  1387. /* run converter ? */
  1388.                   if( convert )
  1389.                   {
  1390.                     if( convertable )
  1391.                     {
  1392.                       LockGUI();
  1393.  
  1394.                         Message( "converting '%s' '%s' '%s'\n", srcname, (selecteddt -> dtn_DTName), destname );
  1395.  
  1396.                         Convert( srcname, (selecteddt -> dtn_DTName), destname );
  1397.  
  1398.                       UnlockGUI();
  1399.                     }
  1400.  
  1401.                     convert = FALSE;
  1402.                   }
  1403.                 }
  1404.  
  1405.                 /**********
  1406.                  * Done ! *
  1407.                  **********/
  1408.                 if( appwindow )
  1409.                 {
  1410.                   (void)RemoveAppWindow( appwindow );
  1411.                 }
  1412.  
  1413.                 if( appdobj )
  1414.                 {
  1415.                   FreeDiskObject( appdobj );
  1416.                 }
  1417.  
  1418.                 if( appicon )
  1419.                 {
  1420.                   (void)RemoveAppIcon( appicon );
  1421.                 }
  1422.  
  1423.                 CloseDTConvert_DATATYPEWindow();
  1424.                 CloseDTConvert_MAINWindow();
  1425.               }
  1426.  
  1427.               FreeAslRequest( SrcFileReq );
  1428.               FreeAslRequest( DestFileReq );
  1429.  
  1430.               CloseDownScreen();
  1431.             }
  1432.  
  1433.             FreeDTDescrList( dtl );
  1434.           }
  1435.  
  1436.           if( srclock )
  1437.           {
  1438.             UnLock( srclock );
  1439.           }
  1440.  
  1441.           ClearMsgPort( appport );
  1442.           DeleteMsgPort( appport );
  1443.         }
  1444.       }
  1445.       else
  1446.       {
  1447.         Convert( srcname, datatypename, destname );
  1448.       }
  1449.     }
  1450.     else
  1451.     {
  1452.       Message( NAME " requires at least a stack size of 16384 bytes\n" );
  1453.       SetIoErr( ERROR_NO_FREE_STORE );
  1454.     }
  1455.  
  1456.     if( IoErr() )
  1457.     {
  1458.       main_retval2 = IoErr();
  1459.       main_retval  = RETURN_ERROR;
  1460.     }
  1461. }
  1462.  
  1463.  
  1464. static
  1465. BOOL NewProject( STRPTR from, STRPTR datatype, STRPTR destname, BOOL gui, STRPTR pubscreen )
  1466. {
  1467.     struct Process              *ThisProc = (struct Process *)FindTask( NULL );
  1468.     BPTR                         olddir    = CurrentDir( (ThisProc -> pr_HomeDir) );
  1469.     BOOL                         success  = FALSE;
  1470.     STRPTR                       buffer;
  1471.     ULONG                        buffersize;
  1472.     struct CommandLineInterface *cli = Cli();
  1473.  
  1474.     if( from = GetLockName( olddir, from ) )
  1475.     {
  1476.       buffersize = Strlen( from ) + Strlen( datatype ) + Strlen( destname ) + Strlen( pubscreen ) + 512UL;
  1477.  
  1478.       if( buffer = (STRPTR)AllocVec( buffersize, MEMF_PUBLIC ) )
  1479.       {
  1480.         STRPTR next = buffer;
  1481.  
  1482.         if( cli )
  1483.         {
  1484.           STRPTR s = (STRPTR)BADDR( (cli -> cli_CommandName) );
  1485.  
  1486.           stccpy( next, (&s[ 1 ]), (int)(s[ 0 ] + 1U) );
  1487.         }
  1488.         else
  1489.         {
  1490.           strcpy( next, (ThisProc -> pr_Task . tc_Node . ln_Name) );
  1491.         }
  1492.  
  1493.         next += strlen( next );
  1494.  
  1495.         if( Strlen( from ) )
  1496.         {
  1497.           mysprintf( next, " FROM=\"%s\"", from );
  1498.           next += strlen( next );
  1499.         }
  1500.  
  1501.         if( Strlen( datatype ) )
  1502.         {
  1503.           mysprintf( next, " DATATYPE=\"%s\"", datatype );
  1504.           next += strlen( next );
  1505.         }
  1506.  
  1507.         if( Strlen( destname ) )
  1508.         {
  1509.           mysprintf( next, " TO=\"%s\"", destname );
  1510.           next += strlen( next );
  1511.         }
  1512.  
  1513.         if( gui )
  1514.         {
  1515.           mysprintf( next, " GUI" );
  1516.           next += strlen( next );
  1517.         }
  1518.  
  1519.         if( Strlen( pubscreen ) )
  1520.         {
  1521.           mysprintf( next, " PUBSCREEN=\"%s\"", pubscreen );
  1522.         }
  1523.  
  1524.         if( SystemTags( buffer,
  1525.                         SYS_Input,     Open( "CON:////" NAME "/auto/wait/close", MODE_READWRITE ),
  1526.                         SYS_Asynch,    TRUE,
  1527.                         TAG_DONE ) != (-1L) )
  1528.         {
  1529.           success = TRUE;
  1530.         }
  1531.  
  1532.         FreeVec( buffer );
  1533.       }
  1534.       
  1535.       FreeVec( from );
  1536.     }
  1537.  
  1538.     (void)CurrentDir( olddir );
  1539.  
  1540.     return( success );
  1541. }
  1542.  
  1543.  
  1544. /* GUI locking stuff */
  1545. static ULONG            GUILock                = 0UL;
  1546. static struct Requester MAINBlockReq           = { 0 };
  1547. static BOOL             MAINBlockReqActive     = FALSE;
  1548. static struct Requester DATATYPEBlockReq       = { 0 };
  1549. static BOOL             DATATYPEBlockReqActive = FALSE;
  1550.  
  1551.  
  1552. static
  1553. void LockGUI( void )
  1554. {
  1555.     if( GUILock++ == 0UL )
  1556.     {
  1557.       InitRequester( (&MAINBlockReq) );
  1558.       InitRequester( (&DATATYPEBlockReq) );
  1559.  
  1560.       if( DTConvert_MAINWnd )
  1561.       {
  1562.         SetWindowPointer( DTConvert_MAINWnd, WA_BusyPointer, TRUE, WA_PointerDelay, TRUE, TAG_DONE );
  1563.  
  1564.         if( MAINBlockReqActive == FALSE )
  1565.         {
  1566.           MAINBlockReqActive = Request( (&MAINBlockReq), DTConvert_MAINWnd );
  1567.         }
  1568.       }
  1569.  
  1570.       if( DTConvert_DATATYPEWnd )
  1571.       {
  1572.         SetWindowPointer( DTConvert_DATATYPEWnd, WA_BusyPointer, TRUE,  WA_PointerDelay, TRUE, TAG_DONE );
  1573.  
  1574.         if( DATATYPEBlockReqActive == FALSE )
  1575.         {
  1576.           DATATYPEBlockReqActive = Request( (&DATATYPEBlockReq), DTConvert_DATATYPEWnd );
  1577.         }
  1578.       }
  1579.     }
  1580. }
  1581.  
  1582.  
  1583. static
  1584. void UnlockGUI( void )
  1585. {
  1586.     if( --GUILock == 0UL )
  1587.     {
  1588.       if( DTConvert_MAINWnd )
  1589.       {
  1590.         SetWindowPointer( DTConvert_MAINWnd, WA_BusyPointer, FALSE, TAG_DONE );
  1591.  
  1592.         if( MAINBlockReqActive )
  1593.         {
  1594.           EndRequest( (&MAINBlockReq), DTConvert_MAINWnd );
  1595.           MAINBlockReqActive = FALSE;
  1596.         }
  1597.       }
  1598.  
  1599.       if( DTConvert_DATATYPEWnd )
  1600.       {
  1601.         SetWindowPointer( DTConvert_DATATYPEWnd, WA_BusyPointer, FALSE, TAG_DONE );
  1602.  
  1603.         if( DATATYPEBlockReqActive )
  1604.         {
  1605.           EndRequest( (&DATATYPEBlockReq), DTConvert_DATATYPEWnd );
  1606.           DATATYPEBlockReqActive = FALSE;
  1607.         }
  1608.       }
  1609.     }
  1610. }
  1611.  
  1612.  
  1613. void Message( STRPTR fmt, ... )
  1614. {
  1615.     VPrintf( fmt, (APTR)((&fmt) + 1) );
  1616. }
  1617.  
  1618.  
  1619. static
  1620. struct DTList *CreateDTDescrList( BPTR lock, ULONG groupid )
  1621. {
  1622.     APTR  pool;
  1623. #define NUM_GID_TABLE (32) /* we have much less GID_#? types defined yet (datatypes.library V45), but... */
  1624.     ULONG groupid_table[ NUM_GID_TABLE ] = { 0 };
  1625.  
  1626.     /* If a lock is given, we build here a list of all DT group ids the source file may be of... */
  1627.     if( lock )
  1628.     {
  1629.       struct DataType *dtn,
  1630.                       *prevdtn = NULL;
  1631.  
  1632.       /* Print whole list or determine the DataType of the file */
  1633.       while( dtn = ObtainDataType( DTST_FILE, (APTR)lock, DTA_DataType,                  prevdtn,
  1634.                                                           XTAG( groupid, DTA_GroupID ),  groupid,
  1635.                                                           TAG_DONE ) )
  1636.       {
  1637.         ULONG i,
  1638.               groupid = dtn -> dtn_Header -> dth_GroupID;
  1639.  
  1640.         /* Release previous DataType */
  1641.         ReleaseDataType( prevdtn );
  1642.  
  1643.         /* the follwoing statement assmes that GID_SYSTEM datatypes are not convertable
  1644.          * (and it filters some invalid datatypes which have a 0 group id)
  1645.          */
  1646.         if( (groupid != GID_SYSTEM) && (groupid != 0UL) )
  1647.         {
  1648.           for( i = 0UL ; i < NUM_GID_TABLE ; i++ )
  1649.           {
  1650.             if( !groupid_table[ i ] )
  1651.             {
  1652.               groupid_table[ i ] = groupid;
  1653.               break;
  1654.             }
  1655.           }
  1656.         }
  1657.  
  1658.         prevdtn = dtn;
  1659.       }
  1660.  
  1661.       /* Release last datatype */
  1662.       ReleaseDataType( prevdtn );
  1663.     }
  1664.  
  1665.     if( pool = CreatePool( (MEMF_PUBLIC | MEMF_CLEAR), 1024UL, 1024UL ) )
  1666.     {
  1667.       struct DTList *dtl;
  1668.  
  1669.       if( dtl = (struct DTList *)AllocVecPooled( pool, sizeof( struct DTList ) ) )
  1670.       {
  1671.         struct DataType *dtn,
  1672.                         *prevdtn = NULL;
  1673.         BOOL             error   = FALSE;
  1674.  
  1675.         NewList( (&(dtl -> dtl_List)) );
  1676.         dtl -> dtl_Pool = pool;
  1677.  
  1678.         /* Print whole list or determine the DataType of the file */
  1679.         while( dtn = ObtainDataType( DTST_RAM, NULL, DTA_DataType,                  prevdtn,
  1680.                                                      XTAG( groupid, DTA_GroupID ),  groupid,
  1681.                                                      TAG_DONE ) )
  1682.         {
  1683.           struct DataTypeHeader *dth;          /* datatypes header        */
  1684.           BOOL                   match = TRUE; /* include this datatype ? */
  1685.  
  1686.           /* Release previous DataType */
  1687.           ReleaseDataType( prevdtn );
  1688.  
  1689.           dth = dtn -> dtn_Header; /* Shortcut... */
  1690.  
  1691.           /* If we have a lock given, we previously build a group id table... */
  1692.           if( lock )
  1693.           {
  1694.             ULONG i;
  1695.  
  1696.             match = FALSE;
  1697.  
  1698.             /* ... now check if this datatype node matches any source groupid */
  1699.             for( i = 0UL ; ((i < NUM_GID_TABLE) && groupid_table[ i ]) ; i++ )
  1700.             {
  1701.               /* Match ? */
  1702.               if( groupid_table[ i ] == (dth -> dth_GroupID) )
  1703.               {
  1704.                 match = TRUE;
  1705.                 break;
  1706.               }
  1707.  
  1708.               /* Special kluge that we can convert GID_ANIMATION to GID_MOVIE and backwards
  1709.                * (both are based on animation.datatype, here we have the same interface :-)
  1710.                */
  1711.               if( ((groupid_table[ i ]   == GID_MOVIE) || (groupid_table[ i ]   == GID_ANIMATION)) &&
  1712.                   (((dth -> dth_GroupID) == GID_MOVIE) || ((dth -> dth_GroupID) == GID_ANIMATION)) )
  1713.               {
  1714.                 match = TRUE;
  1715.                 break;
  1716.               }
  1717.             }
  1718.           }
  1719.  
  1720.           /* Include this datatype ? */
  1721.           if( match )
  1722.           {
  1723.             STRPTR         groupid_name; /* short-cut to GID_#? name string    */
  1724.             ULONG          size;         /* size of struct DTNode and contents */
  1725.             struct DTNode *namenode;
  1726.  
  1727.             groupid_name = GetDTString( (dth -> dth_GroupID) );
  1728.  
  1729.             size = sizeof( struct DTNode ) + (strlen( (dth -> dth_Name) ) * 2UL) + Strlen( groupid_name ) + 16UL;
  1730.  
  1731.             /* Alloc and build node... */
  1732.             if( namenode = (struct DTNode *)AllocVecPooled( pool, size ) )
  1733.             {
  1734.               STRPTR s = (STRPTR)(namenode + 1);
  1735.  
  1736.               /* store listview names */
  1737.               mysprintf( s, "%s %s", (dth -> dth_Name), groupid_name );
  1738.               namenode -> dtn_Node . ln_Name = s;
  1739.  
  1740.               s = s + strlen( s ) + 2; /* next free space */
  1741.  
  1742.               /* store datatype name */
  1743.               strcpy( s, (dth -> dth_Name) );
  1744.               namenode -> dtn_DTName = s;
  1745.  
  1746.               /* add node */
  1747.               AddTail( (&(dtl -> dtl_List)), (&(namenode -> dtn_Node)) );
  1748.               dtl -> dtl_NumNodes++;
  1749.             }
  1750.             else
  1751.             {
  1752.               error = TRUE;
  1753.             }
  1754.           }
  1755.  
  1756.           prevdtn = dtn;
  1757.         }
  1758.  
  1759.         /* Release last datatype */
  1760.         ReleaseDataType( prevdtn );
  1761.  
  1762.         /* Success ? */
  1763.         if( !error )
  1764.         {
  1765.           return( dtl );
  1766.         }
  1767.       }
  1768.  
  1769.       DeletePool( pool );
  1770.     }
  1771.  
  1772.     return( NULL );
  1773. }
  1774.  
  1775.  
  1776. static
  1777. void FreeDTDescrList( struct DTList *list )
  1778. {
  1779.    if( list )
  1780.    {
  1781.      DeletePool( (list -> dtl_Pool) );
  1782.    }
  1783. }
  1784.  
  1785.  
  1786. static
  1787. struct DTNode *FindDTNodeByName( struct DTList *list, STRPTR name )
  1788. {
  1789.     struct DTNode *node;
  1790.     struct DTNode *result = NULL;
  1791.  
  1792.     if( list && name )
  1793.     {
  1794.       for( node = (struct DTNode *)(list -> dtl_List . lh_Head) ; node -> dtn_Node . ln_Succ ; node = (struct DTNode *)(node -> dtn_Node . ln_Succ) )
  1795.       {
  1796.         if( !Stricmp( (node -> dtn_DTName), name ) )
  1797.         {
  1798.           result = node;
  1799.           break;
  1800.         }
  1801.       }
  1802.     }
  1803.  
  1804.     return( result );
  1805. }
  1806.  
  1807.  
  1808. static
  1809. STRPTR StringSave( STRPTR s )
  1810. {
  1811.     STRPTR saved;
  1812.  
  1813.     if( s )
  1814.     {
  1815.       if( saved = AllocStringBuff( (ULONG)strlen( s ) ) )
  1816.       {
  1817.         strcpy( saved, s );
  1818.  
  1819.         return( saved );
  1820.       }
  1821.     }
  1822.  
  1823.     return( NULL );
  1824. }
  1825.  
  1826.  
  1827. static
  1828. STRPTR AllocStringBuff( ULONG size )
  1829. {
  1830.     return( (STRPTR)AllocVecPooled( StringPool, (size + 2UL) ) );
  1831. }
  1832.  
  1833.  
  1834. static
  1835. STRPTR UpdateString( STRPTR *storage, STRPTR newstring )
  1836. {
  1837.     STRPTR s;
  1838.  
  1839.     s = NULL;
  1840.  
  1841.     if( storage )
  1842.     {
  1843.       FreeString( (*storage) );
  1844.  
  1845.       s = (*storage) = StringSave( newstring );
  1846.     }
  1847.  
  1848.     return( s );
  1849. }
  1850.  
  1851.  
  1852. static
  1853. void FreeString( STRPTR s )
  1854. {
  1855.     if( s )
  1856.     {
  1857.       FreeVecPooled( StringPool, s );
  1858.     }
  1859. }
  1860.  
  1861.  
  1862. static
  1863. struct DiskObject *GetToolDiskObject( STRPTR name )
  1864. {
  1865.     struct DiskObject *dobj;
  1866.     struct Process    *ThisProc = (struct Process *)FindTask( NULL );
  1867.     BPTR               olddir   = CurrentDir( (ThisProc -> pr_HomeDir) );
  1868.  
  1869.     dobj = GetDiskObjectNew( name );
  1870.  
  1871.     (void)CurrentDir( olddir );
  1872.  
  1873.     return( dobj );
  1874. }
  1875.  
  1876.  
  1877. static
  1878. ULONG SumString( STRPTR s )
  1879. {
  1880.     ULONG sum = 0UL;
  1881.  
  1882.     if( s )
  1883.     {
  1884.       ULONG ch;
  1885.  
  1886.       while( ch = *s++ )
  1887.       {
  1888.         sum = (sum * 7UL) + ch;
  1889.       }
  1890.     }
  1891.  
  1892.     return( sum );
  1893. }
  1894.  
  1895.  
  1896.