home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format 124 / af124a.adf / af124a.lzx / WBStartup+V2.8 / Source / WBStartup+Prefs / WBStartup+Prefs.c < prev    next >
C/C++ Source or Header  |  1999-03-29  |  53KB  |  1,436 lines

  1. /*Requests:
  2.  
  3. sort by CX_PRIORITY
  4. Update the list by monitoring the 2 dirs
  5. */
  6.  
  7.  
  8. /*  WBStartup+Prefs.c */
  9.  
  10. #define VERSION   "2.8"
  11. #define DATENUM   __AMIGADATE__
  12. #define DATETEXT  "December 12, 1996"
  13. #define COPYRIGHT "Copyright © 1996 John Hughes"
  14.  
  15. //#define DEBUG 1
  16.  
  17. /*****************************************************************/
  18.  
  19. #include <exec/types.h>
  20. #include <exec/memory.h>
  21.  
  22. #include <clib/dos_protos.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <stdlib.h>
  26. #include <utility/tagitem.h>    /* TAG_DONE */
  27. #include <dos/exall.h>
  28. #include <clib/alib_protos.h>   /* List */
  29. #include <clib/exec_protos.h>   /* AllocVec() */
  30. #include <workbench/startup.h>
  31. #include <dos/dostags.h>         /* SYS_Asynch */
  32. #include <dos/exall.h>
  33. #include <intuition/gadgetclass.h>
  34. #include <graphics/gfxmacros.h>
  35. #include <graphics/gfxbase.h>
  36. #include <dos/stdio.h>
  37.  
  38. /* These add the function prototypes and the #pragmas which reduce the code size */
  39. #include <proto/dos.h>
  40. #include <proto/exec.h>
  41. #include <proto/gadtools.h>
  42. #include <proto/intuition.h>
  43. #include <proto/icon.h>
  44. #include <proto/graphics.h>
  45. #include <proto/wb.h>
  46. #include <proto/commodities.h>
  47. #include <proto/diskfont.h>
  48. #include <proto/graphics.h>
  49. #include <proto/utility.h>
  50. #include <proto/wb.h>
  51.  
  52. #include <math.h>
  53.  
  54. #include "CheckBoxListView.h"
  55. #include "WBStartup+Prefs.h"
  56. #include "GetStringWindow.h"
  57. #include "GetPriorityWindow.h"
  58. #include "ChooseGroupWindow.h"
  59. #include "CopyWindow.h"
  60. #include "DisableWindow.h"
  61.  
  62. #include "WBStartupPlusPrefs_Cat.h"
  63.  
  64. //#define MWDEBUG 1
  65. //#include "sc:extras/memlib/memwatch.h"
  66.  
  67.  
  68. char const version[]="\0$VER: WBStartup+Prefs "VERSION" "DATENUM"\r\n"COPYRIGHT"\r\njohughes@heartland.bradley.edu";
  69.  
  70. #define PREFSFILE "ENVARC:WBStartup+"
  71.  
  72. #define OUTSIDEBORDER 10
  73. #define GADTEXTBORDERSUM 6
  74.  
  75. ULONG PRIORITYEDGE;  /* The horizontal position in the listview gadget to draw the vertical line */
  76.  
  77. /*  ln_Type's  */
  78. #define EXECUTE  TRUE
  79. #define STORAGE  FALSE
  80.  
  81.  
  82. void GetFilenames(struct List *filenamequeue, APTR memPool, char *directory, UBYTE type, struct WBStartupPrefs *prefs);
  83. struct WBSPNode *AddFileToList(struct List *filenamequeue, APTR memPool, char *pathname, UBYTE type, struct WBStartupPrefs *prefs);
  84. void RunPrograms(struct List *filenamequeue, char *path);
  85. void GetArguments(int argc, char **argv, struct WBStartupPrefs *prefs);
  86. void ProcessEvents(struct List *list, struct List *grouplist, struct WBStartupPrefs *prefs, APTR groupPool);
  87. BOOL RenderGadgets(struct Gadget **glist, void *vi,
  88. struct Window *win, struct Gadget *my_gads[], struct List *list,
  89. struct Gadget *(*CreateGadgetsFunction)(struct Gadget **glistptr, void *vi, struct Window *win, struct Gadget *my_gads[], struct List *list));
  90.  
  91. void ShowRequester(STRPTR RequesterText);
  92. struct Gadget *createAllGadgets(struct Gadget **glistptr, void *vi, struct Window *win, struct Gadget *my_gads[], struct List *list);
  93. void RestoreTypes(struct List *filenamequeue);
  94. void SaveChanges(struct List *list, struct WBStartupPrefs *prefs);
  95. BOOL ChangePriTooltype(char *filename, BYTE pri);
  96. void ShowWBIconRequester(struct WBSPNode *node, struct WBStartupPrefs *Prefs, struct Screen *scr);
  97. void AlphabetizeList(struct List *list);
  98. ULONG GetScreenHeight(struct Screen *scr);
  99. ULONG BestWindowHeight(struct Screen *scr, struct List *list);
  100. ULONG ListViewHeight(struct Screen *scr, struct List *list);
  101. void SortPriorityList(struct List *list);
  102.  
  103. void SaveGroups(struct List *list);
  104. void ReadGroups(struct List *list, APTR memPool);
  105. void CreateGroup(struct List *grouplist, struct List *wbsplist, char *groupname, APTR memPool);
  106. void SelectGroup(struct List *wbsplist, struct List *list);
  107. void DeleteGroup(struct GroupNode *node, APTR memPool);
  108.  
  109. BOOL ShowGroupsRequester(void);
  110. BOOL CopyFile(char *source,char *dest);
  111.  
  112.  
  113. struct IntuitionBase *IntuitionBase;
  114. struct Library *GadToolsBase;
  115. struct Library *CxBase, *IconBase;
  116. struct Library *ScreenNotifyBase;
  117. struct Library *WorkbenchBase;
  118. struct Library *DiskfontBase;
  119. struct GfxBase *GfxBase;
  120. struct Library *UtilityBase;
  121.  
  122. /****************************************************************************************/
  123.  
  124. struct Hook CBLVHook;
  125.  
  126. /****************************************************************************************/
  127.  
  128.  
  129. main (int argc, char **argv)
  130. {
  131.   struct List filenamequeue;
  132.   struct List grouplist;
  133.   struct WBStartupPrefs prefs;
  134.   struct MsgPort *port;
  135.  
  136.   struct WBSPNode titlenode =
  137.   {
  138.     {NULL,NULL,TITLE,127,NULL},
  139.     0
  140.   };
  141.  
  142.   if (IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",37))
  143.   {
  144.     if (CxBase = OpenLibrary("commodities.library", 37L))
  145.     {
  146.       if (IconBase = OpenLibrary("icon.library", 36L))
  147.       {
  148.         if (WorkbenchBase = OpenLibrary("workbench.library", 39L))
  149.         {
  150.           if (GadToolsBase=OpenLibrary("gadtools.library",39))
  151.           {
  152.             if (DiskfontBase = OpenLibrary("diskfont.library", 37L))
  153.             {
  154.               if (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 37L))
  155.               {
  156.                 if (UtilityBase = OpenLibrary("utility.library", 37L))
  157.                 {
  158.                   if (prefs.filenamePool=CreatePool(MEMF_PUBLIC,31,31))  /* Node is 14 bytes, largest filename is 30 */
  159.                   {
  160.                     if (prefs.groupPool=CreatePool(MEMF_PUBLIC,31,31))  /* Node is 14 bytes, largest filename is 30 */
  161.                     {
  162.                       NewList(&grouplist);
  163.                       NewList(&filenamequeue);
  164.                       if (titlenode.wbsp_node.ln_Name=AllocVec(strlen(GetString(STRProgramName))+strlen(GetString(STRPriority))+2,MEMF_PUBLIC))
  165.                         sprintf(titlenode.wbsp_node.ln_Name,"%s,%s",GetString(STRProgramName),GetString(STRPriority));
  166.                       AddHead(&filenamequeue,&titlenode);
  167.  
  168.                       GetArguments(argc, argv, &prefs);
  169.  
  170.                       if (prefs.EnabledDirLock=Lock(prefs.ExecutePath,ACCESS_READ))
  171.                       {
  172.                         if (prefs.DisabledDirLock=Lock(prefs.StoragePath,ACCESS_READ))
  173.                         {
  174.                           prefs.NumPrograms=0;
  175.                           GetFilenames(&filenamequeue,prefs.filenamePool,prefs.ExecutePath,EXECUTE,&prefs);
  176.                           GetFilenames(&filenamequeue,prefs.filenamePool,prefs.StoragePath,STORAGE,&prefs);
  177.  
  178.                           ReadGroups(&grouplist,prefs.groupPool);
  179.  
  180.                           if (prefs.Alphabetize)
  181.                             AlphabetizeList(&filenamequeue);
  182.  
  183.                           ProcessEvents(&filenamequeue, &grouplist, &prefs, prefs.groupPool);
  184.  
  185.                           UnLock(prefs.DisabledDirLock);
  186.                         }
  187.                         else
  188.                           ShowRequester(GetString(STRCouldntLockDir));
  189.                         UnLock(prefs.EnabledDirLock);
  190.                       }
  191.                       else
  192.                         ShowRequester(GetString(STRCouldntLockDir));
  193.  
  194.  
  195.                       if (titlenode.wbsp_node.ln_Name)
  196.                         FreeVec(titlenode.wbsp_node.ln_Name);
  197.  
  198.                       /* If WBStartup+ is running and waiting for us to quit, send it a message */
  199.                       Forbid();
  200.                       if (port=FindPort("WBStartup+"))
  201.                       {
  202.                         struct Message msg;
  203.                         PutMsg(port,&msg);
  204.                       }
  205.                       Permit();
  206.  
  207.  
  208.                       DeletePool(prefs.groupPool);
  209.                     }
  210.                     DeletePool(prefs.filenamePool);
  211.                   }
  212.                   CloseLibrary(UtilityBase);
  213.                 }
  214.                 CloseLibrary((struct Library *)GfxBase);
  215.               }
  216.               CloseLibrary(DiskfontBase);
  217.             }
  218.             CloseLibrary(GadToolsBase);
  219.           }
  220.           CloseLibrary(WorkbenchBase);
  221.         }
  222.         else
  223.           ShowRequester(GetString(STRRequiredDosVer));
  224.         CloseLibrary(IconBase);
  225.       }
  226.       CloseLibrary(CxBase);
  227.     }
  228.     CloseLibrary((struct Library *)IntuitionBase);
  229.   }
  230.  
  231.   #ifdef DEBUG
  232.     printf("Exiting\n");
  233.   #endif
  234. }
  235.  
  236. /* GetFilesnames() is NOT the same function that is in "WBStartup+.c" */
  237. void GetFilenames(struct List *filenamequeue, APTR memPool, char *directory, UBYTE type, struct WBStartupPrefs *prefs)
  238. {
  239.   struct ExAllControl *myexallctrl;  /* The ExAllControl structure */
  240.   struct ExAllData    *eadptr;       /* temp pointer to data structure */
  241.   BPTR mylock;                       /* Lock on the directory */
  242.   int more;                          /* Are there more entries ? */
  243.   struct ExAllData ExAllBuf[20];     /* hold the filenames and types */
  244.   char pathname[500];                /* path and filename of the icon */
  245.   char filename[32];                 /* parsed match string 2*length+2=22 */
  246.  
  247.  
  248.   if (mylock=Lock(directory,SHARED_LOCK))
  249.   {
  250.     if (myexallctrl=(struct ExAllControl *)AllocDosObjectTags(DOS_EXALLCONTROL,TAG_END))
  251.     {
  252.       myexallctrl->eac_LastKey = 0;
  253.       myexallctrl->eac_Entries = 0;
  254.       myexallctrl->eac_MatchString = NULL;
  255.       myexallctrl->eac_MatchFunc = NULL;
  256.  
  257.       do   /* go until more==0 */
  258.       {
  259.         more = ExAll(mylock, ExAllBuf, sizeof(ExAllBuf), ED_TYPE, myexallctrl);
  260.         if ((!more) && (IoErr() != ERROR_NO_MORE_ENTRIES))
  261.         {
  262.             ShowRequester("ExAll failed abnormally");//: %ld.", IoErr());
  263.             break;
  264.         }
  265.  
  266.         if (myexallctrl->eac_Entries)
  267.         {
  268.           eadptr=ExAllBuf;
  269.  
  270.           while (eadptr)
  271.           {
  272.             if (eadptr->ed_Type < 0)  /* make sure it is a file, not a directory, see end of dos/dosextens.h */
  273.             {
  274.               strcpy(filename, eadptr->ed_Name);
  275.  
  276.               /* truncate the filename if it is an icon, ie. remove the ".info" */
  277.               if (!Stricmp(filename+strlen(filename)-5,".info"))
  278.                 filename[strlen(filename) - 5] = NULL;  /* take the .info off of the string */
  279.               else
  280.                 filename[strlen(filename)] = NULL;  /* take the .info off of the string */
  281.  
  282.               /* See if the file is already in the list */
  283.               if (!FindName(filenamequeue,filename))
  284.               {
  285.                 if (Stricmp(filename,"WBStartup+"))  /* Make sure we don't recursively run ourself */
  286.                 {
  287.                   strcpy(pathname,directory);
  288.                   AddPart(pathname, filename, 500);
  289.  
  290.                   AddFileToList(filenamequeue,memPool,pathname,type,prefs);
  291.                 }
  292.               }
  293.             }
  294.             eadptr=eadptr->ed_Next;
  295.           }
  296.         }
  297.  
  298.       } while (more);
  299.  
  300.       FreeDosObject(DOS_EXALLCONTROL,myexallctrl);
  301.     }
  302.     else
  303.       ShowRequester("Not enough memory for ExAllControl.");
  304.     UnLock(mylock);
  305.   }
  306.   else
  307.     ShowRequester(GetString(STRCouldntLockDir));
  308. }
  309.  
  310.  
  311. struct WBSPNode *AddFileToList(struct List *filenamequeue, APTR memPool, char *pathname, UBYTE type, struct WBStartupPrefs *prefs)
  312. {
  313.   /* pathname should be like:  ram:t/myfile */
  314.   struct WBSPNode *node;             /* hold the filenames and proiority for the List */
  315.   struct DiskObject *diskobj;        /* Pointer to the icon info */
  316.   char *toolstring;                  /* Pointer to a tooltype string */
  317.   char *filenameptr;
  318.  
  319.   filenameptr=FilePart(pathname);
  320.  
  321.   if (diskobj=GetDiskObjectNew(pathname))
  322.   {
  323.     if ((diskobj->do_Type==WBPROJECT) || (diskobj->do_Type==WBTOOL))  /* Make sure we got an icon that isn't a drawer icon */
  324.     {
  325.       if (node=(struct WBSPNode *)AllocPooled(memPool,sizeof(struct WBSPNode)))
  326.       {
  327.         if (node->wbsp_node.ln_Name=(char *)AllocPooled(memPool, strlen(filenameptr)+1))
  328.         {
  329.           strcpy(node->wbsp_node.ln_Name, filenameptr);
  330.           if (toolstring=FindToolType(diskobj->do_ToolTypes,"STARTPRI"))
  331.             node->wbsp_node.ln_Pri = node->Original_Priority = atoi((char *)toolstring);
  332.           else
  333.             node->wbsp_node.ln_Pri = node->Original_Priority = 0;
  334.           node->wbsp_node.ln_Type = node->Original_Type = type;  /* EXECUTE or STORAGE */
  335.           Enqueue(filenamequeue,node);
  336.           prefs->NumPrograms++;
  337.         }
  338.       }
  339.     }
  340.     FreeDiskObject(diskobj);
  341.   }
  342.   return(node);
  343. }
  344.  
  345.  
  346.  
  347. void GetArguments(int argc, char **argv, struct WBStartupPrefs *prefs)
  348. {
  349.   UBYTE **ttypes;
  350.  
  351.   ttypes = ArgArrayInit(argc,argv);
  352.   strcpy(prefs->ExecutePath , ArgString(ttypes,"ENABLEDPATH","SYS:WBStartup/WBStartup (Enabled)"));
  353.   strcpy(prefs->StoragePath , ArgString(ttypes,"DISABLEDPATH","SYS:WBStartup/WBStartup (Disabled)"));
  354.   prefs->Alphabetize = ((FindToolType(ttypes,"ALPHABETIZE")) ? TRUE : FALSE);
  355.   ArgArrayDone();
  356. }
  357.  
  358. void ProcessEvents(struct List *list, struct List *grouplist, struct WBStartupPrefs *prefs, APTR groupPool)
  359. {
  360.   ULONG signals;
  361.   ULONG winsigflag;
  362.   BOOL LOOP;
  363.   struct IntuiMessage *winmsg;
  364.   struct Window *win;
  365.   struct Screen *scr;
  366.   UBYTE  *WindowTitle="WBStartup+ Prefs";
  367.  
  368.   struct Menu *MainMenu;
  369.   struct MenuItem *menuitemaddress;
  370.   struct NewMenu MainNewMenu[25]=
  371.   {
  372.     { NM_TITLE, NULL/*"Project"*/,                0, 0, 0, 0, },
  373.     {   NM_ITEM,  NULL/*"Save"*/,               "S", 0, 0, (APTR)SAVE_MENU, },
  374.     {   NM_ITEM,  NM_BARLABEL,                 0, 0, 0, 0, },
  375.     {   NM_ITEM,  NULL/*"About..."*/,              "?", 0, 0, (APTR)ABOUT_MENU, },
  376.     {   NM_ITEM,  NM_BARLABEL,                 0, 0, 0, 0, },
  377.     {   NM_ITEM,  NULL/*"Quit"*/,               "Q", 0, 0, (APTR)QUIT_MENU, },
  378.     { NM_TITLE, NULL/*"Edit"*/,                   0, 0, 0, 0, },
  379.     {   NM_ITEM,  NULL/*"Restore"*/,            "R", 0, 0, (APTR)RESTORE_MENU, },
  380.     {   NM_ITEM,  NULL/*"Icon Window..."*/,     "I", 0, 0, (APTR)PROGRAMINFO_MENU, },
  381.     {   NM_ITEM,  NM_BARLABEL,                 0, 0, 0, 0, },
  382.     {   NM_ITEM,  NULL/*"Create Group..."*/,    "C", 0, 0, (APTR)CREATEGROUP_MENU, },
  383.     {   NM_ITEM,  NULL/*"Modify Group..."*/,    "M", 0, 0, (APTR)MODIFYGROUP_MENU, },
  384.     {   NM_ITEM,  NM_BARLABEL,                 0, 0, 0, 0, },
  385.     {   NM_ITEM,  NULL/*"Delete Group..."*/,    "D", 0, 0, (APTR)DELETEGROUP_MENU, },
  386.     { NM_TITLE, NULL/*"Sort"*/,                   0, 0, 0, 0, },
  387.     {   NM_ITEM,  NULL/*"Alphabetically"*/,     "Z", 0, 0, (APTR)SORTALPHABETICALLY_MENU, },
  388.     {   NM_ITEM,  NULL/*"Priority"*/,           "P", 0, 0, (APTR)SORTPRIORITY_MENU, },
  389.     { NM_TITLE, NULL/*"Select"*/,                 0, 0, 0, 0, },
  390.     {   NM_ITEM,  NULL/*"All"*/,                "A", 0, 0, (APTR)SELECTALL_MENU, },
  391.     {   NM_ITEM,  NULL/*"None"*/,               "N", 0, 0, (APTR)SELECTNONE_MENU, },
  392.     {   NM_ITEM,  NULL/*"Toggle"*/,             "T", 0, 0, (APTR)SELECTTOGGLE_MENU, },
  393.     {   NM_ITEM,  NM_BARLABEL,                 0, 0, 0, 0, },
  394.     {   NM_ITEM,  NULL/*"Group..."*/,           "G", 0, 0, (APTR)SELECTGROUP_MENU, },
  395.       { NM_END,   NULL,                          0, 0, 0, 0, },
  396.   };
  397.   struct VisualInfo *vi;
  398.  
  399.   struct Gadget *glist=NULL, *my_gads[TOTALGADGETS];
  400.     struct Node *n;
  401.   struct WBSPNode *node;
  402.   struct GroupNode *groupnode;  /* ptr to a node in the group list */
  403.     long z;
  404.   ULONG height;
  405.   UBYTE oldpriority;
  406.   char groupname[40];
  407.  
  408.   BOOL GroupsModified=FALSE;
  409.  
  410.   ULONG appwinsig = 0L;
  411.   struct MsgPort *awport;
  412.   struct AppWindow *appwin;
  413.   struct AppMessage *amsg;
  414.   struct WBArg *argptr;
  415.   LONG argnum;
  416.   char *sourcename,*destname;
  417.  
  418.   int count=0;
  419.  
  420.   /* Put strings in Menu */
  421.   MainNewMenu[count++].nm_Label = GetString(STRProjectMenu);
  422.   MainNewMenu[count++].nm_Label = GetString(STRSaveMenu);
  423.   MainNewMenu[count++].nm_Label = NM_BARLABEL;
  424.   MainNewMenu[count++].nm_Label = GetString(STRAboutMenu);
  425.   MainNewMenu[count++].nm_Label = NM_BARLABEL;
  426.   MainNewMenu[count++].nm_Label = GetString(STRQuitMenu);
  427.   MainNewMenu[count++].nm_Label = GetString(STREditMenu);
  428.   MainNewMenu[count++].nm_Label = GetString(STRRestoreMenu);
  429.   MainNewMenu[count++].nm_Label = GetString(STRIconWindowMenu);
  430.   MainNewMenu[count++].nm_Label = NM_BARLABEL;
  431.   MainNewMenu[count++].nm_Label = GetString(STRCreateGroupMenu);
  432.   MainNewMenu[count++].nm_Label = GetString(STRModifyGroupMenu);
  433.   MainNewMenu[count++].nm_Label = NM_BARLABEL;
  434.   MainNewMenu[count++].nm_Label = GetString(STRDeleteGroupMenu);
  435.   MainNewMenu[count++].nm_Label = GetString(STRSortMenu);
  436.   MainNewMenu[count++].nm_Label = GetString(STRAlphabeticallyMenu);
  437.   MainNewMenu[count++].nm_Label = GetString(STRPriorityMenu);
  438.   MainNewMenu[count++].nm_Label = GetString(STRSelectMenu);
  439.   MainNewMenu[count++].nm_Label = GetString(STRAllMenu);
  440.   MainNewMenu[count++].nm_Label = GetString(STRNoneMenu);
  441.   MainNewMenu[count++].nm_Label = GetString(STRToggleMenu);
  442.   MainNewMenu[count++].nm_Label = NM_BARLABEL;
  443.   MainNewMenu[count].nm_Label = GetString(STRGroupMenu);
  444.  
  445.  
  446.   if (scr=LockPubScreen(NULL))
  447.   {
  448.     ChecklistFont.ta_Name = scr->Font->ta_Name;
  449.     ChecklistFont.ta_YSize = scr->Font->ta_YSize;
  450.  
  451.     if (vi=GetVisualInfo(scr,TAG_END))
  452.     {
  453.       height = BestWindowHeight(scr,list);
  454.       if (win = OpenWindowTags(NULL,
  455.             WA_Left,   100 + ((scr->LeftEdge < 0) ? (-scr->LeftEdge) : 0),
  456.             WA_Top,    20 + ((scr->TopEdge < 0) ? (-scr->TopEdge) : 0),
  457.             WA_Width, (TextLength(&scr->RastPort,GetString(STRProgramName),strlen(GetString(STRProgramName)))*2)
  458.               + (TextLength(&scr->RastPort,GetString(STRPriority),strlen(GetString(STRPriority)))*2)
  459.               + (2 * OUTSIDEBORDER)
  460.               + scr->WBorLeft + scr->WBorRight,
  461.             WA_Height, height,
  462.             WA_MinWidth, 264,
  463.             WA_MinHeight, scr->WBorTop + (2 * scr->Font->ta_YSize) + 1 + 160 + scr->WBorBottom,
  464.             WA_MaxWidth, ~0,
  465.             WA_MaxHeight, ~0,
  466.             WA_AutoAdjust, TRUE,
  467.             WA_IDCMP,  IDCMP_RAWKEY | IDCMP_NEWSIZE | IDCMP_GADGETUP | IDCMP_MENUPICK | IDCMP_CLOSEWINDOW | IDCMP_REFRESHWINDOW | LISTVIEWIDCMP,
  468.             WA_Flags, WFLG_SIZEGADGET | WFLG_SIZEBBOTTOM | WFLG_NEWLOOKMENUS | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_SMART_REFRESH | WFLG_ACTIVATE,
  469.             WA_Title,  WindowTitle,
  470.             WA_PubScreen, scr,
  471.             TAG_END))
  472.       {
  473.         winsigflag=1L<<win->UserPort->mp_SigBit;
  474.         if (MainMenu = CreateMenus( &MainNewMenu[0], TAG_DONE ))
  475.           if (LayoutMenus( MainMenu, vi, GTMN_NewLookMenus, TRUE, TAG_DONE ))
  476.             SetMenuStrip( win, MainMenu );
  477.  
  478.         if (RenderGadgets(&glist, vi, win, my_gads, list, createAllGadgets))
  479.         {
  480.  
  481.           if (awport=CreateMsgPort())
  482.             if (appwin = AddAppWindow(1,0,win,awport,NULL))
  483.               appwinsig = 1L << awport->mp_SigBit;
  484.  
  485.           LOOP=TRUE;
  486.           while (LOOP)
  487.           {
  488.             signals=Wait(SIGBREAKF_CTRL_C | winsigflag | appwinsig);
  489.       
  490.             if (signals & SIGBREAKF_CTRL_C)
  491.               LOOP=FALSE;
  492.       
  493.             if (signals & winsigflag)
  494.             {
  495.               while (winmsg = (struct IntuiMessage *)GT_GetIMsg((struct MsgPort *)win->UserPort))
  496.               {
  497.                 switch(winmsg->Class)
  498.                 {
  499.                   case IDCMP_RAWKEY:
  500.                     switch(winmsg->Code)
  501.                     {
  502.                       case 76:    // Up Arrow
  503.                         GT_GetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Selected, &z, TAG_DONE);
  504.                         if (z>1)
  505.                           z--;
  506.                         GT_SetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Selected, z, TAG_DONE);
  507.                         break;
  508.                       case 77:    // Down Arrow
  509.                         GT_GetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Selected, &z, TAG_DONE);
  510.                         if (z == (~0))
  511.                           z=1;
  512.                         else if (z < prefs->NumPrograms)
  513.                           z++;
  514.                         GT_SetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Selected, z, TAG_DONE);
  515.                         break;
  516.                     }
  517.                     break;
  518.                   case IDCMP_NEWSIZE:
  519.                     RemoveGList(win,glist,-1);
  520.                     FreeGadgets(glist);
  521.                     RefreshWindowFrame(win);
  522.                     RenderGadgets(&glist, vi, win, my_gads, list, createAllGadgets);
  523.                     break;
  524.                   case IDCMP_MENUPICK:
  525.                     while( winmsg->Code != MENUNULL )
  526.                     {
  527.                       menuitemaddress = ItemAddress( MainMenu, winmsg->Code );
  528.                         switch((int)GTMENUITEM_USERDATA(menuitemaddress))
  529.                         {
  530.                           case SAVE_MENU:
  531.                             SetWindowTitles(win,GetString(STRSaving),(UBYTE *) ~0);
  532.                             SaveChanges(list, prefs);
  533.                             LOOP=FALSE;
  534.                             break;
  535.                           case ABOUT_MENU:
  536.                             {
  537.                               char *abouttext;
  538.                               DisableWindow(win);
  539.                               if (abouttext=AllocVec(strlen(GetString(STRAbout))+5+30+25,MEMF_PUBLIC))
  540.                               {
  541.                                 sprintf(abouttext,GetString(STRAbout),VERSION,COPYRIGHT,DATETEXT);
  542.                                 ShowRequester(abouttext);
  543.                                 FreeVec(abouttext);
  544.                               }
  545.                               EnableWindow(win);
  546.                             }
  547.                             break;
  548.                           case QUIT_MENU:
  549.                             LOOP=FALSE;
  550.                             break;
  551.                           case RESTORE_MENU:
  552.                             GT_SetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Labels, ~0, TAG_DONE);
  553.                             RestoreTypes(list);
  554.                             GT_SetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Labels, list, TAG_DONE);
  555.                             break;
  556.                           case PROGRAMINFO_MENU:
  557.                             GT_GetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Selected, &z, TAG_DONE);
  558.                             if (z != ~0)
  559.                             {
  560.                               for (n = list->lh_Head; z; z--)
  561.                                 n = n->ln_Succ;
  562.                               if (n->ln_Type != TITLE)
  563.                               {
  564.                                 DisableWindow(win);
  565.                                 ShowWBIconRequester((struct WBSPNode *)n, prefs, win->WScreen);
  566.                                 EnableWindow(win);
  567.                               }
  568.                             }
  569.                             else
  570.                               ShowRequester("You must first select a program!");
  571.                             break;
  572.                           case SORTALPHABETICALLY_MENU:
  573.                             GT_SetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Labels, ~0, TAG_DONE);
  574.                             AlphabetizeList(list);
  575.                             GT_SetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Labels, list, TAG_DONE);
  576.                             prefs->Alphabetize = TRUE;
  577.                             break;
  578.                           case SORTPRIORITY_MENU:
  579.                             GT_SetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Labels, ~0, TAG_DONE);
  580.                             SortPriorityList(list);
  581.                             GT_SetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Labels, list, TAG_DONE);
  582.                             prefs->Alphabetize = FALSE;
  583.                             break;
  584.                           case SELECTALL_MENU:
  585.                             GT_SetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Labels, ~0, TAG_DONE);
  586.                             for (node = (struct WBSPNode *)list->lh_Head; node->wbsp_node.ln_Succ; node = (struct WBSPNode *)node->wbsp_node.ln_Succ)
  587.                               if (node->wbsp_node.ln_Type != TITLE)
  588.                                 node->wbsp_node.ln_Type = EXECUTE;
  589.                             GT_SetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Labels, list, TAG_DONE);
  590.                             break;
  591.                           case SELECTNONE_MENU:
  592.                             GT_SetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Labels, ~0, TAG_DONE);
  593.                             for (node = (struct WBSPNode *)list->lh_Head; node->wbsp_node.ln_Succ; node = (struct WBSPNode *)node->wbsp_node.ln_Succ)
  594.                               if (node->wbsp_node.ln_Type != TITLE)
  595.                                 node->wbsp_node.ln_Type = STORAGE;
  596.                             GT_SetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Labels, list, TAG_DONE);
  597.                             break;
  598.                           case SELECTTOGGLE_MENU:
  599.                             GT_SetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Labels, ~0, TAG_DONE);
  600.                             for (node = (struct WBSPNode *)list->lh_Head; node->wbsp_node.ln_Succ; node = (struct WBSPNode *)node->wbsp_node.ln_Succ)
  601.                               if (node->wbsp_node.ln_Type != TITLE)
  602.                                 if (node->wbsp_node.ln_Type == EXECUTE)
  603.                                   node->wbsp_node.ln_Type = STORAGE;
  604.                                 else
  605.                                   node->wbsp_node.ln_Type = EXECUTE;
  606.                             GT_SetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Labels, list, TAG_DONE);
  607.                             break;
  608.                           case CREATEGROUP_MENU:
  609.                             DisableWindow(win);
  610.                             groupname[0]=NULL;  /* Clear the group name string */
  611.                             GetStringWindow(win->LeftEdge+winmsg->MouseX,win->TopEdge+winmsg->MouseY,GetString(STRGroupName),groupname,30);
  612.                             if (groupname[0])
  613.                             {
  614.                               CreateGroup(grouplist, list, groupname, groupPool);
  615.                               GroupsModified=TRUE;
  616.                             }
  617.                             EnableWindow(win);
  618.                             break;
  619.                           case DELETEGROUP_MENU:
  620.                             DisableWindow(win);
  621.                             if (groupnode = (struct GroupNode *)ChooseGroup(win->LeftEdge+winmsg->MouseX, win->TopEdge+winmsg->MouseY, grouplist, "Delete Group"))
  622.                             {
  623.                               DeleteGroup(groupnode, groupPool);
  624.                               GroupsModified=TRUE;
  625.                             }
  626.                             EnableWindow(win);
  627.                             break;
  628.                           case MODIFYGROUP_MENU:
  629.                             DisableWindow(win);
  630.                             if (groupnode = (struct GroupNode *)ChooseGroup(win->LeftEdge+winmsg->MouseX, win->TopEdge+winmsg->MouseY, grouplist, "Modify Group"))
  631.                             {
  632.                               strcpy(groupname,groupnode->group_node.ln_Name);
  633.                               DeleteGroup(groupnode,groupPool);
  634.                               CreateGroup(grouplist, list, groupname, groupPool);
  635.                               GroupsModified=TRUE;
  636.                             }
  637.                             EnableWindow(win);
  638.                             break;
  639.                           case SELECTGROUP_MENU:
  640.                             DisableWindow(win);
  641.                             groupnode = (struct GroupNode *)ChooseGroup(win->LeftEdge+winmsg->MouseX, win->TopEdge+winmsg->MouseY, grouplist, "Select Group");
  642.                             if (groupnode)
  643.                             {
  644.                               GT_SetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Labels, ~0, TAG_DONE);
  645.                               SelectGroup(list, &(groupnode->enabled));
  646.                               GT_SetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Labels, list, TAG_DONE);
  647.                             }
  648.                             EnableWindow(win);
  649.                             break;
  650.                         }
  651.                       winmsg->Code = menuitemaddress->NextSelect;
  652.                     }
  653.                     break;
  654.                   case IDCMP_GADGETUP:
  655.                     switch(((struct Gadget *)winmsg->IAddress)->GadgetID)
  656.                     {
  657.                       case SAVE_GAD:
  658.                         SetWindowTitles(win,GetString(STRSaving),(UBYTE *) ~0);
  659.                         SaveChanges(list, prefs);
  660.                         SaveGroups(grouplist);
  661.                         GroupsModified=FALSE;
  662.                         LOOP=FALSE;
  663.                         break;
  664.                       case CANCEL_GAD:
  665.                         LOOP=FALSE;
  666.                         break;
  667.                       case LIST_GAD:
  668.                         z = winmsg->Code;
  669.                         for (n = list->lh_Head; z; z--)
  670.                           n = n->ln_Succ;
  671.                         if (n->ln_Type != TITLE)
  672.                         {
  673.                           if(winmsg->MouseX < my_gads[LIST_GAD]->LeftEdge+xoff) /* checkbox was clicked */
  674.                           {
  675.                             GT_SetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Labels, ~0, TAG_DONE);
  676.                             if (n->ln_Type == EXECUTE)
  677.                               n->ln_Type = STORAGE;
  678.                             else if (n->ln_Type == STORAGE)
  679.                               n->ln_Type = EXECUTE;
  680.                             GT_SetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Labels, list, TAG_DONE);
  681.                           }
  682.                           else if (winmsg->MouseX > my_gads[LIST_GAD]->LeftEdge+PRIORITYEDGE+2) /* priority clicked */
  683.                           {
  684.                             DisableWindow(win);
  685.                             GT_SetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Labels, ~0, TAG_DONE);
  686.                             oldpriority = n->ln_Pri;
  687.                             n->ln_Pri=GetPriority(n->ln_Pri,win->LeftEdge+winmsg->MouseX,win->TopEdge+winmsg->MouseY);
  688.                             if (oldpriority != n->ln_Pri)
  689.                               if (!prefs->Alphabetize)
  690.                               {
  691.                                 Remove(n);
  692.                                 Enqueue(list,n);
  693.                               }
  694.                             GT_SetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Labels, list, TAG_DONE);
  695.                             EnableWindow(win);
  696.                           }
  697.                         }
  698.                         break;
  699.                     }
  700.                     break;
  701.                   case IDCMP_CLOSEWINDOW:
  702.                     LOOP=FALSE;
  703.                     break;
  704.                   case IDCMP_REFRESHWINDOW:
  705.                     BeginRefresh(win);
  706.                     EndRefresh(win, TRUE);
  707.                     break;
  708.                 }
  709.                 GT_ReplyIMsg(winmsg);
  710.               }
  711.             }  /* End of process window events */
  712.  
  713.             /*****************************/
  714.             /* Process App Window events */
  715.             /*****************************/
  716.             if (signals & appwinsig)
  717.             {
  718.               while (amsg = (struct AppMessage *) GetMsg(awport))
  719.               {
  720.                 int flags=WBSP_ENABLED;
  721.  
  722.                 if (SameLock(amsg->am_ArgList->wa_Lock,prefs->EnabledDirLock)==LOCK_SAME_VOLUME)
  723.                   flags |= WBSP_MOVE;
  724.                 flags = CopyWindow(win->LeftEdge+amsg->am_MouseX,win->TopEdge+amsg->am_MouseY,flags);
  725.  
  726.                 if (!(flags & WBSP_CANCEL))
  727.                 {
  728.                   argptr = amsg->am_ArgList;
  729.                   for (argnum=0; argnum < amsg->am_NumArgs; argnum++)
  730.                   {
  731.                     SetWindowTitles(win,GetString(STRCopyingFiles),(UBYTE *) ~0);
  732.  
  733.                     if (sourcename=(char *)AllocVec(500,MEMF_PUBLIC))
  734.                     {
  735.                       int destlen;
  736.  
  737.                       NameFromLock(argptr->wa_Lock,sourcename,500);
  738.                       AddPart(sourcename,argptr->wa_Name,500);
  739.  
  740.                       if (flags & WBSP_ENABLED)
  741.                         destlen = strlen(prefs->ExecutePath)+strlen(argptr->wa_Name)+2;
  742.                       else
  743.                         destlen = strlen(prefs->StoragePath)+strlen(argptr->wa_Name)+2;
  744.  
  745.                       if (destname=(char *)AllocVec(destlen,MEMF_PUBLIC))
  746.                       {
  747.                         strcpy(destname,(flags & WBSP_ENABLED) ? prefs->ExecutePath : prefs->StoragePath);
  748.                         AddPart(destname,argptr->wa_Name,500);
  749.  
  750.                         /* Copy or Move files */
  751.                         if (flags & WBSP_MOVE)
  752.                         {
  753.                           if (SameLock(amsg->am_ArgList->wa_Lock,prefs->EnabledDirLock)==LOCK_SAME_VOLUME)
  754.                           {
  755.                             /* Move files on same device */
  756.                             struct DiskObject *diskobj;
  757.  
  758.                             Rename(sourcename,destname);
  759.                             if (diskobj=GetDiskObject(sourcename))
  760.                             {
  761.                               diskobj->do_CurrentX = diskobj->do_CurrentY = NO_ICON_POSITION;
  762.                               if (PutDiskObject(destname,diskobj))
  763.                                 DeleteDiskObject(sourcename);
  764.                               FreeDiskObject(diskobj);
  765.                             }
  766.                           }
  767.                           else
  768.                             /* Move files on different devices */
  769.                             if (CopyFile(sourcename,destname))
  770.                             {
  771.                               DeleteFile(sourcename);
  772.                               DeleteDiskObject(sourcename);
  773.                             }
  774.                         }
  775.                         else
  776.                           CopyFile(sourcename,destname);
  777.  
  778.                         /* Add file to list */
  779.                         GT_SetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Labels, ~0, TAG_DONE);
  780.                         AddFileToList(list,prefs->filenamePool,destname, (flags & WBSP_ENABLED) ? EXECUTE : STORAGE, prefs);
  781.                         if (prefs->Alphabetize)
  782.                           AlphabetizeList(list);
  783.                         else
  784.                           SortPriorityList(list);
  785.                         GT_SetGadgetAttrs(my_gads[LIST_GAD], win, NULL, GTLV_Labels, list, TAG_DONE);
  786.  
  787.                         FreeVec(destname);
  788.                       }
  789.                       FreeVec(sourcename);
  790.                       argptr++;
  791.                     }
  792.                   }
  793.                 }
  794.                 ReplyMsg((struct Message *)amsg);
  795.                 SetWindowTitles(win,WindowTitle,(UBYTE *) ~0);
  796.               }
  797.             }  /* End of Process App Window events */
  798.  
  799.           }   /* End of while (LOOP) */
  800.  
  801.           /* Remove AppWindow stuff */
  802.           if (appwin)
  803.             RemoveAppWindow(appwin);
  804.           if (awport)
  805.           {
  806.             while (amsg = (struct AppMessage *)GetMsg(awport))
  807.               ReplyMsg((struct Message *)amsg);
  808.             DeleteMsgPort(awport);
  809.           }
  810.  
  811.           /* Remove Menu and gadget stuff */
  812.           ClearMenuStrip( win );
  813.           FreeMenus( MainMenu );
  814.           RemoveGList(win,glist,-1);
  815.  
  816.  
  817.           /* Notify user if groups were modified. */
  818.           if (GroupsModified)
  819.             if(ShowGroupsRequester())
  820.               SaveGroups(grouplist);
  821.  
  822.  
  823.         } /* End of createAllGadgets() */
  824.         FreeGadgets(glist);
  825.         /* Free up the checkmark box object that was made during the listview callbacks */
  826.         CheckBoxList_CallBack_CleanUp(); 
  827.         CloseWindow(win);
  828.       }  /* End of if(OpenWindowTags()) */
  829.       FreeVisualInfo(vi);
  830.     }
  831.     UnlockPubScreen(NULL,scr);
  832.   }
  833. }
  834.  
  835. BOOL RenderGadgets(struct Gadget **glist, void *vi,
  836.   struct Window *win, struct Gadget *my_gads[], struct List *list,
  837.   struct Gadget *(*CreateGadgetsFunction)(struct Gadget **glistptr, void *vi, struct Window *win, struct Gadget *my_gads[], struct List *list))
  838. {
  839.   /* This function now intializes *glist to NULL, since it must be null when we later call CreateContext() in another function */
  840.   BOOL success=FALSE;
  841.   struct DrawInfo *dri;
  842.  
  843.   *glist=NULL;  /* This is for security! Do not remove!, otherwise enforcer hits will appear */
  844.  
  845.   if (dri = GetScreenDrawInfo(win->WScreen))
  846.   {
  847.     /* Fill window with Crosshatch */
  848.     SetAfPt(win->RPort,(UWORD *)&Crosshatch,1);
  849.     SetAPen(win->RPort,dri->dri_Pens[BACKGROUNDPEN]);
  850.     SetBPen(win->RPort,dri->dri_Pens[SHINEPEN]);
  851.     RectFill(win->RPort,win->BorderLeft,win->BorderTop,win->Width-win->BorderRight-1,win->Height-win->BorderBottom-1);
  852.     FreeScreenDrawInfo( win->WScreen, dri );
  853.   }
  854.  
  855.   if (CreateGadgetsFunction(glist, vi, win, my_gads, list))
  856.   {
  857.     if (dri = GetScreenDrawInfo(win->WScreen))
  858.     {
  859.       /* Fill clear area in window where the listview gadget will be */
  860.       SetAfPt(win->RPort,(UWORD *)&SolidLine,1);
  861.       SetAPen(win->RPort,0);
  862.       RectFill(win->RPort,my_gads[LIST_GAD]->LeftEdge,my_gads[LIST_GAD]->TopEdge,my_gads[LIST_GAD]->LeftEdge+my_gads[LIST_GAD]->Width-1,my_gads[LIST_GAD]->TopEdge+my_gads[LIST_GAD]->Height-1);
  863.       FreeScreenDrawInfo( win->WScreen, dri );
  864.     }
  865.  
  866.     AddGList(win,*glist,-1,-1,NULL);
  867.     RefreshGList(*glist,win,NULL,-1);
  868.     GT_RefreshWindow(win,NULL);
  869.  
  870.     success=TRUE;
  871.   }
  872.   return(success);
  873. }
  874.  
  875.  
  876. void ShowRequester(STRPTR RequesterText)
  877. {
  878.   struct EasyStruct myRequestStruct={
  879.     sizeof (struct EasyStruct ),
  880.     0,
  881.     "WBStartup+Prefs",
  882.     NULL,
  883.     NULL};
  884.  
  885.   myRequestStruct.es_GadgetFormat=GetString(STROk);
  886.   myRequestStruct.es_TextFormat=RequesterText;
  887.   EasyRequestArgs(NULL,&myRequestStruct,NULL,NULL);
  888. }
  889.  
  890. struct Gadget *createAllGadgets(struct Gadget **glistptr, void *vi, struct Window *win, struct Gadget *my_gads[], struct List *list)
  891. {
  892.   struct NewGadget ng;
  893.   struct Gadget *gad;
  894.   ULONG  buttonwidth,maxbuttonwidth;
  895.   ULONG  canceltextwidth,savetextwidth;
  896.  
  897.   gad = CreateContext(glistptr);
  898.  
  899.   ng.ng_LeftEdge = win->BorderLeft+OUTSIDEBORDER;
  900.   ng.ng_TopEdge = win->BorderTop+OUTSIDEBORDER;
  901.   ng.ng_Width = win->Width-win->BorderRight-win->BorderLeft-(2*OUTSIDEBORDER);
  902.   ng.ng_Height = win->Height-win->BorderTop-OUTSIDEBORDER-8-win->WScreen->Font->ta_YSize - GADTEXTBORDERSUM - 4 - win->BorderBottom;
  903.   ng.ng_GadgetText = NULL;
  904.   ng.ng_TextAttr = win->WScreen->Font;
  905.   ng.ng_VisualInfo = vi;
  906.   ng.ng_GadgetID = LIST_GAD;
  907.   ng.ng_Flags = 0;
  908.  
  909.   InitHook(&CBLVHook,CheckBoxList_CallBack,NULL);
  910.   my_gads[LIST_GAD] = gad = CreateGadget(LISTVIEW_KIND,gad,&ng,
  911.       GTLV_Labels,list,
  912.       GTLV_ShowSelected,0,
  913.       GTLV_CallBack,(ULONG) &CBLVHook,
  914.       LAYOUTA_Spacing,2,
  915.       TAG_DONE);
  916.  
  917.  
  918.   /* Determine where to draw the vertical line in the listview gadget */
  919.   PRIORITYEDGE = (my_gads[LIST_GAD]->Width * 15/24);
  920.  
  921.   /* Determine the optimal width of the Save and cancel gadgets */
  922.   canceltextwidth = TextLength(&win->WScreen->RastPort,GetString(STRCancel),strlen(GetString(STRCancel)));
  923.   savetextwidth   = TextLength(&win->WScreen->RastPort,GetString(STRSave),strlen(GetString(STRSave)));
  924.   maxbuttonwidth = 2 * max(canceltextwidth,savetextwidth);
  925.   buttonwidth = min(maxbuttonwidth , ((win->Width - win->BorderLeft - win->BorderRight - (OUTSIDEBORDER*2))/2)-8);
  926.  
  927.   ng.ng_TopEdge = win->Height - (win->WScreen->Font->ta_YSize + GADTEXTBORDERSUM + 4 + win->BorderBottom);
  928.   ng.ng_Width = buttonwidth;
  929.   ng.ng_Height = win->WScreen->Font->ta_YSize + GADTEXTBORDERSUM;
  930.   ng.ng_GadgetText = GetString(STRSave);
  931.   ng.ng_GadgetID = SAVE_GAD;
  932.  
  933.   my_gads[SAVE_GAD] = gad = CreateGadget(BUTTON_KIND,gad,&ng,TAG_DONE);
  934.  
  935.   ng.ng_LeftEdge = win->Width-win->BorderRight-OUTSIDEBORDER-buttonwidth;
  936.   ng.ng_GadgetText = GetString(STRCancel);
  937.   ng.ng_GadgetID = CANCEL_GAD;
  938.  
  939.   my_gads[CANCEL_GAD] = gad = CreateGadget(BUTTON_KIND,gad,&ng,TAG_DONE);
  940.  
  941.   return(gad);
  942. }
  943.  
  944. void RestoreTypes(struct List *filenamequeue)
  945. {
  946.   struct WBSPNode *node;
  947.  
  948.   for (node=(struct WBSPNode *)filenamequeue->lh_Head ; node->wbsp_node.ln_Succ ; node = (struct WBSPNode *)node->wbsp_node.ln_Succ)
  949.   {
  950.     if (node->wbsp_node.ln_Type != TITLE)
  951.     {
  952.       node->wbsp_node.ln_Type = node->Original_Type;
  953.       node->wbsp_node.ln_Pri = node->Original_Priority;
  954.     }
  955.   }
  956. }
  957.  
  958. void SaveChanges(struct List *list, struct WBStartupPrefs *prefs)
  959. {
  960.   struct WBSPNode *node;
  961.   char pathname1[500];
  962.   char icon1[500];
  963.   char pathname2[500];
  964.   char icon2[500];
  965.   BOOL DifferentVolumes = FALSE;  // TRUE when the Enabled and Disabled paths are on different volumes
  966.  
  967.   if (SameLock(prefs->EnabledDirLock, prefs->DisabledDirLock)==LOCK_DIFFERENT)
  968.     DifferentVolumes = TRUE;
  969.  
  970.   for (node=(struct WBSPNode *)list->lh_Head ; node->wbsp_node.ln_Succ ; node = (struct WBSPNode *)node->wbsp_node.ln_Succ)
  971.   {
  972.     if (node->wbsp_node.ln_Type != TITLE)
  973.     {
  974.       /* Change STARTPRI tooltypes */
  975.       if (node->wbsp_node.ln_Pri != node->Original_Priority)
  976.       {
  977.         if (node->Original_Type == EXECUTE)
  978.           strcpy(pathname1,prefs->ExecutePath);
  979.         else
  980.           strcpy(pathname1,prefs->StoragePath);
  981.         AddPart(pathname1,node->wbsp_node.ln_Name,1100-1);
  982.         ChangePriTooltype(pathname1,node->wbsp_node.ln_Pri);
  983.       }
  984.   
  985.       /* Move files */
  986.       if (node->wbsp_node.ln_Type != node->Original_Type)
  987.       {
  988.         strcpy(pathname1,prefs->ExecutePath);
  989.         AddPart(pathname1,node->wbsp_node.ln_Name,1100-1);
  990.         sprintf(icon1, "%s.info",pathname1 );
  991.   
  992.         strcpy(pathname2,prefs->StoragePath);
  993.         AddPart(pathname2,node->wbsp_node.ln_Name,1100-1);
  994.         sprintf(icon2, "%s.info",pathname2 );
  995.  
  996.         if (node->wbsp_node.ln_Type == STORAGE)
  997.         {
  998.           if (DifferentVolumes)
  999.           {
  1000.             /* Move files on different volumes */
  1001.             if (CopyFile(pathname1,pathname2))
  1002.             {
  1003.               DeleteFile(pathname1);
  1004.               DeleteDiskObject(pathname1);
  1005.             }
  1006.           }
  1007.           else
  1008.           {
  1009.             /* Move files on same volumes */
  1010.             Rename(pathname1,pathname2);
  1011.             Rename(icon1,icon2);
  1012.           }
  1013.         }
  1014.         else
  1015.         {
  1016.           if (DifferentVolumes)
  1017.           {
  1018.             /* Move files on different volumes */
  1019.             if (CopyFile(pathname2,pathname1))
  1020.             {
  1021.               DeleteFile(pathname2);
  1022.               DeleteDiskObject(pathname2);
  1023.             }
  1024.           }
  1025.           else
  1026.           {
  1027.             /* Move files on same volumes */
  1028.             Rename(pathname2,pathname1);
  1029.             Rename(icon2,icon1);
  1030.           }
  1031.         }
  1032.       }
  1033.     }
  1034.   }
  1035. }
  1036.  
  1037.  
  1038. BOOL ChangePriTooltype(char *filename, BYTE pri)
  1039. {
  1040.   struct DiskObject *dobj;
  1041.   char **oldtooltypes;
  1042.   char **newtooltypes;
  1043.   BOOL success=FALSE;
  1044.   char pristr[18];
  1045.   int numberoftooltypes=1; /* set it to 1 since we need one for the final NULL */
  1046.   char **ptr, **newptr;
  1047.   BOOL wrotepri=FALSE;
  1048.  
  1049.   if (dobj=GetDiskObjectNew(filename))
  1050.   {
  1051.     /* count tooltypes */
  1052.     for (ptr = dobj->do_ToolTypes; *ptr; ptr++)
  1053.       numberoftooltypes++;
  1054.     if (!FindToolType(dobj->do_ToolTypes,"STARTPRI"))
  1055.       numberoftooltypes++;
  1056.  
  1057.     /* Allocate new tooltype pointer list */
  1058.     if (newtooltypes = AllocVec(numberoftooltypes * sizeof(char *),MEMF_PUBLIC))
  1059.     {
  1060.       sprintf(pristr,"STARTPRI=%ld",(long)pri);
  1061.  
  1062.       /* Copy tooltype pointers */
  1063.       newptr=newtooltypes;
  1064.       for (ptr = dobj->do_ToolTypes; *ptr; ptr++)
  1065.       {
  1066.         if (strncmp(*ptr,"STARTPRI",8))
  1067.           *newptr = *ptr;  /* copy argument */
  1068.         else
  1069.         {
  1070.           if (!wrotepri)
  1071.           {
  1072.             *newptr = &pristr[0];
  1073.             wrotepri=TRUE;
  1074.           }
  1075.           else
  1076.             newptr--;
  1077.         }
  1078.         newptr++;
  1079.       }
  1080.       if (!wrotepri)
  1081.         *newptr++ = &pristr[0];
  1082.       *newptr = NULL;
  1083.  
  1084.       oldtooltypes = dobj->do_ToolTypes;
  1085.       dobj->do_ToolTypes = newtooltypes;
  1086.  
  1087.       success = PutDiskObject(filename, dobj);
  1088.  
  1089.       dobj->do_ToolTypes = oldtooltypes;
  1090.  
  1091.       FreeVec(newtooltypes);
  1092.     }
  1093.     FreeDiskObject(dobj);
  1094.   }
  1095.  
  1096.   return(success);
  1097. }
  1098.  
  1099. void ShowWBIconRequester(struct WBSPNode *node, struct WBStartupPrefs *prefs, struct Screen *scr)
  1100. {
  1101.   BPTR lock;
  1102.   char *dirname;
  1103.  
  1104.   if (node->Original_Type == EXECUTE)
  1105.     dirname = prefs->ExecutePath;
  1106.   else
  1107.     dirname = prefs->StoragePath;
  1108.  
  1109.   if (lock = Lock(dirname,SHARED_LOCK))
  1110.   {
  1111.     WBInfo(lock, node->wbsp_node.ln_Name, scr);
  1112.     UnLock(lock);
  1113.   }
  1114. }
  1115.  
  1116.  
  1117. void AlphabetizeList(struct List *list)
  1118. {
  1119.   struct List newlist;
  1120.   struct WBSPNode *titlenode, *node, *succ, *pred;
  1121.  
  1122.   NewList(&newlist);
  1123.  
  1124.   titlenode = (struct WBSPNode *)list->lh_Head;
  1125.   RemHead(list);
  1126.   while (!IsListEmpty(list))
  1127.   {
  1128.     node = (struct WBSPNode *)list->lh_Head;
  1129.     Remove(node);
  1130.  
  1131.     for (succ = (struct WBSPNode *)newlist.lh_Head; succ->wbsp_node.ln_Succ; succ = (struct WBSPNode *)succ->wbsp_node.ln_Succ)
  1132.       if( Stricmp(node->wbsp_node.ln_Name, succ->wbsp_node.ln_Name) <0 )
  1133.         break;
  1134.  
  1135.     if (succ->wbsp_node.ln_Pred == (struct Node *)&newlist)
  1136.       pred = NULL;
  1137.     else
  1138.       pred = (struct WBSPNode *)succ->wbsp_node.ln_Pred;
  1139.     Insert(&newlist,node,pred);
  1140.   }
  1141.   AddHead(&newlist,titlenode);  /* Put title node back in list */
  1142.   /* Copy the list structure */
  1143.   newlist.lh_TailPred->ln_Succ = (struct Node *)&(list->lh_Tail);
  1144.   list->lh_Head = newlist.lh_Head;
  1145.   list->lh_Tail = newlist.lh_Tail;
  1146.   list->lh_TailPred = newlist.lh_TailPred;
  1147. }
  1148.  
  1149. ULONG GetScreenHeight(struct Screen *scr)
  1150. {
  1151.   ULONG height;
  1152.   struct Rectangle rect;
  1153.  
  1154.   if (QueryOverscan(GetVPModeID(&(scr->ViewPort)), &rect, OSCAN_TEXT))
  1155.     height = rect.MaxY - rect.MinY + 1;
  1156.   else
  1157.     height = scr->WBorTop + (2 * scr->Font->ta_YSize) + 1 + 167 + scr->WBorBottom;
  1158.   height = min(height,scr->Height);
  1159.  
  1160.   height -= (20 + 20);  /* We want space above and below the window */
  1161.  
  1162.   return(height);
  1163. }
  1164.  
  1165.  
  1166. ULONG BestWindowHeight(struct Screen *scr, struct List *list)
  1167. {
  1168.   ULONG fontheight, windowheight, screenheight;
  1169.  
  1170.   fontheight = scr->Font->ta_YSize;
  1171.  
  1172.   /* To calculate the window's bottom border size, I use the same size as the top border. This is because urouhack makes them equal sizes for some odd reason. */
  1173.   windowheight = (scr->WBorTop + fontheight + 1) + OUTSIDEBORDER + ListViewHeight(scr,list) + 8 + (fontheight + GADTEXTBORDERSUM) + 4 + (scr->WBorTop + fontheight + 1);
  1174.   screenheight = GetScreenHeight(scr);
  1175.   windowheight = min(windowheight, screenheight);
  1176.  
  1177.   return(windowheight);
  1178. }
  1179.  
  1180.  
  1181. ULONG ListViewHeight(struct Screen *scr, struct List *list)
  1182. {
  1183.   struct WBSPNode *node;
  1184.   ULONG fontheight;
  1185.   ULONG listheight=0;
  1186.  
  1187.   fontheight = scr->Font->ta_YSize;
  1188.  
  1189.   /* Determine the height of the listview gadget with including all nodes in the list */
  1190.   for (node = (struct WBSPNode *)list->lh_Head; node->wbsp_node.ln_Succ; node=(struct WBSPNode *)node->wbsp_node.ln_Succ)
  1191.     listheight += fontheight + 2;  /* The 2 is the space between cells */
  1192.   listheight += 4; /* top and bottom borders of gadget */
  1193.  
  1194.   return(listheight);
  1195. }
  1196.  
  1197.  
  1198. void SortPriorityList(struct List *list)
  1199. {
  1200.   struct List newlist;
  1201.   struct WBSPNode *titlenode, *node;
  1202.  
  1203.   NewList(&newlist);
  1204.  
  1205.   titlenode = (struct WBSPNode *)list->lh_Head;
  1206.   RemHead(list);
  1207.   while (!IsListEmpty(list))
  1208.   {
  1209.     node = (struct WBSPNode *)list->lh_Head;
  1210.     Remove(node);
  1211.     Enqueue(&newlist,node);
  1212.   }
  1213.   AddHead(&newlist,titlenode);  /* Put title node back in list */
  1214.   /* Copy the list structure */
  1215.   newlist.lh_TailPred->ln_Succ = (struct Node *)&(list->lh_Tail);
  1216.   newlist.lh_Head->ln_Pred = (struct Node *)list;
  1217.   list->lh_Head = newlist.lh_Head;
  1218.   list->lh_Tail = newlist.lh_Tail;
  1219.   list->lh_TailPred = newlist.lh_TailPred;
  1220. }
  1221.  
  1222.  
  1223. void SaveGroups(struct List *list)
  1224. {
  1225.   BPTR file;
  1226.   struct GroupNode *groupnode;
  1227.   struct Node *node;
  1228.  
  1229.   if (file = Open(PREFSFILE,MODE_NEWFILE))
  1230.   {
  1231.     for (groupnode=(struct GroupNode *)list->lh_Head ; groupnode->group_node.ln_Succ ; groupnode = (struct GroupNode *)groupnode->group_node.ln_Succ)
  1232.     {
  1233.       FPutC(file,'@');
  1234.       FPuts(file, groupnode->group_node.ln_Name);
  1235.       FPutC(file,10);  /* 10 = NEWLINE */
  1236.       for (node = groupnode->enabled.lh_Head ; node->ln_Succ ; node = node->ln_Succ)
  1237.       {
  1238.         FPuts(file, node->ln_Name);
  1239.         FPutC(file,10);
  1240.       }
  1241.     }
  1242.     Close(file);
  1243.   }
  1244. }
  1245.  
  1246. void ReadGroups(struct List *list, APTR memPool)
  1247. {
  1248.   BPTR file;
  1249.   struct GroupNode *groupnode;
  1250.   struct Node *node;
  1251.   char buffer[40];
  1252.  
  1253.   NewList(list);
  1254.   if (file = Open(PREFSFILE,MODE_OLDFILE))
  1255.   {
  1256.     while (FGets(file,buffer,40))
  1257.     {
  1258.       buffer[strlen(buffer)-1]=NULL; /* Remove the NEWLINE character from the end */
  1259.       if (buffer[0] == '@')
  1260.       {
  1261.         if (groupnode=(struct GroupNode *)AllocPooled(memPool,sizeof(struct GroupNode)))
  1262.         {
  1263.           if (groupnode->group_node.ln_Name=(char *)AllocPooled(memPool,strlen(buffer+1)+1))
  1264.           {
  1265.             strcpy(groupnode->group_node.ln_Name,buffer+1);
  1266.             NewList(&groupnode->enabled);
  1267.             AddTail(list,groupnode);
  1268.           }
  1269.           else
  1270.             FreePooled(memPool,groupnode,sizeof(struct GroupNode));
  1271.         }
  1272.       }
  1273.       else  /* Add to group */
  1274.       {
  1275.         if (node=(struct Node *)AllocPooled(memPool,sizeof(struct Node)))
  1276.         {
  1277.           if (node->ln_Name=(char *)AllocPooled(memPool,strlen(buffer)+1))
  1278.           {
  1279.             strcpy(node->ln_Name,buffer);
  1280.             AddTail(&groupnode->enabled,node);
  1281.           }
  1282.           else
  1283.             FreePooled(memPool,node,sizeof(struct Node));
  1284.         }
  1285.       }
  1286.     }
  1287.     Close(file);
  1288.   }
  1289. }
  1290.  
  1291. void CreateGroup(struct List *grouplist, struct List *wbsplist, char *groupname, APTR memPool)
  1292. {
  1293.   struct GroupNode *groupnode;
  1294.   struct Node *node;
  1295.   struct WBSPNode *wbspnode;
  1296.  
  1297.   if (groupnode=(struct GroupNode *)AllocPooled(memPool,sizeof(struct GroupNode)))
  1298.   {
  1299.     if (groupnode->group_node.ln_Name=(char *)AllocPooled(memPool,strlen(groupname)+1))
  1300.     {
  1301.       strcpy(groupnode->group_node.ln_Name,groupname);
  1302.       NewList(&groupnode->enabled);
  1303.  
  1304.       for (wbspnode=(struct WBSPNode *)wbsplist->lh_Head ; wbspnode->wbsp_node.ln_Succ ; wbspnode = (struct WBSPNode *)wbspnode->wbsp_node.ln_Succ)
  1305.       {
  1306.         if (wbspnode->wbsp_node.ln_Type == EXECUTE)
  1307.         {
  1308.           if (node=(struct Node *)AllocPooled(memPool,sizeof(struct Node)))
  1309.           {
  1310.             if (node->ln_Name=(char *)AllocPooled(memPool,strlen(wbspnode->wbsp_node.ln_Name)+1))
  1311.             {
  1312.               strcpy(node->ln_Name,wbspnode->wbsp_node.ln_Name);
  1313.               AddTail(&groupnode->enabled,node);
  1314.             }
  1315.             else
  1316.               FreePooled(memPool,node,sizeof(struct Node));
  1317.           }
  1318.         }
  1319.       }
  1320.       AddTail(grouplist,groupnode);
  1321.     }
  1322.     else
  1323.       FreePooled(memPool,groupnode,sizeof(struct GroupNode));
  1324.   }
  1325. }
  1326.  
  1327. void SelectGroup(struct List *wbsplist, struct List *subgrouplist)
  1328. {
  1329.   struct WBSPNode *node;
  1330.  
  1331.   for (node = (struct WBSPNode *)wbsplist->lh_Head; node->wbsp_node.ln_Succ; node = (struct WBSPNode *)node->wbsp_node.ln_Succ)
  1332.     if (node->wbsp_node.ln_Type != TITLE)
  1333.       if (FindName(subgrouplist,node->wbsp_node.ln_Name))
  1334.         node->wbsp_node.ln_Type = EXECUTE;
  1335.       else
  1336.         node->wbsp_node.ln_Type = STORAGE;
  1337. }
  1338.  
  1339. void DeleteGroup(struct GroupNode *node, APTR memPool)
  1340. {
  1341.   struct Node *worknode;
  1342.   struct Node *nextnode;
  1343.  
  1344.   if (node)
  1345.   {
  1346.     Remove((struct Node *)node);
  1347.  
  1348.     FreePooled(memPool,node->group_node.ln_Name,strlen(node->group_node.ln_Name)+1);
  1349.  
  1350.     worknode=node->enabled.lh_Head;
  1351.     while (nextnode = worknode->ln_Succ)
  1352.     {
  1353.       FreePooled(memPool,worknode->ln_Name,strlen(worknode->ln_Name)+1);
  1354.       FreePooled(memPool,worknode,sizeof(struct Node));
  1355.       worknode=nextnode;
  1356.     }
  1357.  
  1358.     FreePooled(memPool,node,sizeof(struct GroupNode));
  1359.   }
  1360. }
  1361.  
  1362. BOOL ShowGroupsRequester(void)
  1363. {
  1364.   BOOL save=FALSE;
  1365.   struct EasyStruct myRequestStruct={
  1366.     sizeof (struct EasyStruct ),
  1367.      0,
  1368.     "WBStartup+Prefs",
  1369.     NULL,
  1370.     NULL};
  1371.  
  1372.   myRequestStruct.es_GadgetFormat=GetString(STRSaveNoGadget);
  1373.   myRequestStruct.es_TextFormat=GetString(STRAskSaveGroups);
  1374.  
  1375.   if (EasyRequestArgs(NULL,&myRequestStruct,NULL,NULL))
  1376.     save=TRUE;
  1377.  
  1378.   return(save);
  1379. }
  1380.  
  1381.  
  1382. BOOL CopyFile(char *source,char *dest)
  1383. {
  1384.   /* source and dest should include the path and filename */
  1385.   BPTR infile,outfile;
  1386.   STRPTR buf=NULL;
  1387.   long x;
  1388.   struct DiskObject *diskobj;
  1389.   BOOL success=TRUE;
  1390.   //const long bufsize=512;
  1391.   //long numbuf=200;
  1392.   const long bufsize=1;
  1393.   long numbuf=200*512;
  1394.  
  1395.   /* Allocate the buffer used to copy the file */
  1396.   while ((buf==NULL) && (numbuf>0))
  1397.     if (!(buf=(STRPTR)AllocVec(bufsize*numbuf,MEMF_PUBLIC)))
  1398. //      numbuf-=10;
  1399.       numbuf/=2;
  1400.  
  1401.   /* Copy File */
  1402.   if (buf)
  1403.   {
  1404.     if (infile=Open(source,MODE_OLDFILE))
  1405.     {
  1406.       if (outfile=Open(dest,MODE_NEWFILE))
  1407.       {
  1408.         SetVBuf(outfile,NULL,BUF_FULL,bufsize*numbuf);
  1409.         do {
  1410.           x=FRead(infile,buf,bufsize,numbuf);
  1411.           FWrite(outfile,buf,bufsize,x);
  1412.         } while(x);
  1413.  
  1414.         Close(infile);
  1415.       }
  1416.       else
  1417.         success=FALSE;
  1418.       Close(outfile);
  1419.     }
  1420.     FreeVec(buf);
  1421.   }
  1422.   else
  1423.     success=FALSE;
  1424.  
  1425.   /* Copy Icon */
  1426.   if (diskobj=GetDiskObject(source))
  1427.   {
  1428.     diskobj->do_CurrentX = diskobj->do_CurrentY = NO_ICON_POSITION;
  1429.     if (!PutDiskObject(dest,diskobj))
  1430.       success=FALSE;
  1431.     FreeDiskObject(diskobj);
  1432.   }
  1433.  
  1434.   return(success);
  1435. }
  1436.