home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / misc / emu / AROSdev.lha / AROS / workbench / demos / readicon.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-27  |  15.1 KB  |  748 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: readicon.c,v 1.6 1997/01/27 00:22:39 ldp Exp $
  4.  
  5.     Desc: Read an icon from an .info file
  6.     Lang: english
  7. */
  8.  
  9. #include <stdio.h>
  10. #include <stddef.h>
  11.  
  12. #include <exec/memory.h>
  13. #include <aros/structdesc.h>
  14. #include <aros/asmcall.h>
  15. #include <aros/debug.h>
  16. #include <workbench/workbench.h>
  17. #include <intuition/intuition.h>
  18. #include <intuition/intuitionbase.h>
  19. #include <intuition/intuition.h>
  20. #include <graphics/gfxbase.h>
  21. #include <graphics/rastport.h>
  22.  
  23. #include <proto/alib.h>
  24. #include <proto/exec.h>
  25. #include <proto/dos.h>
  26. #include <proto/aros.h>
  27. #include <proto/intuition.h>
  28.  
  29. AROS_UFH3(ULONG, ProcessDrawerData,
  30.     AROS_UFHA(struct Hook *,   hook, A0),
  31.     AROS_UFHA(BPTR,            file, A2),
  32.     AROS_UFHA(struct SDData *, data, A1)
  33. );
  34. AROS_UFH3(ULONG, ProcessGadgetRender,
  35.     AROS_UFHA(struct Hook *,   hook, A0),
  36.     AROS_UFHA(BPTR,            file, A2),
  37.     AROS_UFHA(struct SDData *, data, A1)
  38. );
  39. AROS_UFH3(ULONG, ProcessSelectRender,
  40.     AROS_UFHA(struct Hook *,   hook, A0),
  41.     AROS_UFHA(BPTR,            file, A2),
  42.     AROS_UFHA(struct SDData *, data, A1)
  43. );
  44. AROS_UFH3(ULONG, ProcessDefaultTool,
  45.     AROS_UFHA(struct Hook *,   hook, A0),
  46.     AROS_UFHA(BPTR,            file, A2),
  47.     AROS_UFHA(struct SDData *, data, A1)
  48. );
  49. AROS_UFH3(ULONG, ProcessToolTypes,
  50.     AROS_UFHA(struct Hook *,   hook, A0),
  51.     AROS_UFHA(BPTR,            file, A2),
  52.     AROS_UFHA(struct SDData *, data, A1)
  53. );
  54. AROS_UFH3(ULONG, ProcessFlagPtr,
  55.     AROS_UFHA(struct Hook *,   hook, A0),
  56.     AROS_UFHA(BPTR,            file, A2),
  57.     AROS_UFHA(struct SDData *, data, A1)
  58. );
  59.  
  60. struct Hook ProcessDrawerDataHook =
  61. {
  62.     { NULL, NULL}, ProcessDrawerData, NULL, NULL
  63. },
  64. ProcessGadgetRenderHook =
  65. {
  66.     { NULL, NULL}, ProcessGadgetRender, NULL, NULL
  67. },
  68. ProcessSelectRenderHook =
  69. {
  70.     { NULL, NULL}, ProcessSelectRender, NULL, NULL
  71. },
  72. ProcessFlagPtrHook =
  73. {
  74.     { NULL, NULL}, ProcessFlagPtr, NULL, NULL
  75. },
  76. ProcessDefaultToolHook =
  77. {
  78.     { NULL, NULL}, ProcessDefaultTool, NULL, NULL
  79. },
  80. ProcessToolTypesHook =
  81. {
  82.     { NULL, NULL}, ProcessToolTypes, NULL, NULL
  83. };
  84.  
  85. #undef O
  86. #define O(x)    (offsetof (struct Gadget,x))
  87. IPTR GadgetDesc[] =
  88. {
  89.     sizeof (struct Gadget),
  90.     SDM_IGNORE(4), /* NextGadget */
  91.     SDM_WORD(O(LeftEdge)),
  92.     SDM_WORD(O(TopEdge)),
  93.     SDM_WORD(O(Width)),
  94.     SDM_WORD(O(Height)),
  95.     SDM_UWORD(O(Flags)),
  96.     SDM_UWORD(O(Activation)),
  97.     SDM_UWORD(O(GadgetType)),
  98.     SDM_SPECIAL(O(GadgetRender),&ProcessFlagPtrHook),
  99.     SDM_SPECIAL(O(SelectRender),&ProcessFlagPtrHook),
  100.     SDM_SPECIAL(O(GadgetText),&ProcessFlagPtrHook),
  101.     SDM_LONG(O(MutualExclude)),
  102.     SDM_SPECIAL(O(SpecialInfo),&ProcessFlagPtrHook),
  103.     SDM_UWORD(O(GadgetID)),
  104.     SDM_ULONG(O(UserData)),
  105.     SDM_END
  106. };
  107.  
  108. #undef O
  109. #define O(x)    (offsetof (struct DiskObject,x))
  110. IPTR DiskObjectDesc[] =
  111. {
  112.     sizeof (struct DiskObject),
  113.     SDM_UWORD(O(do_Magic)),
  114.     SDM_UWORD(O(do_Version)),
  115.     SDM_STRUCT(O(do_Gadget),GadgetDesc),
  116.     SDM_UBYTE(O(do_Type)),
  117.     SDM_IGNORE(1), /* Pad */
  118.     SDM_SPECIAL(O(do_DefaultTool),&ProcessFlagPtrHook),
  119.     SDM_SPECIAL(O(do_ToolTypes),&ProcessFlagPtrHook),
  120.     SDM_LONG(O(do_CurrentX)),
  121.     SDM_LONG(O(do_CurrentY)),
  122.     SDM_SPECIAL(O(do_DrawerData),&ProcessFlagPtrHook),
  123.     SDM_SPECIAL(O(do_ToolWindow),&ProcessFlagPtrHook),
  124.     SDM_LONG(O(do_StackSize)),
  125.     SDM_END
  126. };
  127.  
  128. #undef O
  129. #define O(x)    (offsetof (struct Image,x))
  130. IPTR ImageDesc[] =
  131. {
  132.     sizeof (struct Image),
  133.     SDM_WORD(O(LeftEdge)),
  134.     SDM_WORD(O(TopEdge)),
  135.     SDM_WORD(O(Width)),
  136.     SDM_WORD(O(Height)),
  137.     SDM_WORD(O(Depth)),
  138.     SDM_SPECIAL(O(ImageData),&ProcessFlagPtrHook),
  139.     SDM_UBYTE(O(PlanePick)),
  140.     SDM_UBYTE(O(PlaneOnOff)),
  141.     SDM_SPECIAL(O(NextImage),&ProcessFlagPtrHook),
  142.     SDM_END
  143. };
  144.  
  145. IPTR IconDesc[] =
  146. {
  147.     sizeof (struct DiskObject),
  148.     SDM_STRUCT(0,DiskObjectDesc),
  149.     SDM_SPECIAL(0,&ProcessDrawerDataHook),
  150.     SDM_SPECIAL(0,&ProcessGadgetRenderHook),
  151.     SDM_SPECIAL(0,&ProcessSelectRenderHook),
  152.     SDM_SPECIAL(0,&ProcessDefaultToolHook),
  153.     SDM_SPECIAL(0,&ProcessToolTypesHook),
  154.     SDM_END
  155. };
  156.  
  157. #define IM(x)       ((struct Image *)x)
  158.  
  159. struct IntuitionBase *IntuitionBase;
  160. struct GfxBase *GfxBase;
  161.  
  162. void DoWindow (struct DiskObject * dobj)
  163. {
  164.     struct Window   * win = NULL;
  165.     struct RastPort * rp;
  166.     struct IntuiMessage * im;
  167.     int cont;
  168.  
  169.     GfxBase=(struct GfxBase *)OpenLibrary(GRAPHICSNAME,39);
  170.     IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",39);
  171.  
  172.     if (!GfxBase)
  173.     {
  174.     fprintf (stderr, "Couldn't open %s\n", GRAPHICSNAME);
  175.     goto end;
  176.     }
  177.  
  178.     if (!IntuitionBase)
  179.     {
  180.     fprintf (stderr, "Couldn't open intuition.library\n");
  181.     goto end;
  182.     }
  183.  
  184.     dobj->do_Gadget.LeftEdge = dobj->do_Gadget.Width * 2 + 30;
  185.     dobj->do_Gadget.TopEdge  = 10;
  186.  
  187.     win = OpenWindowTags (NULL
  188.     , WA_Title,        "Show an icon"
  189.     , WA_Left,        100
  190.     , WA_Top,        100
  191.     , WA_Width,        dobj->do_Gadget.Width * 3 + 40
  192.     , WA_Height,        dobj->do_Gadget.Height + 20
  193.     , WA_IDCMP,        IDCMP_RAWKEY
  194.     , WA_SimpleRefresh, TRUE
  195.     , WA_Gadgets,        &dobj->do_Gadget
  196.     , TAG_END
  197.     );
  198.  
  199.     if (!win)
  200.     goto end;
  201.  
  202.     rp = win->RPort;
  203.  
  204.     DrawImage (rp, dobj->do_Gadget.GadgetRender, 10, 10);
  205.     DrawImage (rp, dobj->do_Gadget.SelectRender, 20 + dobj->do_Gadget.Width, 10);
  206.  
  207.     cont = 1;
  208.  
  209.     printf ("Press a key to exit\n");
  210.  
  211.     while (cont)
  212.     {
  213.     if ((im = (struct IntuiMessage *)GetMsg (win->UserPort)))
  214.     {
  215.         /* D("Got msg\n"); */
  216.         switch (im->Class)
  217.         {
  218.         case IDCMP_RAWKEY:
  219.         cont = FALSE;
  220.         break;
  221.  
  222.         }
  223.  
  224.         ReplyMsg ((struct Message *)im);
  225.     }
  226.     else
  227.     {
  228.         /* D("Waiting\n"); */
  229.         Wait (1L << win->UserPort->mp_SigBit);
  230.     }
  231.     }
  232.  
  233. end:
  234.     if (win)
  235.     CloseWindow (win);
  236.  
  237.     if (GfxBase)
  238.     CloseLibrary ((struct Library *)GfxBase);
  239.  
  240.     if (IntuitionBase)
  241.     CloseLibrary ((struct Library *)IntuitionBase);
  242.  
  243.     return;
  244. } /* DoWindow */
  245.  
  246. int main (int argc, char ** argv)
  247. {
  248.     struct RDArgs     * rda;
  249.     struct DiskObject * dobj;
  250.  
  251.     STRPTR arg;
  252.     BPTR   icon;
  253.     int    rc;
  254.     int    t;
  255.  
  256.     rc = 0;
  257.  
  258.     rda = ReadArgs ("IconFile/A", (IPTR *)&arg, NULL);
  259.  
  260.     if (rda)
  261.     {
  262.     if (!(icon = Open (arg, MODE_OLDFILE)) )
  263.     {
  264.         fprintf (stderr, "Cannot open file %s for reading: ", arg);
  265.         PrintFault (IoErr(), "");
  266.         rc = 10;
  267.     }
  268.     else
  269.     {
  270.         if (!ReadStruct (icon, (APTR *)&dobj, IconDesc))
  271.         {
  272.         fprintf (stderr, "Error reading file %s: ", arg);
  273.         PrintFault (IoErr(), "");
  274.         rc = 10;
  275.         }
  276.         else
  277.         {
  278.         Close (icon);
  279.  
  280.         /* hexdump (dobj, 0L, sizeof (struct DiskObject)); */
  281.  
  282.         printf ("Some information about the icon:\n"
  283.             "Magic = %d\n"
  284.             "Version = %d\n"
  285.             "Type = %d\n"
  286.             "Gadget: %dx%d+%d+%d Flags=%x Act=%x Type=%d\n"
  287.             "Stack = %ld\n"
  288.             , dobj->do_Magic
  289.             , dobj->do_Version
  290.             , dobj->do_Type
  291.             , dobj->do_Gadget.Width
  292.             , dobj->do_Gadget.Height
  293.             , dobj->do_Gadget.LeftEdge
  294.             , dobj->do_Gadget.TopEdge
  295.             , dobj->do_Gadget.Flags
  296.             , dobj->do_Gadget.Activation
  297.             , dobj->do_Gadget.GadgetType
  298.             , dobj->do_StackSize
  299.         );
  300.  
  301.         if (dobj->do_Gadget.GadgetRender)
  302.         {
  303.             printf ("GImage: %dx%d+%d+%d\n"
  304.             , IM(dobj->do_Gadget.GadgetRender)->Width
  305.             , IM(dobj->do_Gadget.GadgetRender)->Height
  306.             , IM(dobj->do_Gadget.GadgetRender)->LeftEdge
  307.             , IM(dobj->do_Gadget.GadgetRender)->TopEdge
  308.             );
  309.  
  310.             /* hexdump (IM(dobj->do_Gadget.GadgetRender)->ImageData
  311.             , 0L
  312.             , 720
  313.             ); */
  314.         }
  315.         else
  316.         {
  317.             printf ("GImage: none\n");
  318.         }
  319.  
  320.         if (dobj->do_Gadget.SelectRender)
  321.         {
  322.             printf ("SImage: %dx%d+%d+%d\n"
  323.             , IM(dobj->do_Gadget.SelectRender)->Width
  324.             , IM(dobj->do_Gadget.SelectRender)->Height
  325.             , IM(dobj->do_Gadget.SelectRender)->LeftEdge
  326.             , IM(dobj->do_Gadget.SelectRender)->TopEdge
  327.             );
  328.  
  329.             /* hexdump (IM(dobj->do_Gadget.SelectRender)->ImageData
  330.             , 0L
  331.             , 720
  332.             ); */
  333.         }
  334.         else
  335.         {
  336.             printf ("SImage: none\n");
  337.         }
  338.  
  339.         printf ("DefaultTool: %s\n", dobj->do_DefaultTool);
  340.  
  341.         printf ("ToolTypes:\n");
  342.  
  343.         for (t=0; dobj->do_ToolTypes[t]; t++)
  344.             printf ("TT %d: %s\n", t, dobj->do_ToolTypes[t]);
  345.  
  346.         if (!(icon = Open ("readicon.info", MODE_NEWFILE)) )
  347.             PrintFault (IoErr(), "Cannot write icon to readicon.info");
  348.         else
  349.         {
  350.             if (!WriteStruct (icon, dobj, IconDesc))
  351.             PrintFault (IoErr(), "Writing of icon to readicon.info failed");
  352.  
  353.             Close (icon);
  354.         }
  355.  
  356.         DoWindow (dobj);
  357.  
  358.         FreeStruct (dobj, DiskObjectDesc);
  359.         }
  360.     }
  361.  
  362.     FreeArgs (rda);
  363.     }
  364.     else
  365.     rc = 10;
  366.  
  367.     return rc;
  368. } /* main */
  369.  
  370. #define DO(x)       ((struct DiskObject *)x)
  371.  
  372. AROS_UFH3(ULONG, ProcessDrawerData,
  373.     AROS_UFHA(struct Hook *,   hook, A0),
  374.     AROS_UFHA(BPTR,            file, A2),
  375.     AROS_UFHA(struct SDData *, data, A1)
  376. )
  377. {
  378. /* kprintf ("ProcessDrawerData\n"); */
  379.     if (DO(data->sdd_Dest)->do_Type == WBDRAWER)
  380.     {
  381.     switch (data->sdd_Mode)
  382.     {
  383.     case SDV_SPECIALMODE_READ:
  384.         Flush (file);
  385.  
  386.         return Seek (file, DRAWERDATAFILESIZE, OFFSET_CURRENT) != EOF;
  387.  
  388.     case SDV_SPECIALMODE_WRITE:
  389.         return Write (file
  390.         , DO(data->sdd_Dest)->do_DrawerData
  391.         , DRAWERDATAFILESIZE
  392.         ) != EOF;
  393.  
  394.     case SDV_SPECIALMODE_FREE:
  395.         break;
  396.     }
  397.     }
  398.  
  399.     return TRUE;
  400. } /* ProcessDrawerData */
  401.  
  402. struct Image * ReadImage (BPTR file)
  403. {
  404.     struct Image * image;
  405.     ULONG       size;
  406.     ULONG       t;
  407.  
  408.     if (!ReadStruct (file, (APTR *)&image, ImageDesc))
  409.     return NULL;
  410.  
  411.     /* Size of imagedata in bytes */
  412.     size = ((image->Width + 15) >> 3) * image->Height * image->Depth;
  413.  
  414. /* kprintf ("ReadImage: %dx%dx%d (%d bytes)\n"
  415.     , image->Width
  416.     , image->Height
  417.     , image->Depth
  418.     , size
  419. ); */
  420.  
  421.     if (size)
  422.     {
  423.     if (!(image->ImageData = AllocMem (size, MEMF_CHIP)) )
  424.     {
  425.         FreeStruct (image, ImageDesc);
  426.         return NULL;
  427.     }
  428.  
  429.     size >>= 1; /* Get size in words */
  430.  
  431.     for (t=0; t<size; t++)
  432.         if (!ReadWord (file, &image->ImageData[t]))
  433.         break;
  434.  
  435.     if (t != size)
  436.     {
  437.         FreeStruct (image, ImageDesc);
  438.         return NULL;
  439.     }
  440.     }
  441.  
  442.     return image;
  443. } /* ReadImage */
  444.  
  445. int WriteImage (BPTR file, struct Image * image)
  446. {
  447.     ULONG size;
  448.     ULONG t;
  449.  
  450.     if (!WriteStruct (file, image, ImageDesc) )
  451.     return FALSE;
  452.  
  453.     /* Get size in words */
  454.     size = ((image->Width + 15) >> 4) * image->Height * image->Depth;
  455.  
  456.     for (t=0; t<size; t++)
  457.     if (!WriteWord (file, image->ImageData[t]))
  458.         break;
  459.  
  460.     return (t == size);
  461. } /* WriteImage */
  462.  
  463. void FreeImage (struct Image * image)
  464. {
  465.     ULONG size;
  466.  
  467.     /* Get size in bytes */
  468.     size = ((image->Width + 15) >> 3) * image->Height * image->Depth;
  469.  
  470.     if (size)
  471.     FreeMem (image->ImageData, size);
  472.  
  473.     FreeStruct (image, ImageDesc);
  474. } /* FreeImage */
  475.  
  476. AROS_UFH3(ULONG, ProcessGadgetRender,
  477.     AROS_UFHA(struct Hook *,   hook, A0),
  478.     AROS_UFHA(BPTR,            file, A2),
  479.     AROS_UFHA(struct SDData *, data, A1)
  480. )
  481. {
  482.     struct Image * image;
  483. /* kprintf ("ProcessGadgetRender\n"); */
  484.  
  485.     switch (data->sdd_Mode)
  486.     {
  487.     case SDV_SPECIALMODE_READ:
  488.     image = ReadImage (file);
  489.  
  490.     if (!image)
  491.         return FALSE;
  492.  
  493.     DO(data->sdd_Dest)->do_Gadget.GadgetRender = image;
  494.  
  495.     break;
  496.  
  497.     case SDV_SPECIALMODE_WRITE:
  498.     image = DO(data->sdd_Dest)->do_Gadget.GadgetRender;
  499.  
  500.     return WriteImage (file, image);
  501.  
  502.     case SDV_SPECIALMODE_FREE:
  503.     image = DO(data->sdd_Dest)->do_Gadget.GadgetRender;
  504.  
  505.     FreeImage (image);
  506.  
  507.     break;
  508.     }
  509.  
  510.     return TRUE;
  511. } /* ProcessGadgetRender */
  512.  
  513. AROS_UFH3(ULONG, ProcessSelectRender,
  514.     AROS_UFHA(struct Hook *,   hook, A0),
  515.     AROS_UFHA(BPTR,            file, A2),
  516.     AROS_UFHA(struct SDData *, data, A1)
  517. )
  518. {
  519.     struct Image * image;
  520. /* kprintf ("ProcessSelectRender\n"); */
  521.  
  522.     if (DO(data->sdd_Dest)->do_Gadget.Flags & GFLG_GADGHIMAGE)
  523.     {
  524.     switch (data->sdd_Mode)
  525.     {
  526.     case SDV_SPECIALMODE_READ:
  527.         image = ReadImage (file);
  528.  
  529.         if (!image)
  530.         return FALSE;
  531.  
  532.         DO(data->sdd_Dest)->do_Gadget.SelectRender = image;
  533.  
  534.         break;
  535.  
  536.     case SDV_SPECIALMODE_WRITE:
  537.         image = DO(data->sdd_Dest)->do_Gadget.SelectRender;
  538.  
  539.         return WriteImage (file, image);
  540.  
  541.     case SDV_SPECIALMODE_FREE:
  542.         image = DO(data->sdd_Dest)->do_Gadget.SelectRender;
  543.  
  544.         FreeImage (image);
  545.  
  546.         break;
  547.     }
  548.     }
  549.  
  550.     return TRUE;
  551. } /* ProcessSelectRender */
  552.  
  553. AROS_UFH3(ULONG, ProcessFlagPtr,
  554.     AROS_UFHA(struct Hook *,   hook, A0),
  555.     AROS_UFHA(BPTR,            file, A2),
  556.     AROS_UFHA(struct SDData *, data, A1)
  557. )
  558. {
  559.     LONG ptr;
  560.  
  561.     switch (data->sdd_Mode)
  562.     {
  563.     case SDV_SPECIALMODE_READ:
  564.     if (FRead (file, &ptr, 4, 1) == EOF)
  565.         return FALSE;
  566.  
  567.     *((APTR *)data->sdd_Dest) = (APTR)(ptr != 0L);
  568.  
  569.     break;
  570.  
  571.     case SDV_SPECIALMODE_WRITE:
  572.     if (*((APTR *)data->sdd_Dest))
  573.         ptr = 0xABADCAFEL;
  574.     else
  575.         ptr = 0L;
  576.  
  577.     if (FWrite (file, &ptr, 4, 1) == EOF)
  578.         return FALSE;
  579.  
  580.     break;
  581.  
  582.     case SDV_SPECIALMODE_FREE:
  583.     break;
  584.     }
  585.  
  586.  
  587.     return TRUE;
  588. } /* ProcessFlagPtr */
  589.  
  590. STRPTR ReadIconString (BPTR file)
  591. {
  592.     ULONG  len;
  593.     STRPTR str;
  594.  
  595.     if (!ReadLong (file, &len))
  596.     return NULL;
  597.  
  598.     str = AllocMem (len, MEMF_ANY);
  599.  
  600.     if (!str)
  601.     return NULL;
  602.  
  603.     if (FRead (file, str, len, 1) == EOF)
  604.     {
  605.     FreeMem (str, len);
  606.     return NULL;
  607.     }
  608.  
  609.     return str;
  610. } /* ReadIconString */
  611.  
  612. int WriteIconString (BPTR file, STRPTR str)
  613. {
  614.     ULONG len;
  615.  
  616.     len = strlen (str) + 1;
  617.  
  618.     if (!WriteLong (file, len))
  619.     return FALSE;
  620.  
  621.     return FWrite (file, str, len, 1) != EOF;
  622. } /* WriteIconString */
  623.  
  624. AROS_UFH3(ULONG, ProcessDefaultTool,
  625.     AROS_UFHA(struct Hook *,   hook, A0),
  626.     AROS_UFHA(BPTR,            file, A2),
  627.     AROS_UFHA(struct SDData *, data, A1)
  628. )
  629. {
  630.     STRPTR str;
  631.  
  632.     if (DO(data->sdd_Dest)->do_DefaultTool)
  633.     {
  634.     switch (data->sdd_Mode)
  635.     {
  636.     case SDV_SPECIALMODE_READ:
  637.         str = ReadIconString (file);
  638.  
  639.         if (!str)
  640.         return FALSE;
  641.  
  642.         DO(data->sdd_Dest)->do_DefaultTool = str;
  643.  
  644.         break;
  645.  
  646.     case SDV_SPECIALMODE_WRITE: {
  647.         str = DO(data->sdd_Dest)->do_DefaultTool;
  648.  
  649.         WriteIconString (file, str);
  650.  
  651.         break; }
  652.  
  653.     case SDV_SPECIALMODE_FREE:
  654.         str = DO(data->sdd_Dest)->do_DefaultTool;
  655.  
  656.         FreeMem (str, strlen (str)+1);
  657.  
  658.         break;
  659.     }
  660.     }
  661.  
  662.     return TRUE;
  663. } /* ProcessDefaultTool */
  664.  
  665. AROS_UFH3(ULONG, ProcessToolTypes,
  666.     AROS_UFHA(struct Hook *,   hook, A0),
  667.     AROS_UFHA(BPTR,            file, A2),
  668.     AROS_UFHA(struct SDData *, data, A1)
  669. )
  670. {
  671.     if (DO(data->sdd_Dest)->do_ToolTypes)
  672.     {
  673.     ULONG     t;
  674.     ULONG     count;
  675.     STRPTR * ttarray;
  676.  
  677.     switch (data->sdd_Mode)
  678.     {
  679.     case SDV_SPECIALMODE_READ:
  680.         /* Read size of ToolTypes array (each entry is 4 bytes and the
  681.            last is 0L */
  682.         if (!ReadLong (file, &count))
  683.         return FALSE;
  684.  
  685.         count = (count >> 2) - 1; /* How many entries */
  686.  
  687.         ttarray = AllocMem ((count+1)*sizeof(STRPTR), MEMF_ANY);
  688.  
  689.         for (t=0; t<count; t++)
  690.         {
  691.         ttarray[t] = ReadIconString (file);
  692.  
  693.         if (!ttarray[t])
  694.         {
  695.             ULONG i;
  696.  
  697.             for (i=0; i<t; i++)
  698.             FreeMem (ttarray[t], strlen (ttarray[t])+1);
  699.  
  700.             FreeMem (ttarray, (count+1)*sizeof(STRPTR));
  701.  
  702.             return FALSE;
  703.         }
  704.         }
  705.  
  706.         ttarray[t] = NULL;
  707.  
  708.         DO(data->sdd_Dest)->do_ToolTypes = (char **)ttarray;
  709.  
  710.         break;
  711.  
  712.     case SDV_SPECIALMODE_WRITE: {
  713.         ULONG size;
  714.  
  715.         ttarray = (STRPTR *)DO(data->sdd_Dest)->do_ToolTypes;
  716.  
  717.         for (count=0; ttarray[count]; count++);
  718.  
  719.         size = (count+1)*4;
  720.  
  721.         if (!WriteLong (file, size))
  722.         return FALSE;
  723.  
  724.         for (t=0; t<count; t++)
  725.         {
  726.         if (!WriteIconString (file, ttarray[t]))
  727.             return FALSE;
  728.         }
  729.  
  730.         break; }
  731.  
  732.     case SDV_SPECIALMODE_FREE:
  733.         ttarray = (STRPTR *)DO(data->sdd_Dest)->do_ToolTypes;
  734.  
  735.         for (t=0; ttarray[t]; t++)
  736.         FreeMem (ttarray[t], strlen (ttarray[t])+1);
  737.  
  738.         FreeMem (ttarray, (t+1)*sizeof(STRPTR));
  739.  
  740.         break;
  741.     }
  742.     }
  743.  
  744.     return TRUE;
  745. } /* ProcessToolTypes */
  746.  
  747.  
  748.