/**
 * Scout - The Amiga System Monitor
 *
 *------------------------------------------------------------------
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * You must not use this source code to gain profit of any kind!
 *
 *------------------------------------------------------------------
 *
 * @author Andreas Gelhausen
 * @author Richard Körber <rkoerber@gmx.de>
 */



#include "system_headers.h"

#define KEYMAPRESNAME   "keymap.resource"

int  libcnt,devcnt,rescnt;

static APTR LibPool = NULL, DevPool = NULL, ResPool = NULL;

__asm __saveds LONG liblist_dspfunc(register __a2 char **array, register __a1 struct LibEntry *libentry, register __a0 struct Hook *hook)
{
   if (libentry) {
      *array++ = libentry->lib_address;
      *array++ = libentry->lib_name;
      *array++ = libentry->lib_pri;
      *array++ = libentry->lib_ver;
      *array++ = libentry->lib_ocnt;
      *array++ = libentry->lib_rcnt;
      *array++ = libentry->lib_type;
      *array   = NULL;
   } else {
      *array++ = ESC "bAddress";
      *array++ = ESC "bln_Name";
      *array++ = ESC "bln_Pri";
      *array++ = ESC "bVersion";
      *array++ = ESC "bOpenC";
      *array++ = ESC "bRPC";
      *array++ = ESC "bln_Type";
      *array   = NULL;
   }
   return(0);
}

struct Hook liblist_dsphook = {
 {NULL, NULL},
 (ULONG (* )())liblist_dspfunc,
 NULL, NULL
};

static struct FSEntry {
   struct FSEntry *fs_Next;
   char fs_FileSystem[16];
   char fs_DOSType[16];
   char fs_Version[16];
   char fs_Creator[64];
};

__asm __saveds LONG fsentry_dspfunc(register __a2 char **array, register __a1 struct FSEntry *fsentry, register __a0 struct Hook *hook)
{
   if (fsentry) {
      *array++ = fsentry->fs_FileSystem;
      *array++ = fsentry->fs_DOSType;
      *array++ = fsentry->fs_Version;
      *array++ = fsentry->fs_Creator;
      *array   = NULL;
   } else {
      *array++ = ESC "bFileSystem";
      *array++ = ESC "bfse_DosType";
      *array++ = ESC "bfse_Version";
      *array++ = ESC "bfse_Creator";
      *array   = NULL;
   }
   return(0);
}

struct Hook fsentry_dsphook = {
 {NULL, NULL},
 (ULONG (* )())fsentry_dspfunc,
 NULL, NULL
};

__asm __saveds LONG fsentry_cmpfunc(register __a1 struct FSEntry *fsentry1, register __a2 struct FSEntry *fsentry2)
{
    return strcmpi(fsentry1->fs_FileSystem, fsentry2->fs_FileSystem);
}

struct Hook fsentry_cmphook = {
 {NULL, NULL},
 (ULONG (* )())fsentry_cmpfunc,
 NULL, NULL
};

static struct NSDCmdEntry {
   struct NSCmdEntry *nce_Next;
   UWORD nce_Number;
   char nce_DecNumber[16];
   char nce_HexNumber[16];
   char nce_CmdName[64];
};

__asm __saveds LONG nsdcmdentry_dspfunc(register __a2 char **array, register __a1 struct NSDCmdEntry *nsdcmdentry, register __a0 struct Hook *hook)
{
   if (nsdcmdentry) {
      *array++ = nsdcmdentry->nce_DecNumber;
      *array++ = nsdcmdentry->nce_HexNumber;
      *array++ = nsdcmdentry->nce_CmdName;
      *array   = NULL;
   } else {
      *array++ = ESC "bNumber (dec)";
      *array++ = ESC "bNumber (hex)";
      *array++ = ESC "bName";
      *array   = NULL;
   }
   return(0);
}

struct Hook nsdcmdentry_dsphook = {
 {NULL, NULL},
 (ULONG (* )())nsdcmdentry_dspfunc,
 NULL, NULL
};

__asm __saveds LONG nsdcmdentry_cmpfunc(register __a1 struct NSDCmdEntry *nsdcmdentry1, register __a2 struct NSDCmdEntry *nsdcmdentry2)
{
    return nsdcmdentry1->nce_Number - nsdcmdentry2->nce_Number;
}

struct Hook nsdcmdentry_cmphook = {
 {NULL, NULL},
 (ULONG (* )())nsdcmdentry_cmpfunc,
 NULL, NULL
};

int TestResource (struct Library *lib) {
   char  *name;

   name = lib->lib_Node.ln_Name;

   if ((stricmp (name, FSRNAME)) && (stricmp (name, CARDRESNAME)) && \
       (stricmp (name, KEYMAPRESNAME))) {
      return (TRUE);
   } else {
      return (FALSE);
   }
}

LONG NSDQuery( UBYTE *dev,
               ULONG unit,
               struct NSDeviceQueryResult *nqr )
{
    LONG result = IOERR_OPENFAIL;
    struct MsgPort *mp;

    if (mp = CreateMsgPort()) {
        struct IOStdReq *io;

        if (io = CreateIORequest(mp, sizeof(struct IOStdReq) + 128)) {
            if (strcmp(AHINAME, dev) == 0) {
                ((struct AHIRequest *)io)->ahir_Version = 4;
            }

            if (OpenDevice(dev, unit, io, 0) == 0) {
                io->io_Command = NSCMD_DEVICEQUERY;
                io->io_Data = nqr;
                io->io_Length = sizeof(struct NSDeviceQueryResult);
                result = DoIO(io);

                CloseDevice(io);
            }

            DeleteIORequest(io);
        }

        DeleteMsgPort(mp);
    }

    return result;
}

UBYTE *NSDTypeToCmdName( ULONG nsdType,
                         UWORD cmd )
{
    UBYTE *result;

    switch (cmd) {
        case CMD_INVALID      : result = "CMD_INVALID"; break;
        case CMD_RESET        : result = "CMD_RESET";   break;
        case CMD_READ         : result = "CMD_READ";    break;
        case CMD_WRITE        : result = "CMD_WRITE";   break;
        case CMD_UPDATE       : result = "CMD_UPDATE";  break;
        case CMD_CLEAR        : result = "CMD_CLEAR";   break;
        case CMD_STOP         : result = "CMD_STOP";    break;
        case CMD_START        : result = "CMD_START";   break;
        case CMD_FLUSH        : result = "CMD_FLUSH";   break;
        case NSCMD_DEVICEQUERY: result = "NSCMD_DEVICEQUERY"; break;
        default               : result = "<unknown>";   break;
    }

    switch (nsdType) {
        case NSDEVTYPE_GAMEPORT:
            switch (cmd) {
                case GPD_READEVENT : result = "GPD_READEVENT";  break;
                case GPD_ASKCTYPE  : result = "GPD_ASKCTYPE";   break;
                case GPD_SETCTYPE  : result = "GPD_SETCTYPE";   break;
                case GPD_ASKTRIGGER: result = "GPD_ASKTRIGGER"; break;
                case GPD_SETTRIGGER: result = "GPD_SETTRIGGER"; break;
            }
            break;

        case NSDEVTYPE_TIMER:
            switch (cmd) {
                case TR_ADDREQUEST: result = "TR_ADDREQUEST"; break;
                case TR_GETSYSTIME: result = "TR_GETSYSTIME"; break;
                case TR_SETSYSTIME: result = "TR_SETSYSTIME"; break;
            }
            break;

        case NSDEVTYPE_KEYBOARD:
            switch (cmd) {
                case KBD_READEVENT       : result = "KBD_READEVENT";        break;
                case KBD_READMATRIX      : result = "KBD_READMATRIX";       break;
                case KBD_ADDRESETHANDLER : result = "KBD_ADDRESETHANDLER";  break;
                case KBD_REMRESETHANDLER : result = "KBD_REMRESETHANDLER";  break;
                case KBD_RESETHANDLERDONE: result = "KBD_RESETHANDLERDONE"; break;
            }
            break;

        case NSDEVTYPE_INPUT:
            switch (cmd) {
                case IND_ADDHANDLER: result = "IND_ADDHANDLER"; break;
                case IND_REMHANDLER: result = "IND_REMHANDLER"; break;
                case IND_WRITEEVENT: result = "IND_WRITEEVENT"; break;
                case IND_SETTHRESH : result = "IND_SETTHRESH";  break;
                case IND_SETPERIOD : result = "IND_SETPERIOD";  break;
                case IND_SETMPORT  : result = "IND_SETMPORT";   break;
                case IND_SETMTYPE  : result = "IND_SETMTYPE";   break;
                case IND_SETMTRIG  : result = "IND_SETMTRIG";   break;
            }
            break;

        case NSDEVTYPE_TRACKDISK:
            switch (cmd) {
                case TD_MOTOR          : result = "TD_MOTOR";           break;
                case TD_SEEK           : result = "TD_SEEK";            break;
                case TD_FORMAT         : result = "TD_FORMAT";          break;
                case TD_REMOVE         : result = "TD_REMOVE";          break;
                case TD_CHANGENUM      : result = "TD_CHANGENUM";       break;
                case TD_CHANGESTATE    : result = "TD_CHANGESTATE";     break;
                case TD_PROTSTATUS     : result = "TD_PROTSTATUS";      break;
                case TD_RAWREAD        : result = "TD_RAWREAD";         break;
                case TD_RAWWRITE       : result = "TD_RAWWRITE";        break;
                case TD_GETDRIVETYPE   : result = "TD_GETDRIVETYPE";    break;
                case TD_GETNUMTRACKS   : result = "TD_GETNUMTRACKS";    break;
                case TD_ADDCHANGEINT   : result = "TD_ADDCHANGEINT";    break;
                case TD_REMCHANGEINT   : result = "TD_REMCHANGEINT";    break;
                case TD_GETGEOMETRY    : result = "TD_GETGEOMETRY";     break;
                case TD_EJECT          : result = "TD_EJECT";           break;
                case HD_SCSICMD        : result = "HD_SCSICMD";         break;
                case ETD_WRITE         : result = "ETD_WRITE";          break;
                case ETD_READ          : result = "ETD_READ";           break;
                case ETD_MOTOR         : result = "ETD_MOTOR";          break;
                case ETD_SEEK          : result = "ETD_SEEK";           break;
                case ETD_FORMAT        : result = "ETD_FORMAT";         break;
                case ETD_UPDATE        : result = "ETD_UPDATE";         break;
                case ETD_CLEAR         : result = "ETD_CLEAR";          break;
                case ETD_RAWREAD       : result = "ETD_RAWREAD";        break;
                case ETD_RAWWRITE      : result = "ETD_RAWWRITE";       break;
                case NSCMD_TD_READ64   : result = "NSCMD_TD_READ64";    break;
                case NSCMD_TD_WRITE64  : result = "NSCMD_TD_WRITE64";   break;
                case NSCMD_TD_SEEK64   : result = "NSCMD_TD_SEEK64";    break;
                case NSCMD_TD_FORMAT64 : result = "NSCMD_TD_FORMAT64";  break;
                case NSCMD_ETD_READ64  : result = "NSCMD_ETD_READ64";   break;
                case NSCMD_ETD_WRITE64 : result = "NSCMD_ETD_WRITE64";  break;
                case NSCMD_ETD_SEEK64  : result = "NSCMD_ETD_SEEK64";   break;
                case NSCMD_ETD_FORMAT64: result = "NSCMD_ETD_FORMAT64"; break;
                case CD_INFO           : result = "CD_INFO";            break;
                case CD_CONFIG         : result = "CD_CONFIG";          break;
                case CD_TOCMSF         : result = "CD_TOCMSF";          break;
                case CD_TOCLSN         : result = "CD_TOCLSN";          break;
                case CD_READXL         : result = "CD_READXL";          break;
                case CD_PLAYTRACK      : result = "CD_PLAYTRACK";       break;
                case CD_PLAYMSF        : result = "CD_PLAYMSF";         break;
                case CD_PLAYLSN        : result = "CD_PLAYLSN";         break;
                case CD_PAUSE          : result = "CD_PAUSE";           break;
                case CD_SEARCH         : result = "CD_SEARCH";          break;
                case CD_QCODEMSF       : result = "CD_QCODEMSF";        break;
                case CD_QCODELSN       : result = "CD_QCODELSN";        break;
                case CD_ATTENUATE      : result = "CD_ATTENUATE";       break;
                case CD_ADDFRAMEINT    : result = "CD_ADDFRAMEINT";     break;
                case CD_REMFRAMEINT    : result = "CD_REMFRAMEINT";     break;
            }
            break;

        case NSDEVTYPE_CONSOLE:
            switch (cmd) {
                case CD_ASKKEYMAP       : result = "CD_ASKKEYMAP";        break;
                case CD_SETKEYMAP       : result = "CD_SETKEYMAP";        break;
                case CD_ASKDEFAULTKEYMAP: result = "CD_ASKDEFAULTKEYMAP"; break;
                case CD_SETDEFAULTKEYMAP: result = "CD_SETDEFAULTKEYMAP"; break;
            }
            break;

        case NSDEVTYPE_SANA2:
            switch (cmd) {
                case S2_DEVICEQUERY          : result = "S2_DEVICEQUERY";           break;
                case S2_GETSTATIONADDRESS    : result = "S2_GETSTATIONADDRESS";     break;
                case S2_CONFIGINTERFACE      : result = "S2_CONFIGINTERFACE";       break;
                case S2_ADDMULTICASTADDRESS  : result = "S2_ADDMULTICASTADDRESS";   break;
                case S2_DELMULTICASTADDRESS  : result = "S2_DELMULTICASTADDRESS";   break;
                case S2_MULTICAST            : result = "S2_MULTICAST";             break;
                case S2_BROADCAST            : result = "S2_BROADCAST";             break;
                case S2_TRACKTYPE            : result = "S2_TRACKTYPE";             break;
                case S2_UNTRACKTYPE          : result = "S2_UNTRACKTYPE";           break;
                case S2_GETTYPESTATS         : result = "S2_GETTYPESTATS";          break;
                case S2_GETSPECIALSTATS      : result = "S2_GETSPECIALSTATS";       break;
                case S2_GETGLOBALSTATS       : result = "S2_GETGLOBALSTATS";        break;
                case S2_ONEVENT              : result = "S2_ONEVENT";               break;
                case S2_READORPHAN           : result = "S2_READORPHAN";            break;
                case S2_ONLINE               : result = "S2_ONLINE";                break;
                case S2_OFFLINE              : result = "S2_OFFLINE";               break;
                case 0xc000                  : result = "S2_ADDMULTICASTADDRESSES"; break;
                case 0xc001                  : result = "S2_DELMULTICASTADDRESSES"; break;
            }
            break;

        case NSDEVTYPE_AUDIO:
            switch (cmd) {
                case ADCMD_FREE     : result = "ADCMD_FREE";      break;
                case ADCMD_SETPREC  : result = "ADCMD_SETPREC";   break;
                case ADCMD_FINISH   : result = "ADCMD_FINISH";    break;
                case ADCMD_PERVOL   : result = "ADCMD_PERVOL";    break;
                case ADCMD_LOCK     : result = "ADCMD_LOCK";      break;
                case ADCMD_WAITCYCLE: result = "ADCMD_WAITCYCLE"; break;
                case ADCMD_ALLOCATE : result = "ADCMD_ALLOCATE";  break;
            }
            break;

        case NSDEVTYPE_CLIPBOARD:
            switch (cmd) {
                case CBD_POST          : result = "CBD_POST";           break;
                case CBD_CURRENTREADID : result = "CBD_CURRENTREADID";  break;
                case CBD_CURRENTWRITEID: result = "CBD_CURRENTWRITEID"; break;
                case CBD_CHANGEHOOK    : result = "CBD_CHANGEHOOK";     break;
            }
            break;

        case NSDEVTYPE_PRINTER:
            switch (cmd) {
                case PRD_RAWWRITE     : result = "PRD_RAWWRITE";      break;
                case PRD_PRTCOMMAND   : result = "PRD_PRTCOMMAND";    break;
                case PRD_DUMPRPORT    : result = "PRD_DUMPRPORT";     break;
                case PRD_QUERY        : result = "PRD_QUERY";         break;
                case PRD_RESETPREFS   : result = "PRD_RESETPREFS";    break;
                case PRD_LOADPREFS    : result = "PRD_LOADPREFS";     break;
                case PRD_USEPREFS     : result = "PRD_USEPREFS";      break;
                case PRD_SAVEPREFS    : result = "PRD_SAVEPREFS";     break;
                case PRD_READPREFS    : result = "PRD_READPREFS";     break;
                case PRD_WRITEPREFS   : result = "PRD_WRITEPREFS";    break;
                case PRD_EDITPREFS    : result = "PRD_EDITPREFS";     break;
                case PRD_SETERRHOOK   : result = "PRD_SETERRHOOK";    break;
                case PRD_DUMPRPORTTAGS: result = "PRD_DUMPRPORTTAGS"; break;
            }
            break;

        case NSDEVTYPE_SERIAL:
            switch (cmd) {
                case SDCMD_QUERY    : result = "SDCMD_QUERY";         break;
                case SDCMD_BREAK    : result = "SDCMD_BREAK";         break;
                case SDCMD_SETPARAMS: result = "SDCMD_SETPARAMS";     break;
                case CMD_NONSTD + 7 : result = "SIOCMD_SETCTRLLINES"; break;
            }
            break;

        case NSDEVTYPE_PARALLEL:
            switch (cmd) {
                case PDCMD_QUERY    : result = "PDCMD_QUERY";     break;
                case PDCMD_SETPARAMS: result = "PDCMD_SETPARAMS"; break;
            }
            break;
    }

    return result;
}

static struct FctEntry {
   struct FctEntry *fe_next;
   char fe_address[16];
   char fe_offsetdec[8];
   char fe_offsethex[8];
//*UHEX*   char fe_offsetuns[8];
   char fe_name[52];
};

__asm __saveds LONG lfctlist_dspfunc(register __a2 char **array, register __a1 struct FctEntry *entry, register __a0 struct Hook *hook)
{
   if (entry) {
      *array++ = entry->fe_offsetdec;
      *array++ = entry->fe_offsethex;
//*UHEX*      *array++ = entry->fe_offsetuns;
      *array++ = entry->fe_address;
      *array   = entry->fe_name;
   } else {
      *array++ = ESC "bOffset";
      *array++ = ESC "bHex";
//*UHEX*      *array++ = ESC "bU-Hex";
      *array++ = ESC "bAddress";
      *array   = ESC "bName";
   }
   return(0);
}

struct Hook lfctlist_dsphook = {
 {NULL, NULL},
 (ULONG (* )())lfctlist_dspfunc,
 NULL, NULL
};

void GetLDRFctList (struct Library *lib, char mode) {
   struct   WinFree  *ptr;
   unsigned char     *title = "FUNCTIONS: ";
   APTR     lfctlist;
   ULONG    offset, max;
   struct   FctEntry *entry;
   APTR     fctadr;
   BOOL     getfct = (IdentifyBase!=NULL);
   STRPTR   name;
   APTR     pool = NULL;

   switch (mode) {
      case 'L': pool = LibPool; break;
      case 'D': pool = DevPool; break;
      case 'R': pool = ResPool; break;
   }

   if (ptr = AllocWinFree()) {
      ptr->wf_Window = (APTR) WindowObject,
      MUIA_HelpNode, "Functions",
      MUIA_Window_ID, MakeDetailID('.','L','F','T'),
      WindowContents, VGroup,
         Child, lfctlist = ListviewObject,
            MUIA_Listview_Input, FALSE,
            MUIA_Listview_List, ListObject,
               ReadListFrame,
               MUIA_List_Title, TRUE,
               MUIA_List_Format, "DELTA=8 P=\33r, DELTA=8 P=\33r, DELTA=8,",
//*UHEX*               MUIA_List_Format, "DELTA=8 P=\33r, P=\33r, DELTA=8 P=\33r, DELTA=8,",
               MUIA_List_DisplayHook, &lfctlist_dsphook,
            End,
            MUIA_CycleChain, TRUE,
         End,
      End, End;

      if (ptr->wf_Window) {
         ptr->wf_ActiveObject = lfctlist;

         name = lib->lib_Node.ln_Name;

         if( mode!='R' || (
               stricmp(name, FSRNAME)
            && stricmp(name, CARDRESNAME)
            && stricmp(name, KEYMAPRESNAME))) {

            if(!stricmp(name, CIAANAME) || !stricmp(name, CIABNAME))
              name = "cia.resource";

            max = lib->lib_NegSize;

            set(lfctlist,MUIA_List_Quiet,TRUE);

            for(offset=6; offset <= max; offset+=6) {
              if(entry = tbAllocPooled(pool, sizeof(struct FctEntry))) {

                 if(*(WORD *)(((UBYTE*)lib) - offset) == 0x4ef9) {
                    fctadr = (APTR) *(LONG *)(((UBYTE *)lib) - offset + 2);
                    if (points2ram(fctadr)) {
                       _sprintf (entry->fe_address, HELL "$%08lx" DUNKEL, fctadr);
                    } else {
                       _sprintf (entry->fe_address, "$%08lx", fctadr);
                    }
                 } else {
                    strcpy(entry->fe_address, "<no jmp>");
                 }

                 _sprintf (entry->fe_offsetdec, "-%ld"  , offset);
                 _sprintf (entry->fe_offsethex, "-%04lx" , offset);
//*UHEX*                 _sprintf (entry->fe_offsetuns, "%04X" , 0x10000-offset);

                 if(offset<42 && (mode=='D' || (mode=='L' && offset<30))) {

                   STRPTR help;
                   switch(offset) {
                      case  6: help = "Open"   ; break;
                      case 12: help = "Close"  ; break;
                      case 18: help = "Expunge"; break;
                      case 24: help = "Null"   ; break;
                      case 30: help = "AbortIO"; break;
                      case 36: help = "BeginIO"; break;
                      default: help = ""; break;
                   }
                   strcpy(entry->fe_name,help);

                 } else if(getfct) {
                    switch(IdFunctionTags(name,offset,IDTAG_FuncNameStr,entry->fe_name,TAG_DONE)) {
                      case IDERR_NOFD:
                      case IDERR_NOMEM:
                         getfct = FALSE;
                         break;

                      case IDERR_OFFSET:
                         strcpy(entry->fe_name,"---");
                         break;
                    }
                 }

                 InsertBottomEntry (lfctlist, (APTR *) &entry);

              }
            }
            set(lfctlist,MUIA_List_Quiet,FALSE);
         }

         HandleWindowOpen (ptr, title, lib->lib_Node.ln_Name);
         HandleWindowClose (ptr);
      }
   }
}


void GetLDRMore (struct Library *lib, char *title, char *helpnode) {
   unsigned char           rpct[4];
   struct   WinFree        *ptr;
   int      rpc, i;

   APTR LibMainGroup;
   APTR libmoretext0,libmoretext1,libmoretext2a,libmoretext2b,libmoretext3,libmoretext4;
   APTR LibMoreAdd1,LibMoreGroup1,LibMoreAdd2,LibMoreGroup2;
   APTR FSList, DevMoreAdd1, DevMoreAdd2, DevMoreAdd3, DevMoreText1, NSDCmdList;

   UBYTE drflags[]   = {DRF_ALLOC0,DRF_ALLOC1,DRF_ALLOC2,DRF_ALLOC3,DRF_ACTIVE,0};

   char  *drflagstext[] = {"ALLOC0","ALLOC1","ALLOC2",
                           "ALLOC3","ACTIVE"};

   TestResource (lib);

   if (ptr = AllocWinFree()) {
      if (! stricmp (lib->lib_Node.ln_Name, FSRNAME)) {

         ptr->wf_Window = (APTR) WindowObject,

         MUIA_HelpNode, helpnode,
         MUIA_Window_ID, MakeDetailID('.','F','S','Y'),
         WindowContents, VGroup,
            Child, HGroup,
               Child, VGroup, MUIA_Group_SameWidth, TRUE,
                  Child, MyLabel2 ("Name:"),
                  Child, MyLabel2 ("Address:\nPri:"),
                  Child, MyLabel2 ("fsr_Creator:"),
               End,
               Child, VGroup,
                  Child, MyTextObject3 (FSRNAME),
                  Child, HGroup,
                     Child, libmoretext1 = MyTextObject(),
                     Child, MyLabel ("Type:"),
                     Child, libmoretext2b = MyTextObject(),
                  End,
                  Child, libmoretext3 = MyTextObject(),
               End,
            End,
            Child, HGroup,
               Child, MyHSpace(0),
               Child, MyLabel2 ("fsr_FileSysEntries:"),
               Child, MyHSpace(0),
            End,
            Child, FSList = ListviewObject,
               MUIA_Listview_Input, FALSE,
               MUIA_Listview_List, ListObject,
                  ReadListFrame,
                  MUIA_List_Title, TRUE,
                  MUIA_List_Format, "DELTA=8 P=\33c, DELTA=8, DELTA=8 P=\33c, DELTA=8",
                  MUIA_List_DisplayHook, &fsentry_dsphook,
                  MUIA_List_CompareHook, &fsentry_cmphook,
               End,
               MUIA_CycleChain, TRUE,
            End,
         End, End;

         if (ptr->wf_Window) {
            struct FileSysResource *fsr;
            struct FileSysEntry *fse;
            struct FSEntry *entry;

            MySetContents (libmoretext1, ESC "c$%08lx\n%ld", lib, lib->lib_Node.ln_Pri);
            MySetContents (libmoretext2b, ESC "c %s ", GetNodeType (lib->lib_Node.ln_Type));

            strcpy (tmpstr, ((struct FileSysResource *) lib)->fsr_Creator);
            healstring (tmpstr);
            set (libmoretext3, MUIA_Text_Contents, tmpstr);

            HandleWindowOpen (ptr, title, FSRNAME);
            HandleWindowClose (ptr);

            set(FSList,MUIA_List_Quiet, TRUE);

            fsr = (struct FileSysResource *)lib;
            for (fse = (struct FileSysEntry *)fsr->fsr_FileSysEntries.lh_Head; fse->fse_Node.ln_Succ; fse = (struct FileSysEntry *)fse->fse_Node.ln_Succ) {
               if (entry = tbAllocPooled(LibPool, sizeof(struct FSEntry))) {
                  strcpy(entry->fs_FileSystem, GetDiskType((LONG *)&fse->fse_DosType));
                  _sprintf(entry->fs_DOSType, "$%08lx", fse->fse_DosType);
                  _sprintf(entry->fs_Version, "%ld.%ld", fse->fse_Version >> 16, fse->fse_Version & 0xffff);
                  strncpy(entry->fs_Creator, nonetest(fse->fse_Node.ln_Name), 63);
                  healstring(entry->fs_Creator);
                  InsertSortedEntry (FSList, (APTR *) &entry);
               }
            }

            set(FSList,MUIA_List_Quiet, FALSE);
            set(ptr->wf_Window, MUIA_Window_ActiveObject, FSList);
         }
      } else if ((! stricmp (lib->lib_Node.ln_Name, CARDRESNAME)) || \
                 (! stricmp (lib->lib_Node.ln_Name, KEYMAPRESNAME))) {
         ptr->wf_Window = (APTR) WindowObject,

         MUIA_HelpNode, helpnode,
         MUIA_Window_ID, MakeDetailID('.','L','I','B'),
         WindowContents, HGroup,
            Child, VGroup, MUIA_Group_SameWidth, TRUE,
               Child, MyLabel2 ("Name:"),
               Child, MyLabel2 ("Address:\nPri:"),
            End,
            Child, VGroup,
               Child, MyTextObject3 (lib->lib_Node.ln_Name),
               Child, HGroup,
                  Child, libmoretext1 = MyTextObject(),
                  Child, MyLabel ("Type:"),
                  Child, libmoretext2b = MyTextObject(), 
               End,
            End,
         End, End;

         if (ptr->wf_Window) {
            MySetContents (libmoretext1, ESC "c$%08lx\n%ld", lib, lib->lib_Node.ln_Pri);
            MySetContents (libmoretext2b, ESC "c %s ", GetNodeType (lib->lib_Node.ln_Type));

            HandleWindowOpen (ptr, title, lib->lib_Node.ln_Name);
            HandleWindowClose (ptr);
         }
      } else {
         ptr->wf_Window = (APTR) WindowObject,

         MUIA_HelpNode, helpnode,
         MUIA_Window_ID, MakeDetailID('.','L','I','B'),
         WindowContents, LibMainGroup = VGroup,
            Child, HGroup,
               Child, LibMoreGroup1 = VGroup, MUIA_Group_SameWidth, TRUE,
                  Child, MyLabel2 ("Name:"),
                  Child, MyVSpace(0),
                  Child, MyLabel2 ("Address:\nPri:\nType:\nVersion:\nOpenCnt:"),
                  Child, MyVSpace(0),
                  Child, MyLabel2 ("IdString:"),
               End,
               Child, LibMoreGroup2 = VGroup,
                  Child, libmoretext0 = MyTextObject(),
                  Child, HGroup,
                     Child, libmoretext1 = MyTextObject(),
                     Child, VGroup,
                        Child, MyLabel ("Flags:"),
                        Child, MyLabel ("NegSize:\nPosSize:\nSum:\nRamPtrCnt:"),
                     End,
                     Child, VGroup,
                        Child, libmoretext2a = KeyButtonF ('b', lib->lib_Flags),
                        Child, libmoretext2b = MyTextObject(),
                     End,
                  End,
                  Child, libmoretext3 = MyTextObject(),
               End,
            End,
         End, End;

         if (ptr->wf_Window) {
            if ((rpc = GetRamPointerCount (lib)) == (lib->lib_NegSize / 6)) {
               strcpy (rpct, "***");
            } else {
               _sprintf (rpct, "%ld", rpc);
            }
            MySetContents (libmoretext1, ESC "c$%08lx\n%ld\n%s\n%ld.%ld\n%ld", lib, lib->lib_Node.ln_Pri, GetNodeType (lib->lib_Node.ln_Type), lib->lib_Version, lib->lib_Revision, lib->lib_OpenCnt);
            MySetContents (libmoretext2b, ESC "c%ld\n%ld\n$%08lx\n%s", lib->lib_NegSize, lib->lib_PosSize, lib->lib_Sum, rpct);

            if (! stricmp (lib->lib_Node.ln_Name, DISKNAME)) {
               Child, LibMoreAdd1 = VGroup, MUIA_Group_SameWidth, TRUE,
                  Child, MyLabel2 ("dr_Current:"),
                  Child, MyLabel2 ("dr_CurrTask:"),
               End;

               Child, LibMoreAdd2 = VGroup,
                  Child, libmoretext4 = MyTextObject(),
                  Child, MyTextObject3 (GetTaskName (((struct DiscResource *) lib)->dr_CurrTask)),
               End;

               tmpstr[0] = '\0';
               i = 0;
               while (drflags[i]) {
                  if (((struct DiscResource *) lib)->dr_Flags & drflags[i]) {
                     if (strlen (tmpstr))
                        strcat (tmpstr, ", ");
                     strcat (tmpstr, drflagstext[i]);
                  }
                  i++;
               }
               set (libmoretext4, MUIA_Text_Contents, nonetest (tmpstr));
               DoMethod (LibMoreGroup1,OM_ADDMEMBER,LibMoreAdd1);
               DoMethod (LibMoreGroup2,OM_ADDMEMBER,LibMoreAdd2);
            }

            if (strstr(lib->lib_Node.ln_Name, ".device") != NULL) {
               ULONG unit;
               UBYTE nsdType[64];

               Child, DevMoreAdd1 = VGroup, MUIA_Group_SameWidth, TRUE,
                  Child, MyLabel2 ("NSDType:"),
               End;

               Child, DevMoreAdd2 = VGroup,
                  Child, DevMoreText1 = MyTextObject(),
               End;

               Child, DevMoreAdd3 = VGroup,
                  Child, HGroup,
                     Child, MyHSpace(0),
                     Child, MyLabel2 ("Supported commands:"),
                     Child, MyHSpace(0),
                  End,
                  Child, NSDCmdList = ListviewObject,
                     MUIA_Listview_Input, FALSE,
                     MUIA_Listview_List, ListObject,
                        ReadListFrame,
                        MUIA_List_Title, TRUE,
                        MUIA_List_Format, "DELTA=8 P=\33c, DELTA=8 P=\33c, DELTA=8",
                        MUIA_List_DisplayHook, &nsdcmdentry_dsphook,
                        MUIA_List_CompareHook, &nsdcmdentry_cmphook,
                     End,
                     MUIA_CycleChain, TRUE,
                  End,
               End;

               strcpy(nsdType, "unknown (device could not be openend)");

               for (unit = 0; unit < 16; unit++) {
                  struct NSDeviceQueryResult nqr;
                  LONG ioErr;

                  if ((ioErr = NSDQuery(lib->lib_Node.ln_Name, unit, &nqr)) == 0) {
                     UWORD *cmds;
                     struct NSDCmdEntry *entry;

                     set(NSDCmdList, MUIA_List_Quiet, TRUE);

                     cmds = nqr.SupportedCommands;
                     while (*cmds) {
                        if (entry = tbAllocPooled(LibPool, sizeof(struct NSDCmdEntry))) {
                           entry->nce_Number = *cmds;
                           _sprintf(entry->nce_DecNumber, "%ld", *cmds);
                           _sprintf(entry->nce_HexNumber, "$%04lx", *cmds);
                           strcpy(entry->nce_CmdName, NSDTypeToCmdName(nqr.DeviceType, *cmds));
                           InsertSortedEntry (NSDCmdList, (APTR *) &entry);
                        }
                        cmds++;
                     }

                     set(NSDCmdList, MUIA_List_Quiet, FALSE);

                     switch (nqr.DeviceType) {
                        case NSDEVTYPE_GAMEPORT:  strcpy(nsdType, "gameport");  break;
                        case NSDEVTYPE_TIMER:     strcpy(nsdType, "timer");     break;
                        case NSDEVTYPE_KEYBOARD:  strcpy(nsdType, "keyboard");  break;
                        case NSDEVTYPE_INPUT:     strcpy(nsdType, "input");     break;
                        case NSDEVTYPE_TRACKDISK: strcpy(nsdType, "trackdisk"); break;
                        case NSDEVTYPE_CONSOLE:   strcpy(nsdType, "console");   break;
                        case NSDEVTYPE_SANA2:     strcpy(nsdType, "sana2");     break;
                        case NSDEVTYPE_AUDIO:     strcpy(nsdType, "audio");     break;
                        case NSDEVTYPE_CLIPBOARD: strcpy(nsdType, "clipboard"); break;
                        case NSDEVTYPE_PRINTER:   strcpy(nsdType, "printer");   break;
                        case NSDEVTYPE_SERIAL:    strcpy(nsdType, "serial");    break;
                        case NSDEVTYPE_PARALLEL:  strcpy(nsdType, "parallel");  break;
                        default: strcpy(nsdType, "unknown"); break;
                     }

                     _sprintf(tmpstr2, " (subtype %ld)", nqr.DeviceSubType);
                     strcat(nsdType, tmpstr2);
                     break;
                  } else {
                     switch (ioErr) {
                        default:
                        case IOERR_OPENFAIL: strcpy(nsdType, "unknown (device could not be openend)"); break;
                        case IOERR_NOCMD: strcpy(nsdType, "unknown (device does not support NSD)"); break;
                     }

                     if (ioErr == IOERR_NOCMD) break;
                  }
               }

               set(DevMoreText1, MUIA_Text_Contents, nsdType);
               set(ptr->wf_Window, MUIA_Window_ActiveObject, NSDCmdList);

               DoMethod(LibMoreGroup1, OM_ADDMEMBER, DevMoreAdd1);
               DoMethod(LibMoreGroup2, OM_ADDMEMBER, DevMoreAdd2);
               DoMethod(LibMainGroup, OM_ADDMEMBER, DevMoreAdd3);
            }

            HandleFlagsButtonPressed (libmoretext2a, ptr, "(LIBRARY)", "lib_Flags", lib->lib_Flags, (struct LongFlag *) &lib_flags, NULL, 'b');
            HandleWindowOpen (ptr, title, lib->lib_Node.ln_Name);
            MySetContentsHealed (libmoretext0, "%s", lib->lib_Node.ln_Name);
            MySetContentsHealed (libmoretext3, "%s", nonetest (lib->lib_IdString));
            HandleWindowClose (ptr);
         }
      }
   }
}

void GetLibMore (struct Library *lib) {
   char *title = "LIBRARY: ";

   GetLDRMore (lib, title, LibrariesText);
}

void GetDevMore (struct Library *lib) {
   char *title = "DEVICE: ";

   GetLDRMore (lib, title, DevicesText);
}

void GetResMore (struct Library *lib) {
   char *title = "RESOURCE: ";

   GetLDRMore (lib, title, ResourcesText);
}

void PrintLDR (APTR list, char type, char *filename) {
   int   i;
   BPTR  handle;
   struct LibEntry *entryp = NULL;

   handle = HandlePrintStart (filename);
   if ((handle) && (PrintOneLine (handle, "\n  Address   Pri OpenC RPC Name & Version\n\n"))) {
      if ((type == 'L') && (! WI_Libraries)) {
         FillLDRList ('L', &entryp);
      } else if ((type == 'D') && (! WI_Devices)) {
         FillLDRList ('D', &entryp);
      } else if ((type == 'R') && (! WI_Resources)) {
         FillLDRList ('R', &entryp);
      }
//      if (i) {
         for (i=0;;i++) {

            if (((type == 'L') && (WI_Libraries)) \
               || ((type == 'D') && (WI_Devices)) \
               || ((type == 'R') && (WI_Resources))) {
               DoMethod (list,MUIM_List_GetEntry,i,&entryp);
            }
            if (!entryp) break;

            _sprintf (tmpstr2, " %s %4s %4s %3s %s %ld.%ld\n", entryp->lib_address, entryp->lib_pri, entryp->lib_ocnt, entryp->lib_rcnt, entryp->lib_name, ((struct Library *) entryp->lib_ptr)->lib_Version, ((struct Library *) entryp->lib_ptr)->lib_Revision);
            if (! (PrintOneLine (handle, tmpstr2)))
               break;

            if (((type == 'L') && (! WI_Libraries)) \
               || ((type == 'D') && (! WI_Devices)) \
               || ((type == 'R') && (! WI_Resources))) {
               entryp = entryp->lib_next;
            }
         }
//      }
   }
   HandlePrintStop();
}

void PrintLibraries (char *filename) {
   PrintLDR (liblist,'L',filename);
}

void PrintDevices (char *filename) {
   PrintLDR (devlist,'D',filename);
}

void PrintResources (char *filename) {
   PrintLDR (reslist,'R',filename);
}

int FillLDRList (char kind, struct LibEntry **first) {
   struct   Library  *lib = NULL;
   APTR     pool = NULL;
   char     *cmd = NULL;

   struct   LibEntry   *libentry,*previous = NULL;
   int      tmp, teststatus;

   int libcnt = 0;
   *first = 0;

   if (kind == 'L') {
      lib = FIRSTLIBRARY;
      FreeLibraries();
      pool = LibPool = tbCreatePool(MEMF_CLEAR, 4096, 4096);
      cmd = "GetLibList";
   } else if (kind == 'D') {
      lib = FIRSTDEVICE;
      FreeDevices();
      pool = DevPool = tbCreatePool(MEMF_CLEAR, 4096, 4096);
      cmd = "GetDevList";
   } else if (kind == 'R') {
      lib = FIRSTRESOURCE;
      FreeResources();
      pool = ResPool = tbCreatePool(MEMF_CLEAR, 4096, 4096);
      cmd = "GetResList";
   }

   if (clientstate) {
      if (SendDaemon (cmd)) {
         while ((libentry = tbAllocPooled(pool, sizeof(struct LibEntry))) \
           && (ReceiveDecodedEntry ((UBYTE *) libentry, sizeof (struct LibEntry)))) {
            IsHex (libentry->lib_address, (long *) &libentry->lib_ptr);

            if (! *first)
               *first = libentry;
            if (previous)
               previous->lib_next = libentry;

            libcnt++;
            previous = libentry;
         }
      }
   } else {
      while ((lib->lib_Node.ln_Succ != 0) && (libentry = tbAllocPooled(pool, sizeof(struct LibEntry)))) {
         if (! *first)
            *first = libentry;
         if (previous)
            previous->lib_next = libentry;
   
         libentry->lib_ptr = (char *) lib;
         _sprintf (libentry->lib_address, "$%08lx",lib);
         strncpy (libentry->lib_name, lib->lib_Node.ln_Name, 30);
         _sprintf (libentry->lib_pri, "%4ld ", lib->lib_Node.ln_Pri);
         if (strcmp(libentry->lib_name, FSRNAME) == 0 || strcmp(libentry->lib_name, KEYMAPRESNAME) == 0) {
             strcpy(libentry->lib_ver, "---");
         } else {
             _sprintf (libentry->lib_ver, "%ld.%ld ", lib->lib_Version, lib->lib_Revision);
         }
   
         teststatus = TestResource (lib);
   
         if (teststatus) {
            _sprintf (libentry->lib_ocnt, "%3ld ", lib->lib_OpenCnt);
            if ((tmp = GetRamPointerCount(lib)) == (lib->lib_NegSize / 6)) {
               strcpy (libentry->lib_rcnt, "***");
            } else {
               _sprintf (libentry->lib_rcnt, "%3ld", tmp);
            }
         } else {
            strcpy (libentry->lib_ocnt, "--- ");
            strcpy (libentry->lib_rcnt, "---");
         }
         strcpy (libentry->lib_type, GetNodeType (lib->lib_Node.ln_Type));
   
         libcnt++;
         previous = libentry;
         lib = (struct Library *)lib->lib_Node.ln_Succ;
      }
   }
   return (libcnt);
}

void FreeLibraries (void)
{
    MyFreePoolStructs(&LibPool, libtext, NULL, liblist);
}

void FlushLibraries (void) {
   struct   Library  *lib,*next;

   lib = FIRSTLIBRARY;

   while (next = (struct Library *) lib->lib_Node.ln_Succ) {
      if (! lib->lib_OpenCnt)
         RemLibrary (lib);
      lib = next;
   }
}

void FreeDevices (void)
{
    MyFreePoolStructs(&DevPool, devtext, NULL, devlist);
}

void FlushDevices (void) {
   struct   Library  *lib,*next;

   lib = FIRSTDEVICE;

   while (next = (struct Library *) lib->lib_Node.ln_Succ) {
      if (! lib->lib_OpenCnt)
         RemDevice ((struct Device *) lib);
      lib = next;
   }
   
}

void FreeResources (void)
{
    MyFreePoolStructs(&ResPool, restext, NULL, reslist);
}

void ShowLibraries (void)
{
    struct LibEntry *lib;

    ApplicationSleep();
    set(liblist,MUIA_List_Quiet,TRUE);
    set(liblist,MUIA_List_CompareHook,liblist_cmphook_ptr);
    set(BT_LibRemove, MUIA_Disabled, TRUE);
    set(BT_LibClose, MUIA_Disabled, TRUE);
    set(BT_LibPriority, MUIA_Disabled, TRUE);
    set(BT_LibFunctions, MUIA_Disabled, TRUE);
    set(BT_LibMore, MUIA_Disabled, TRUE);

    libcnt = FillLDRList ('L', &lib);

    while (lib) {
        InsertSortedEntry (liblist, (APTR *) &lib);
        lib = lib->lib_next;
    }

    SetCountText (libcount, libcnt);
    AwakeApplication();
    set(liblist,MUIA_List_Quiet,FALSE);
}

void ShowDevices (void)
{
    struct LibEntry *lib;

    ApplicationSleep();
    set(devlist,MUIA_List_Quiet,TRUE);
    set(devlist,MUIA_List_CompareHook,devlist_cmphook_ptr);
    set(BT_DevRemove, MUIA_Disabled, TRUE);
    set(BT_DevPriority, MUIA_Disabled, TRUE);
    set(BT_DevFunctions, MUIA_Disabled, TRUE);
    set(BT_DevMore, MUIA_Disabled, TRUE);

    devcnt = FillLDRList ('D', &lib);

    while (lib) {
        InsertSortedEntry (devlist, (APTR *) &lib);
        lib = lib->lib_next;
    }

    SetCountText (devcount, devcnt);
    AwakeApplication();
    set(devlist,MUIA_List_Quiet,FALSE);
}

void ShowResources (void)
{
    struct LibEntry *lib;

    ApplicationSleep();
    set(reslist,MUIA_List_Quiet,TRUE);
    set(reslist,MUIA_List_CompareHook,reslist_cmphook_ptr);
    set(BT_ResRemove, MUIA_Disabled, TRUE);
    set(BT_ResPriority, MUIA_Disabled, TRUE);
    set(BT_ResFunctions, MUIA_Disabled, TRUE);
    set(BT_ResMore, MUIA_Disabled, TRUE);

    rescnt = FillLDRList ('R', &lib);

    while (lib) {
        InsertSortedEntry (reslist, (APTR *) &lib);
        lib = lib->lib_next;
    }

    SetCountText (rescount, rescnt);
    AwakeApplication();
    set(reslist,MUIA_List_Quiet,FALSE);
}

void SendLibList (void)
{
    struct LibEntry *lib;

    FillLDRList ('L', &lib);

    while (lib) {
        SendEncodedEntry ((UBYTE *) lib, sizeof (struct LibEntry));
        lib = lib->lib_next;
    }
    FreeLibraries ();
}

void SendDevList (void)
{
    struct LibEntry *lib;

    FillLDRList ('D', &lib);

    while (lib) {
        SendEncodedEntry ((UBYTE *) lib, sizeof (struct LibEntry));
        lib = lib->lib_next;
    }
    FreeDevices ();
}

void SendResList (void)
{
    struct LibEntry *lib;

    FillLDRList ('R', &lib);

    while (lib) {
        SendEncodedEntry ((UBYTE *) lib, sizeof (struct LibEntry));
        lib = lib->lib_next;
    }
    FreeResources ();
}

APTR LibSortList[] = {
   &list_cmpnormalhook,
   &list_cmpnamehook,
   &list_cmpaddresshook,
   NULL
};

static const char *CYA_LibSortText[] = {
   "priority",
   "name",
   "address",
   NULL
};

APTR WI_Libraries, liblist, libtext, libcount, CY_LibSort;
int  libsortstate = 0;
APTR BT_LibUpdate, BT_LibPrint, BT_LibPriority, BT_LibClose, BT_LibRemove, BT_LibFunctions, BT_LibMore, BT_LibExit;

char libraries_title[WINDOWTITLELEN];

void LibrariesWindow (BOOL state) {
   if (state) {
      if (WI_Libraries) {
         ShowLibraries();
      } else {
         WI_Libraries = WindowObject,
         MUIA_Window_Title, MyGetWindowTitle (libraries_title, "LIBRARIES"),
         MUIA_HelpNode, LibrariesText,
         MUIA_Window_ID, MakeListID('L','I','B','S'),
         WindowContents, VGroup,
            Child, liblist = MyListviewObject ("COL=0 DELTA=8,COL=1 DELTA=8,COL=2 DELTA=8 P=\33r,COL=3 DELTA=8 P=\33c,COL=4 DELTA=8 P=\33r,COL=5 DELTA=8 P=\33r,COL=6",&liblist_dsphook),
            Child, MyBelowSortedListview (&libtext, &libcount, &CY_LibSort, CYA_LibSortText, libsortstate),
            Child, MyVSpace(2),
            Child, HGroup, MUIA_Group_SameSize, TRUE,
               Child, BT_LibPriority  = KeyButtonA (PriorityText ,ID_LIBPRIORITY),
               Child, BT_LibClose     = KeyButtonA (CloseText    ,ID_LIBCLOSE),
               Child, BT_LibRemove    = KeyButtonA (RemoveText   ,ID_LIBREMOVE),
               Child, BT_LibFunctions = KeyButtonA (FunctionsText,ID_LIBFUNCTIONS),
            End,
            Child, HGroup, MUIA_Group_SameSize, TRUE,
               Child, BT_LibUpdate    = KeyButtonA (UpdateText  ,ID_LIBUPDATE),
               Child, BT_LibPrint     = KeyButtonA (PrintText   ,ID_LIBPRINT),
               Child, BT_LibMore      = KeyButtonA (MoreText    ,ID_LIBMORE),
               Child, BT_LibExit      = KeyButtonA (ExitText    ,ID_LIBEXIT),
            End,
         End, End;

         DoMethod (AP_Scout,OM_ADDMEMBER,WI_Libraries);
         DoMethod (WI_Libraries,MUIM_Window_SetCycleChain,liblist,CY_LibSort,BT_LibUpdate,BT_LibPrint,BT_LibPriority,BT_LibClose,BT_LibRemove,BT_LibFunctions,BT_LibMore,BT_LibExit,NULL);
         DoMethod (CY_LibSort, MUIM_Notify, MUIA_Cycle_Active, MUIV_EveryTime, AP_Scout, 2, MUIM_Application_ReturnID, ID_LIBSORT);

         SetCloseRequest (WI_Libraries,ID_LIBEXIT);
         SetListActive (liblist,ID_LIBLV_ACTIVE);
         SetListviewDoubleClick (liblist,ID_LIBMORE);

         ShowLibraries();

         SetWindowOpen (WI_Libraries,liblist,ID_LIBEXIT);
      }
   } else if ((! state) && (WI_Libraries)) {
      SetWindowClose (WI_Libraries,TRUE);

      FreeLibraries();

      DoMethod (AP_Scout,OM_REMMEMBER,WI_Libraries);
      MUI_DisposeObject (WI_Libraries);
      WI_Libraries = NULL;
      liblist = NULL;
   }
}

APTR WI_Devices, devlist, devtext, devcount, CY_DevSort;
int  devsortstate = 0;
APTR BT_DevUpdate, BT_DevPrint, BT_DevPriority, BT_DevRemove, BT_DevFunctions, BT_DevMore, BT_DevExit;

char devices_title[WINDOWTITLELEN];

void DevicesWindow (BOOL state) {
   if (state) {
      if (WI_Devices) {
         ShowDevices();
      } else {
         WI_Devices = WindowObject,
         MUIA_Window_Title, MyGetWindowTitle (devices_title, "DEVICES"),
         MUIA_HelpNode, DevicesText,
         MUIA_Window_ID, MakeListID('D','E','V','S'),
         WindowContents, VGroup,
            Child, devlist = MyListviewObject ("COL=0 DELTA=8,COL=1 DELTA=8,COL=2 DELTA=8 P=\33r,COL=3 DELTA=8 P=\33c,COL=4 DELTA=8 P=\33r,COL=5 DELTA=8 P=\33r,COL=6",&liblist_dsphook),
            Child, MyBelowSortedListview (&devtext, &devcount, &CY_DevSort, CYA_LibSortText, devsortstate),
            Child, MyVSpace(2),
            Child, HGroup, MUIA_Group_SameSize, TRUE,
               Child, BT_DevPriority  = KeyButtonA (PriorityText ,ID_DEVPRIORITY),
               Child, BT_DevRemove    = KeyButtonA (RemoveText   ,ID_DEVREMOVE),
               Child, BT_DevFunctions = KeyButtonA (FunctionsText,ID_DEVFUNCTIONS),
            End,
            Child, HGroup, MUIA_Group_SameSize, TRUE,
               Child, BT_DevUpdate    = KeyButtonA (UpdateText   ,ID_DEVUPDATE),
               Child, BT_DevPrint     = KeyButtonA (PrintText    ,ID_DEVPRINT),
               Child, BT_DevMore      = KeyButtonA (MoreText     ,ID_DEVMORE),
               Child, BT_DevExit      = KeyButtonA (ExitText     ,ID_DEVEXIT),
            End,
         End, End;

         DoMethod (AP_Scout,OM_ADDMEMBER,WI_Devices);
         DoMethod (WI_Devices,MUIM_Window_SetCycleChain,devlist,CY_DevSort,BT_DevUpdate,BT_DevPrint,BT_DevPriority,BT_DevRemove,BT_DevMore,BT_DevFunctions,BT_DevExit,NULL);
         DoMethod (CY_DevSort, MUIM_Notify, MUIA_Cycle_Active, MUIV_EveryTime, AP_Scout, 2, MUIM_Application_ReturnID, ID_DEVSORT);

         SetCloseRequest (WI_Devices,ID_DEVEXIT);
         SetListActive (devlist,ID_DEVLV_ACTIVE);
         SetListviewDoubleClick (devlist,ID_DEVMORE);

         ShowDevices();

         SetWindowOpen (WI_Devices,devlist,ID_DEVEXIT);
      }
   } else if ((! state) && (WI_Devices)) {
      SetWindowClose (WI_Devices,TRUE);

      FreeDevices();

      DoMethod (AP_Scout,OM_REMMEMBER,WI_Devices);
      MUI_DisposeObject (WI_Devices);
      WI_Devices = NULL;
      devlist = NULL;
   }
}

APTR WI_Resources, reslist, restext, rescount, CY_ResSort;
int  ressortstate = 0;
APTR BT_ResUpdate, BT_ResPrint, BT_ResPriority, BT_ResRemove, BT_ResFunctions, BT_ResMore, BT_ResExit;

char resources_title[WINDOWTITLELEN];

void ResourcesWindow (BOOL state) {
   if (state) {
      if (WI_Resources) {
         ShowResources();
      } else {
         WI_Resources = WindowObject,
         MUIA_Window_Title, MyGetWindowTitle (resources_title, "RESOURCES"),
         MUIA_HelpNode, ResourcesText,
         MUIA_Window_ID, MakeListID('R','E','S','O'),
         WindowContents, VGroup,
            Child, reslist = MyListviewObject ("COL=0 DELTA=8,COL=1 DELTA=8,COL=2 DELTA=8 P=\33r,COL=3 DELTA=8 P=\33c,COL=4 DELTA=8 P=\33r,COL=5 DELTA=8 P=\33r,COL=6",&liblist_dsphook),
            Child, MyBelowSortedListview (&restext, &rescount, &CY_ResSort, CYA_LibSortText, ressortstate),
            Child, MyVSpace(2),
            Child, HGroup, MUIA_Group_SameSize, TRUE,
               Child, BT_ResPriority  = KeyButtonA (PriorityText ,ID_RESPRIORITY),
               Child, BT_ResRemove    = KeyButtonA (RemoveText   ,ID_RESREMOVE),
               Child, BT_ResFunctions = KeyButtonA (FunctionsText,ID_RESFUNCTIONS),
            End,
            Child, HGroup, MUIA_Group_SameSize, TRUE,
               Child, BT_ResUpdate    = KeyButtonA (UpdateText   ,ID_RESUPDATE),
               Child, BT_ResPrint     = KeyButtonA (PrintText    ,ID_RESPRINT),
               Child, BT_ResMore      = KeyButtonA (MoreText     ,ID_RESMORE),
               Child, BT_ResExit      = KeyButtonA (ExitText     ,ID_RESEXIT),
            End,
         End, End;

         DoMethod (AP_Scout,OM_ADDMEMBER,WI_Resources);
         DoMethod (WI_Resources,MUIM_Window_SetCycleChain,reslist,CY_ResSort,BT_ResUpdate,BT_ResPrint,BT_ResPriority,BT_ResRemove,BT_ResFunctions,BT_ResMore,BT_ResExit,NULL);
         DoMethod (CY_ResSort, MUIM_Notify, MUIA_Cycle_Active, MUIV_EveryTime, AP_Scout, 2, MUIM_Application_ReturnID, ID_RESSORT);

         SetCloseRequest (WI_Resources,ID_RESEXIT);
         SetListActive (reslist,ID_RESLV_ACTIVE);
         SetListviewDoubleClick (reslist,ID_RESMORE);

         ShowResources();

         SetWindowOpen (WI_Resources,reslist,ID_RESEXIT);
      }
   } else if ((! state) && (WI_Resources)) {
      SetWindowClose (WI_Resources,TRUE);

      FreeResources();

      DoMethod (AP_Scout,OM_REMMEMBER,WI_Resources);
      MUI_DisposeObject (WI_Resources);
      WI_Resources = NULL;
      reslist = NULL;
   }
}


