/****h *AmigaTalk/SysScreens.c ****************************************
**
** NAME
**    SysScreens.c - display info about all open screens & windows
**
** DESCRIPTION
**    Allow the user to view a list of all Screens & Windows that are
**    currently open to Intuition.  The user can close any Window or
**    Screen safely(?).
**
** FUNCTIONAL INTERFACE:
**
**    PUBLIC void CloseTheScreen( struct Screen *scr );
**
**    PUBLIC void CloseTheWindow( struct Window *wind );
**
**    PUBLIC int HandleScreenLV( void );
**
***********************************************************************
*/

#include <stdio.h>
#include <string.h>

#include <exec/types.h>
#include <exec/lists.h>
#include <exec/nodes.h>

#include <dos/dosextens.h>

#include <AmigaDOSErrs.h>

#include <intuition/intuitionbase.h>
#include <intuition/classes.h>
#include <intuition/classusr.h>
#include <intuition/gadgetclass.h>

#include <libraries/gadtools.h>

#include <graphics/displayinfo.h>
#include <graphics/gfxbase.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/graphics_protos.h>
#include <clib/utility_protos.h>
#include <clib/diskfont_protos.h>

#include "CPGM:GlobalObjects/CommonFuncs.h"

#include "SysLists.h"

#define MAX_HEIGHT 380

PRIVATE int HandleWindowInfo( void *structptr, int whichdisplay );

PRIVATE char ver[] = "$VER: SysScreens 1.0 (12/20/1999) by J.T. Steichen";

PRIVATE struct Window *IWnd = NULL;

PRIVATE UWORD ILeft   = 0;
PRIVATE UWORD ITop    = 32;
PRIVATE UWORD IWidth  = 640;
PRIVATE UWORD IHeight = MAX_HEIGHT;

PRIVATE UBYTE *IWTitle = "System Screens & Windows Full Info:";

#define XPOS    6
#define MAXNODE 100

PRIVATE struct Gadget *ScrGadgets[ SCR_CNT ];

PRIVATE UBYTE *WTitle = "System Screens & Windows Info:";

PRIVATE UWORD StrYPos[32] = { 0, };

PRIVATE struct MinList ScrList;

PRIVATE struct Node    ScrNode;
PRIVATE struct Node    ScrNodes[ MAXNODE ]      = { NULL, };

PRIVATE UBYTE          NodeStrs[ MAXNODE * 80 ] = "";

PRIVATE UWORD ScrGTypes[] = {

   LISTVIEW_KIND, BUTTON_KIND, BUTTON_KIND, 
   BUTTON_KIND,   BUTTON_KIND, TEXT_KIND
};

PRIVATE int SLVClicked(    int itemnum );
PRIVATE int UpdateClicked( int dummy   );
PRIVATE int CancelClicked( int dummy   );
PRIVATE int MoreClicked(   int dummy   );
PRIVATE int CloseClicked(  int dummy   );

PRIVATE struct NewGadget ScrNGad[] = {

     2,   3, 627, 200,               NULL, NULL, ScrLV,
   0,           NULL, (APTR) SLVClicked,

     4, 205,  71, 17, (UBYTE *) "_Update", NULL, ScrUpdate,
   PLACETEXT_IN, NULL, (APTR) UpdateClicked,

    89, 205,  72, 17, (UBYTE *) "_More",   NULL, ScrMore,
   PLACETEXT_IN, NULL, (APTR) MoreClicked,

   255, 205,  72, 17, (UBYTE *) "Close",   NULL, ScrClose,
   PLACETEXT_IN, NULL, (APTR) CloseClicked,

   554, 205,  72, 17, (UBYTE *) "_Cancel", NULL, ScrCancel,
   PLACETEXT_IN, NULL, (APTR) CancelClicked,

     5, 228, 620, 17,                NULL, NULL, ScrSelection, 
   0, NULL, NULL
};

PRIVATE ULONG ScrGTags[] = {

   GTLV_ShowSelected, NULL, (LAYOUTA_Spacing), 2, (TAG_DONE),

   (GT_Underscore), '_', (TAG_DONE),
   (GT_Underscore), '_', (GA_Disabled), TRUE, (TAG_DONE),

   (GA_Disabled), TRUE, (TAG_DONE),

   (GT_Underscore), '_', (TAG_DONE),

   (GTTX_Border), TRUE, (TAG_DONE)
};

// -----------------------------------------------------------------

PRIVATE void WriteText( char *string, int xpos, int ypos, int color ) 
{
   struct RastPort  *rp = IWnd->RPort;
   struct IntuiText  outtxt;

   outtxt.FrontPen  = color;
   outtxt.BackPen   = 0;
   outtxt.DrawMode  = JAM1;
   outtxt.LeftEdge  = 0;
   outtxt.TopEdge   = 0;
   outtxt.ITextFont = Font;
   outtxt.NextText  = NULL;
   outtxt.IText     = (UBYTE *) string;

   PrintIText( rp, &outtxt, xpos, ypos );

   return;
}

PRIVATE char typ[10], *pgmtype = &typ[0];

PRIVATE char *GetTask_Process( UBYTE type )
{
   if (type == NT_TASK)
      strcpy( pgmtype, "TASK" );
   else if (type == NT_PROCESS)
      strcpy( pgmtype, "PROCESS" );
   else   
      strcpy( pgmtype, "TASK" );

   return( pgmtype );
}

PRIVATE BOOL CheckBit( int flags, int bit )
{
   if ((flags & bit) == bit)
      return( TRUE );
   else
      return( FALSE );
}

PRIVATE char ts[10], *taskstate = &ts[0];
PRIVATE BOOL DispTaskFlag = TRUE;

PRIVATE char *GetTaskState( struct Task *t )
{
   if (t == NULL)
      return( "INVALID" );

   switch (t->tc_State)
      {
      case TS_INVALID:
         strcpy( taskstate, "INVALID" );  // Stack won't be right.
         DispTaskFlag = FALSE;
         break;
         
      case TS_ADDED:
         strcpy( taskstate, "ADDED" );
         DispTaskFlag = TRUE;
         break;
         
      case TS_RUN:
         strcpy( taskstate, "RUNNING" );
         DispTaskFlag = TRUE;
         break;
         
      case TS_READY:
         strcpy( taskstate, "READY" );
         DispTaskFlag = TRUE;
         break;
         
      case TS_WAIT:
         strcpy( taskstate, "WAITING" );
         DispTaskFlag = TRUE;
         break;
         
      case TS_EXCEPT:
         strcpy( taskstate, "EXCEPTION" );
         DispTaskFlag = TRUE;
         break;
         
      case TS_REMOVED:
         strcpy( taskstate, "REMOVED" );
         DispTaskFlag = TRUE;
         break;
      }

   return( taskstate );
}

PRIVATE void SetTaskFlags( struct Task *t, char *str )
{
   *str = '\0';

   if (CheckBit( t->tc_Flags, TF_PROCTIME ) == TRUE)
      strcpy( str, "TF_PROCTIME " );
   
   if (CheckBit( t->tc_Flags, TF_ETASK ) == TRUE)
      strcat( str, "TF_ETASK " );

   if (CheckBit( t->tc_Flags, TF_STACKCHK ) == TRUE)
      strcat( str, "TF_STACKCHK " );

   if (CheckBit( t->tc_Flags, TF_EXCEPT ) == TRUE)
      strcat( str, "TF_EXCEPT " );

   if (CheckBit( t->tc_Flags, TF_SWITCH ) == TRUE)
      strcat( str, "TF_SWITCH " );

   if (CheckBit( t->tc_Flags, TF_LAUNCH ) == TRUE)
      strcat( str, "TF_LAUNCH" );

   return;
}


#define B2APTR( bptr ) ((bptr) << 2)

PRIVATE void WriteTask( void *ptr )
{
   IMPORT UWORD StrYPos[];
   
   struct Task    *task    = (struct Task *) ptr;
   struct Process *process = NULL;

   char t[82], *title = &t[0];
   char s[82], *str   = &s[0];

   int  size = 0;
   
   if (task == NULL)
      return; 

   sprintf( title, "%s: (%08LX) -> %-40.40s", 
            GetTask_Process( task->tc_Node.ln_Type ),
            task, task->tc_Node.ln_Name
          );

   SetWindowTitles( Wnd, title, (char *) -1 );

   // Common (to Task & Process) data to display:
   if ((task->tc_Node.ln_Type == NT_TASK) 
       || (task->tc_Node.ln_Type == NT_PROCESS))
      {
      sprintf( str, "STATE: %s Priority: %4d", 
               GetTaskState( task ),
               task->tc_Node.ln_Pri 
             );

      WriteText( str, XPOS, StrYPos[0], 2 );

      sprintf( str, "SigAlloc: %08LX SigWait : %08LX SigRecvd : %08LX SigExcept: %08LX", 
               task->tc_SigAlloc, task->tc_SigWait, 
               task->tc_SigRecvd, task->tc_SigExcept
             );

      WriteText( str, XPOS, StrYPos[1], 1 );

      sprintf( str, "TrapData: %08LX TrapCode: %08LX TrapAlloc: %08LX TrapAble : %08LX",
               task->tc_TrapData, task->tc_TrapCode, 
               task->tc_TrapAlloc, task->tc_TrapAble
             );

      WriteText( str, XPOS, StrYPos[2], 1 );

      sprintf( str, "Switch(): %08LX Launch(): %08LX UserData : %08LX", 
               task->tc_Switch, task->tc_Launch, 
               task->tc_UserData
             );

      WriteText( str, XPOS, StrYPos[3], 2 );

      sprintf( str, "ExceptData: %08LX ExceptCode: %08LX", 
               task->tc_ExceptData, task->tc_ExceptCode
             );

      WriteText( str, XPOS, StrYPos[5], 1 );

      size = (int) task->tc_SPUpper - (int) task->tc_SPLower;

      sprintf( str, "SPReg     : %08LX SPUpper   : %08LX SPLower: %08LX size: %d",
               task->tc_SPReg, task->tc_SPUpper, 
               task->tc_SPLower, size
             );

      WriteText( str, XPOS, StrYPos[6], 2 );

      sprintf( str, "IDNestCnt: %-08d TDNestCnt: %3d",
               task->tc_IDNestCnt, task->tc_TDNestCnt
             );

      WriteText( str, XPOS, StrYPos[8], 1 );

      sprintf( str, "MemEntry : %08LX", task->tc_MemEntry.lh_Head );

      WriteText( str, XPOS, StrYPos[9], 1 );

      WriteText( "Flags:", XPOS, StrYPos[10], 3 );

      SetTaskFlags( task, str );

      WriteText( str, XPOS, StrYPos[11], 1 );

      if (task->tc_Node.ln_Type == NT_TASK) 
         WriteText( "Press Close Gadget when you're done!", 
                    150, StrYPos[12], 2 
                  ); 
      }

   // Process additions to display:
   if (task->tc_Node.ln_Type == NT_PROCESS)
      {
      char   pn[256], *path = &pn[0];
      UBYTE *ttl = NULL;
            
      process = (struct Process *) ptr;

      WriteText( "Process Structure:", XPOS, StrYPos[12], 3 );  

      if ((struct Window *) process->pr_WindowPtr != NULL)
         ttl = ((struct Window *) process->pr_WindowPtr)->Title;
      else
         ttl = "*NO TITLE!*";

      sprintf( str, "WindowPtr  : %08LX Title: %-40.40s", 
               process->pr_WindowPtr, 
               (strlen( ttl ) > 0) ? ttl : (UBYTE *) "*NO TITLE!*"
             );

      WriteText( str, XPOS, StrYPos[13], 2 );

      if (process->pr_CurrentDir != NULL)
         (void) NameFromLock( process->pr_CurrentDir, path, 255 );
          
      sprintf( str, "CurrentDir : %08LX Path : %-40.40s", 
               B2APTR( process->pr_CurrentDir ),
               (path == NULL) ? "*NO PATH*" : path
             );

      WriteText( str, XPOS, StrYPos[14], 2 );

      sprintf( str, "MsgPort    : %08LX SegList       : %08LX", 
               process->pr_MsgPort, B2APTR( process->pr_SegList )
             );

      WriteText( str, XPOS, StrYPos[15], 1 );

      sprintf( str, "StackBase  : %08LX StackSize     : %d", 
               B2APTR( process->pr_StackBase ), process->pr_StackSize
             );

      WriteText( str, XPOS, StrYPos[16], 1 );

      sprintf( str, "CIS        : %08LX COS           : %08LX", 
               B2APTR( process->pr_CIS ), B2APTR( process->pr_COS )
             );

      WriteText( str, XPOS, StrYPos[17], 1 );

      sprintf( str, "ConsoleTask: %08LX FileSystemTask: %08LX", 
               process->pr_ConsoleTask, 
               process->pr_FileSystemTask
             );

      WriteText( str, XPOS, StrYPos[18], 1 );

      sprintf( str, "PktWait    : %08LX ReturnAddr    : %08LX", 
               process->pr_PktWait, 
               process->pr_ReturnAddr
             );

      WriteText( str, XPOS, StrYPos[19], 1 );

      sprintf( str, "Arguments -> %-60.60s", 
               (process->pr_Arguments == NULL) ? (UBYTE *) "*NO ARGS!*" 
                                               : process->pr_Arguments
             );

      WriteText( str, XPOS, StrYPos[20], 2 );

      sprintf( str, "GlobVec    : %08LX CLI           : %08LX", 
               process->pr_GlobVec, 
               B2APTR( process->pr_CLI )
             );

      WriteText( str, XPOS, StrYPos[21], 1 );

      // CLI additional information: 

      if (process->pr_CLI != NULL)
         {
         struct CommandLineInterface *cli = NULL;
         BOOL                         iflag = FALSE, bflag = FALSE;

         cli = (struct CommandLineInterface *) (process->pr_CLI << 2);

         WriteText( "CommandLineInterface structure:", 
                    XPOS, StrYPos[22], 3
                  );

         sprintf( str, "CommandDir   : %08LX", 
                  B2APTR( cli->cli_CommandDir )
                );

         WriteText( str, XPOS, StrYPos[23], 1 );

         sprintf( str, "StandardInput: %08LX StandardOutput: %08LX", 
                  B2APTR( cli->cli_StandardInput ),
                  B2APTR( cli->cli_StandardOutput )
                );

         WriteText( str, XPOS, StrYPos[24], 1 );

         sprintf( str, "CurrentInput : %08LX CurrentOutput : %08LX", 
                  B2APTR( cli->cli_CurrentInput  ),
                  B2APTR( cli->cli_CurrentOutput )
                );

         WriteText( str, XPOS, StrYPos[25], 1 );

         if (cli->cli_Interactive != FALSE)
            iflag = TRUE;
            
         if (cli->cli_Background != FALSE)
            bflag = TRUE;
            
         sprintf( str, "Module       : %08LX %s %s", 
                  B2APTR( cli->cli_Module ),
                  (bflag == TRUE) ? "BACKGROUND" : "",
                  (iflag == TRUE) ? "& INTERACTIVE" : ""
                );

         WriteText( str, XPOS, StrYPos[26], 1 );
         }

      WriteText( "Press Close Gadget when you're done!", 
                 150, StrYPos[27], 2 
               ); 
      }

   return;
}


PRIVATE void CountGadgets( struct Window *w, int *bgad, 
                           int *sgad, int *pgad
                         )
{
   struct Gadget *first = w->FirstGadget;
   
   while (first != NULL)
      {
      switch (first->GadgetType & 0x07)
         {
         case BOOLGADGET:
            *bgad += 1;
            break; 

         case STRGADGET:
            *sgad += 1;
            break; 

         case PROPGADGET:
            *pgad += 1;
            break; 
         }
          
      first = first->NextGadget;
      }

   return;
}

PRIVATE void CountMenus( struct Window *w, int *m, int *mi )
{
   struct Menu     *menu  = w->MenuStrip;
   struct MenuItem *mitem = NULL;

   while (menu != NULL)
      {
      *m += 1;
      mitem = menu->FirstItem;
      
      while (mitem != NULL)
         {
         *mi += 1;
         
         if (mitem->SubItem != NULL)
            {
            struct MenuItem *subs = mitem->SubItem;
            
            while (subs != NULL)
               {
               *mi += 1;
               
               subs = subs->NextItem;
               }
            }

         mitem = mitem->NextItem;
         }
      
      menu = menu->NextMenu;
      }

   return;
}

PRIVATE void SetScreenFlagString( char *str, struct Screen *s )
{
   if (CheckBit( s->Flags, CUSTOMSCREEN ) == TRUE)
      strcpy( str, "CUSTOMSCREEN  " );
   else
      strcpy( str, "WBENCHSCREEN  " );

   if (CheckBit( s->Flags, SHOWTITLE ) == TRUE)
      strcat( str, "SHOWTITLE  " );
 
   if (CheckBit( s->Flags, BEEPING ) == TRUE)
      strcat( str, "BEEPING  " );
 
   if (CheckBit( s->Flags, CUSTOMBITMAP ) == TRUE)
      strcat( str, "CUSTOMBITMAP" );
 
   return;
}


PRIVATE void SetScreenViewMode1( char *str, struct Screen *s )
{
   *str = '\0';

   if (CheckBit( s->ViewPort.Modes, HIRES ) == TRUE)
      strcpy( str, "HIRES  " );

   if (CheckBit( s->ViewPort.Modes, SPRITES ) == TRUE)
      strcat( str, "SPRITES  " );

   if (CheckBit( s->ViewPort.Modes, VP_HIDE ) == TRUE)
      strcat( str, "VP_HIDE  " );

   if (CheckBit( s->ViewPort.Modes, EXTENDED_MODE ) == TRUE)
      strcat( str, "EXTENDED  " );

   if (CheckBit( s->ViewPort.Modes, HAM ) == TRUE)
      strcat( str, "HAM  " );

   if (CheckBit( s->ViewPort.Modes, DUALPF ) == TRUE)
      strcat( str, "DUALPF  " );

   if (CheckBit( s->ViewPort.Modes, GENLOCK_AUDIO ) == TRUE)
      strcat( str, "GENLOCK_AUDIO  " );

   if (CheckBit( s->ViewPort.Modes, PFBA ) == TRUE)
      strcat( str, "PFBA" );

   return;
}

PRIVATE void SetScreenViewMode2( char *str, struct Screen *s )
{
   *str = '\0';
   
   if (CheckBit( s->ViewPort.Modes, LACE ) == TRUE)
      strcpy( str, "LACE  " );

   if (CheckBit( s->ViewPort.Modes, DOUBLESCAN ) == TRUE)
      strcat( str, "DOUBLESCAN  " );

   if (CheckBit( s->ViewPort.Modes, SUPERHIRES ) == TRUE)
      strcat( str, "SUPERHIRES  " );

   if (CheckBit( s->ViewPort.Modes, EXTRA_HALFBRITE ) == TRUE)
      strcat( str, "EXTRA_HALFBRITE  " );

   if (CheckBit( s->ViewPort.Modes, GENLOCK_VIDEO ) == TRUE)
      strcat( str, "GENLOCK_VIDEO" );

   return;
}

PRIVATE void SetWindowFlags1( struct Window *w, char *str )
{
   *str = '\0';

   if (CheckBit( w->Flags, WFLG_SIZEGADGET ) == TRUE)
      strcpy( str, "WFLG_SIZEGADGET " );

   if (CheckBit( w->Flags, WFLG_DRAGBAR ) == TRUE)
      strcat( str, "WFLG_DRAGBAR " );

   if (CheckBit( w->Flags, WFLG_DEPTHGADGET ) == TRUE)
      strcat( str, "WFLG_DEPTHGADGET " );

   if (CheckBit( w->Flags, WFLG_CLOSEGADGET ) == TRUE)
      strcat( str, "WFLG_CLOSEGADGET" );

   return;
}

PRIVATE void SetWindowFlags2( struct Window *w, char *str )
{
   *str = '\0';

   if (CheckBit( w->Flags, WFLG_SMART_REFRESH ) == TRUE)
      strcpy( str, "WFLG_SMART_REFRESH " );

   if (CheckBit( w->Flags, WFLG_SIMPLE_REFRESH ) == TRUE)
      strcat( str, "WFLG_SIMPLE_REFRESH " );

   if (CheckBit( w->Flags, WFLG_SUPER_BITMAP ) == TRUE)
      strcat( str, "WFLG_SUPER_BITMAP " );

   if (CheckBit( w->Flags, WFLG_OTHER_REFRESH ) == TRUE)
      strcat( str, "WFLG_OTHER_REFRESH " );

   if (CheckBit( w->Flags, WFLG_GIMMEZEROZERO ) == TRUE)
      strcat( str, "WFLG_GIMMEZEROZERO" );

   return;
}

PRIVATE void SetWindowFlags3( struct Window *w, char *str )
{
   *str = '\0';

   if (CheckBit( w->Flags, WFLG_BACKDROP ) == TRUE)
      strcpy( str, "WFLG_BACKDROP " );

   if (CheckBit( w->Flags, WFLG_REPORTMOUSE ) == TRUE)
      strcat( str, "WFLG_REPORTMOUSE " );

   if (CheckBit( w->Flags, WFLG_BORDERLESS ) == TRUE)
      strcat( str, "WFLG_BORDERLESS " );

   if (CheckBit( w->Flags, WFLG_ACTIVATE ) == TRUE)
      strcat( str, "WFLG_ACTIVATE " );

   if (CheckBit( w->Flags, WFLG_SIZEBRIGHT ) == TRUE)
      strcat( str, "WFLG_SIZEBRIGHT" );

   if (CheckBit( w->Flags, WFLG_SIZEBBOTTOM ) == TRUE)
      strcat( str, "WFLG_SIZEBBOTTOM" );

   return;
}

PRIVATE void SetWindowFlags4( struct Window *w, char *str )
{
   *str = '\0';

   if (CheckBit( w->Flags, WFLG_RMBTRAP ) == TRUE)
      strcpy( str, "WFLG_RMBTRAP " );

   if (CheckBit( w->Flags, WFLG_NOCAREREFRESH ) == TRUE)
      strcat( str, "WFLG_NOCAREREFRESH " );

   if (CheckBit( w->Flags, WFLG_WINDOWACTIVE ) == TRUE)
      strcat( str, "WFLG_WINDOWACTIVE " );

   if (CheckBit( w->Flags, WFLG_WBENCHWINDOW ) == TRUE)
      strcat( str, "WFLG_WBENCHWINDOW " );

   if (CheckBit( w->Flags, WFLG_HASZOOM ) == TRUE)
      strcat( str, "WFLG_HASZOOM " );

   if (CheckBit( w->Flags, WFLG_ZOOMED ) == TRUE)
      strcat( str, "WFLG_ZOOMED" );

   return;
}

PRIVATE void SetIDCMPFlags1( struct Window *w, char *str )
{
   *str = '\0';

   if (CheckBit( w->IDCMPFlags, IDCMP_SIZEVERIFY ) == TRUE)
      strcpy( str, "IDCMP_SIZEVERIFY " );

   if (CheckBit( w->IDCMPFlags, IDCMP_NEWSIZE ) == TRUE)
      strcat( str, "IDCMP_NEWSIZE " );

   if (CheckBit( w->IDCMPFlags, IDCMP_REFRESHWINDOW ) == TRUE)
      strcat( str, "IDCMP_REFRESHWINDOW " );

   if (CheckBit( w->IDCMPFlags, IDCMP_MOUSEBUTTONS ) == TRUE)
      strcat( str, "IDCMP_MOUSEBUTTONS" );

   return;
}

PRIVATE void SetIDCMPFlags2( struct Window *w, char *str )
{
   *str = '\0';

   if (CheckBit( w->IDCMPFlags, IDCMP_MOUSEMOVE ) == TRUE)
      strcpy( str, "IDCMP_MOUSEMOVE " );

   if (CheckBit( w->IDCMPFlags, IDCMP_GADGETDOWN ) == TRUE)
      strcat( str, "IDCMP_GADGETDOWN " );

   if (CheckBit( w->IDCMPFlags, IDCMP_GADGETUP ) == TRUE)
      strcat( str, "IDCMP_GADGETUP " );

   if (CheckBit( w->IDCMPFlags, IDCMP_REQSET ) == TRUE)
      strcat( str, "IDCMP_REQSET" );

   return;
}

PRIVATE void SetIDCMPFlags3( struct Window *w, char *str )
{
   *str = '\0';

   if (CheckBit( w->IDCMPFlags, IDCMP_MENUPICK ) == TRUE)
      strcpy( str, "IDCMP_MENUPICK " );

   if (CheckBit( w->IDCMPFlags, IDCMP_CLOSEWINDOW ) == TRUE)
      strcat( str, "IDCMP_CLOSEWINDOW " );

   if (CheckBit( w->IDCMPFlags, IDCMP_RAWKEY ) == TRUE)
      strcat( str, "IDCMP_RAWKEY " );

   if (CheckBit( w->IDCMPFlags, IDCMP_REQVERIFY ) == TRUE)
      strcat( str, "IDCMP_REQVERIFY" );

   return;
}

PRIVATE void SetIDCMPFlags4( struct Window *w, char *str )
{
   *str = '\0';

   if (CheckBit( w->IDCMPFlags, IDCMP_REQCLEAR ) == TRUE)
      strcpy( str, "IDCMP_REQCLEAR " );

   if (CheckBit( w->IDCMPFlags, IDCMP_MENUVERIFY ) == TRUE)
      strcat( str, "IDCMP_MENUVERIFY " );

   if (CheckBit( w->IDCMPFlags, IDCMP_NEWPREFS ) == TRUE)
      strcat( str, "IDCMP_NEWPREFS " );

   if (CheckBit( w->IDCMPFlags, IDCMP_DISKINSERTED ) == TRUE)
      strcat( str, "IDCMP_DISKINSERTED" );

   return;
}

PRIVATE void SetIDCMPFlags5( struct Window *w, char *str )
{
   *str = '\0';

   if (CheckBit( w->IDCMPFlags, IDCMP_DISKREMOVED ) == TRUE)
      strcpy( str, "IDCMP_DISKREMOVED " );

   if (CheckBit( w->IDCMPFlags, IDCMP_WBENCHMESSAGE ) == TRUE)
      strcat( str, "IDCMP_WBENCHMESSAGE " );

   if (CheckBit( w->IDCMPFlags, IDCMP_ACTIVEWINDOW ) == TRUE)
      strcat( str, "IDCMP_ACTIVEWINDOW " );

   if (CheckBit( w->IDCMPFlags, IDCMP_INACTIVEWINDOW ) == TRUE)
      strcat( str, "IDCMP_INACTIVEWINDOW" );

   return;
}

PRIVATE void SetIDCMPFlags6( struct Window *w, char *str )
{
   *str = '\0';

   if (CheckBit( w->IDCMPFlags, IDCMP_DELTAMOVE ) == TRUE)
      strcpy( str, "IDCMP_DELTAMOVE " );

   if (CheckBit( w->IDCMPFlags, IDCMP_VANILLAKEY ) == TRUE)
      strcat( str, "IDCMP_VANILLAKEY " );

   if (CheckBit( w->IDCMPFlags, IDCMP_INTUITICKS ) == TRUE)
      strcat( str, "IDCMP_INTUITICKS " );

   if (CheckBit( w->IDCMPFlags, IDCMP_IDCMPUPDATE ) == TRUE)
      strcat( str, "IDCMP_IDCMPUPDATE" );

   return;
}

PRIVATE void SetIDCMPFlags7( struct Window *w, char *str )
{
   *str = '\0';

   if (CheckBit( w->IDCMPFlags, IDCMP_MENUHELP ) == TRUE)
      strcpy( str, "IDCMP_MENUHELP " );

   if (CheckBit( w->IDCMPFlags, IDCMP_CHANGEWINDOW ) == TRUE)
      strcat( str, "IDCMP_CHANGEWINDOW " );

   if (CheckBit( w->IDCMPFlags, IDCMP_GADGETHELP ) == TRUE)
      strcat( str, "IDCMP_GADGETHELP" );

   return;
}


PRIVATE char bf[82], *itxt  = &bf[0];
PRIVATE char tx[82], *title = &tx[0];

PRIVATE void DisplayStructure( void *ptr, int struct_type )
{
   struct Screen *s = NULL;
   struct Window *w = NULL;
   struct Task   *t = NULL;
  
   int            bgad, sgad, pgad, m, mi;
  
   bgad = sgad = pgad = m = mi = 0;
   
   switch (struct_type)
      {
      case 0: // Screen data:
         s = (struct Screen *) ptr;

         sprintf( title, "SCREEN: (%08LX) %s", s, s->Title );
         SetWindowTitles( IWnd, title, (UBYTE *) -1 );

         sprintf( itxt, "DefaultTitle: %s", s->DefaultTitle );
         WriteText( itxt, XPOS, StrYPos[0], 2 ); 

         sprintf( itxt, "Left     : %3u Top       : %3u Width: %4u Height: %4u", 
                  s->LeftEdge, s->TopEdge, s->Width, s->Height 
                );
         WriteText( itxt, XPOS, StrYPos[1], 1 ); 

         sprintf( itxt, "WBorLeft : %3u WBorTop   : %3u", 
                  s->WBorLeft, s->WBorTop
                );
         WriteText( itxt, XPOS, StrYPos[2], 1 ); 

         sprintf( itxt, "WBorRight: %3u WBorBottom: %3u", 
                  s->WBorRight, s->WBorBottom
                );
         WriteText( itxt, XPOS, StrYPos[3], 1 ); 

         sprintf( itxt, "DetailPen: %3u BlockPen  : %3u", 
                  s->DetailPen, s->BlockPen
                );
         WriteText( itxt, XPOS, StrYPos[4], 1 ); 

         sprintf( itxt, "ViewPort  : %08LX RastPort   : %08LX", 
                  s->ViewPort, s->RastPort
                );
         WriteText( itxt, XPOS, StrYPos[5], 1 ); 

         sprintf( itxt, "BitMap    : %08LX LayerInfo  : %08LX", 
                  s->BitMap, s->LayerInfo
                );
         WriteText( itxt, XPOS, StrYPos[6], 1 ); 

         sprintf( itxt, "ExtData   : %08LX UserData   : %08LX", 
                  s->ExtData, s->UserData
                );
         WriteText( itxt, XPOS, StrYPos[7], 1 ); 

         sprintf( itxt, "NextScreen: %08LX FirstWindow: %08LX", 
                  s->NextScreen, s->FirstWindow
                );
         WriteText( itxt, XPOS, StrYPos[8], 2 ); 

         sprintf( itxt, "BarHeight  : %3u BarVBorder : %3u BarHBorder: %3u", 
                  s->BarHeight, s->BarVBorder, s->BarHBorder
                );
         WriteText( itxt, XPOS, StrYPos[9], 1 ); 

         sprintf( itxt, "MenuVBorder: %3u MenuHBorder: %3u", 
                  s->MenuVBorder, s->MenuHBorder
                );
         WriteText( itxt, XPOS, StrYPos[10], 1 ); 

         WriteText( "Flags:", XPOS, StrYPos[11], 3 );
         
         SetScreenFlagString( itxt, s );
         WriteText( itxt, XPOS, StrYPos[12], 1 );

         WriteText( "ViewModes:", XPOS, StrYPos[13], 3 );

         SetScreenViewMode1( itxt, s );
         WriteText( itxt, XPOS, StrYPos[14], 1 );

         SetScreenViewMode2( itxt, s );
         WriteText( itxt, XPOS, StrYPos[15], 1 );

         WriteText( "Press Close Gadget when you're done!", 
                    150, StrYPos[16], 2 
                  ); 
         break;

      case 1: // Window data:
         w = (struct Window *) ptr;

         sprintf( title, "WINDOW: (%08LX) %s", w, w->Title );
         SetWindowTitles( IWnd, title, (UBYTE *) -1 );

         sprintf( itxt, "WScreen: %08LX -> %s", 
                  w->WScreen, w->WScreen->Title 
                );
         WriteText( itxt, XPOS, StrYPos[0], 2 ); 

         sprintf( itxt, "Left    : %3u Top      : %3u Width    : %5u Height   : %5u",
                  w->LeftEdge, w->TopEdge, w->Width, w->Height 
                );
         WriteText( itxt, XPOS, StrYPos[1], 1 ); 

         sprintf( itxt, "MinWidth: %3u MinHeight: %3u MaxWidth : %5u MaxHeight: %5u",
                  w->MinWidth, w->MinHeight, w->MaxWidth, w->MaxHeight 
                );
         WriteText( itxt, XPOS, StrYPos[2], 1 ); 

         sprintf( itxt, "BdrLeft : %3u BdrTop   : %3u BdrRight : %5u BdrBottom: %5u",
                  w->BorderLeft, w->BorderTop, 
                  w->BorderRight, w->BorderBottom
                );
         WriteText( itxt, XPOS, StrYPos[3], 1 ); 

         sprintf( itxt, "XOffset : %3u YOffset  : %3u DetailPen: %5u BlockPen : %5u",
                  w->XOffset, w->YOffset, w->DetailPen, w->BlockPen
                );
         WriteText( itxt, XPOS, StrYPos[4], 1 ); 

         sprintf( itxt, "CheckMark: %08LX ExtData: %08LX UserData: %08LX",
                  w->CheckMark, w->ExtData, w->UserData
                );
         WriteText( itxt, XPOS, StrYPos[5], 2 ); 

         CountGadgets( w, &bgad, &sgad, &pgad );

         sprintf( itxt, "BoolGadgets: %2u StrGadgets: %4u PropGadgets: %2u",
                  bgad, sgad, pgad
                );
         WriteText( itxt, XPOS, StrYPos[6], 1 ); 

         CountMenus( w, &m, &mi );

         sprintf( itxt, "Menus      : %2u MenuItems : %4u", m, mi );
         WriteText( itxt, XPOS, StrYPos[7], 1 ); 

         t = (struct Task *) w->UserPort->mp_SigTask;

         sprintf( itxt, "UserPort  : %08LX -> mp_SigTask: %08LX, %-30.30s",
                  w->UserPort, w->UserPort->mp_SigTask,
                  (t == NULL ? " " : t->tc_Node.ln_Name)
                );
         WriteText( itxt, XPOS, StrYPos[8], 2 ); 

         t = (struct Task *) w->WindowPort->mp_SigTask;
         
         sprintf( itxt, "WindowPort: %08LX -> mp_SigTask: %08LX, %-30.30s",
                  w->WindowPort, w->WindowPort->mp_SigTask,
                  (t == NULL ? " " : t->tc_Node.ln_Name) 
                );
         WriteText( itxt, XPOS, StrYPos[9], 2 ); 

         sprintf( itxt, "PtrHeight: %3u PtrWidth: %2u Pointer: %08LX",
                  w->PtrHeight, w->PtrWidth, w->Pointer
                );
         WriteText( itxt, XPOS, StrYPos[10], 1 ); 

         sprintf( itxt, "ReqCount : %3u NextWindow: %08LX",
                  w->ReqCount, w->NextWindow
                );
         WriteText( itxt, XPOS, StrYPos[11], 1 ); 

         WriteText( "Flags:", XPOS, StrYPos[12], 3 );

         SetWindowFlags1( w, itxt );
         WriteText( itxt, XPOS, StrYPos[13], 1 ); 

         SetWindowFlags2( w, itxt );
         WriteText( itxt, XPOS, StrYPos[14], 1 ); 

         SetWindowFlags3( w, itxt );
         WriteText( itxt, XPOS, StrYPos[15], 1 ); 

         SetWindowFlags4( w, itxt );
         WriteText( itxt, XPOS, StrYPos[16], 1 ); 

         WriteText( "IDCMPFlags:", XPOS, StrYPos[17], 3 );

         SetIDCMPFlags1( w, itxt );
         WriteText( itxt, XPOS, StrYPos[18], 1 ); 

         SetIDCMPFlags2( w, itxt );
         WriteText( itxt, XPOS, StrYPos[19], 1 ); 

         SetIDCMPFlags3( w, itxt );
         WriteText( itxt, XPOS, StrYPos[20], 1 ); 

         SetIDCMPFlags4( w, itxt );
         WriteText( itxt, XPOS, StrYPos[21], 1 ); 

         SetIDCMPFlags5( w, itxt );
         WriteText( itxt, XPOS, StrYPos[22], 1 ); 

         SetIDCMPFlags6( w, itxt );
         WriteText( itxt, XPOS, StrYPos[23], 1 ); 

         SetIDCMPFlags7( w, itxt );
         WriteText( itxt, XPOS, StrYPos[24], 1 ); 

         WriteText( "Press Close Gadget when you're done!", 
                    150, StrYPos[25], 2 
                  ); 
         break;
      
      case 2: // Task structure:
         WriteTask( ptr );
         break;

      case 3: // Process structure:
         WriteTask( ptr );
         break;
      }

   return;
}


PRIVATE int OpenIWindow( int numlines )
{
   UWORD wleft = ILeft, wtop = ITop, ww, wh;
   int   i;
   
   ComputeFont( Scr, Font, &CFont, IWidth, IHeight );

   IHeight = (numlines + 1) * (CFont.FontY + 3) + 2;

   if (IHeight > MAX_HEIGHT)
      IHeight = MAX_HEIGHT;

   for (i = 0; i < 32; i++)
      StrYPos[i] = 16 + i * (CFont.FontY + 3);
         
   ww = ComputeX( CFont.FontX, IWidth  );
   wh = ComputeY( CFont.FontY, IHeight );

   if ((wleft + ww + CFont.OffX + Scr->WBorRight) > Scr->Width) 
      wleft = Scr->Width - ww;

   if ((wtop + wh + CFont.OffY + Scr->WBorBottom) > Scr->Height) 
      wtop = Scr->Height - wh;

   if ( !(IWnd = OpenWindowTags( NULL,

                   WA_Left,        wleft,
                   WA_Top,         wtop,
                   WA_Width,       ww + CFont.OffX + Scr->WBorRight,
                   WA_Height,      wh + CFont.OffY + Scr->WBorBottom,
                   WA_IDCMP,       BUTTONIDCMP | IDCMP_GADGETUP
                     | IDCMP_REFRESHWINDOW | IDCMP_CLOSEWINDOW,

                   WA_Flags,       WFLG_SMART_REFRESH | WFLG_CLOSEGADGET 
                     | WFLG_ACTIVATE | WFLG_RMBTRAP,

                   WA_Gadgets,     NULL,
                   WA_Title,       IWTitle,
                   WA_ScreenTitle, ScrTitle,
                   TAG_DONE ))
      )
      return( -4 );

   return( 0 );
}

PRIVATE void CloseIWindow( void )
{
   if (IWnd != NULL) 
      {
      CloseWindow( IWnd );
      IWnd = NULL;
      }

   return;
}

PRIVATE int ICloseWindow( void )
{
   CloseIWindow();
   return( (int) FALSE );
}

PRIVATE int HandleInfoIDCMP( void )
{
   struct IntuiMessage	*m;
   BOOL			running = TRUE;

   while (running == TRUE)
      {
      if ((m = (struct IntuiMessag *) GetMsg( IWnd->UserPort )) == NULL)
         {
         (void) Wait( 1L << IWnd->UserPort->mp_SigBit );
         continue;
         }

      CopyMem( (char *) m, (char *) &IMsg, 
               (long) sizeof( struct IntuiMessage )
             );

      ReplyMsg( (struct Message *) m );

      switch (IMsg.Class) 
         {
   	 case IDCMP_CLOSEWINDOW:
   	    running = ICloseWindow();
            break;
         }
      }

   return( running );
}


PRIVATE int HandleWindowInfo( void *structptr, int whichdisplay )
{
   int rval = 0;
   
   switch (whichdisplay)
      {
      case 0: // Screen data:
         rval = OpenIWindow( 16 );
         break;

      case 1: // Window data:
         rval = OpenIWindow( 25 );
         break;

      case 2: // Task data:
         rval = OpenIWindow( 13 );
         break;

      case 3: // Process data:
         rval = OpenIWindow( 28 );
         break;
      }
   
   if (rval < 0)
      {
      (void) Handle_Problem( "Couldn't open Information Window!", 
                             "Allocation Problem:", NULL 
                           );
      return( -1 );
      }

   DisplayStructure( structptr, whichdisplay );
      
   (void) HandleInfoIDCMP();

   return( 0 );
}

PRIVATE int CountWindows( struct Screen *scr )
{
   struct Window *w    = NULL;
   int            rval = 0;
   
   if (scr != NULL)
      w = scr->FirstWindow;
   else
      return( rval );

   while (w != NULL)
      {
      rval++;
      w = w->NextWindow;
      }

   return( rval );
}

PRIVATE int CountScreens( struct Screen *firstscreen )
{
   int rval = 0;
   
   while (firstscreen != NULL)
      {
      rval++;
      firstscreen = firstscreen->NextScreen;
      }

   return( rval );
}

PRIVATE int MakeScrWindowList( void )
{
   struct Screen *firstscr  = NULL;
   struct Screen *tempscr   = NULL;
   struct Screen *activescr = NULL;
   struct Window *activewnd = NULL;
   struct Screen *s         = NULL;

   ULONG          ilock       = 0L;
   int            i, numitems = 0;
   int            j, scrcount = 0;

   /* The following code works without the calls to LockIBase() &
   ** UnlockIBase() just fine.  They are here just in case:
   */

   ilock = LockIBase( 0 );

     firstscr  = IntuitionBase->FirstScreen;
     activescr = IntuitionBase->ActiveScreen;
     activewnd = IntuitionBase->ActiveWindow;
     scrcount  = CountScreens( firstscr );
     tempscr   = firstscr;     
     numitems  = scrcount;
          
     for (j = 0; j < scrcount; j++)
        {
        numitems += CountWindows( tempscr );
        tempscr   = tempscr->NextScreen;
        }

     s = firstscr;
     i = 1;

     do {
        struct Window *w = s->FirstWindow;

        if (s == activescr)
           sprintf( &NodeStrs[ i++ * 80 ], 
                    "%08LX+ %3u,%3u %4u,%4u %08LX 00000000 S: %-30.30s",
                    s, s->LeftEdge, s->TopEdge, s->Width, s->Height,
                    s->Flags, s->Title
                  );
        else
           sprintf( &NodeStrs[ i++ * 80 ], 
                    "%08LX  %3u,%3u %4u,%4u %08LX 00000000 S: %-30.30s",
                    s, s->LeftEdge, s->TopEdge, s->Width, s->Height,
                    s->Flags, s->Title
                  );
        do {

           if (w == activewnd)
              sprintf( &NodeStrs[ i++ * 80 ], 
                       "%08LX+ %3u,%3u %4u,%4u %08LX %08LX W: %-30.30s",
                       w, w->LeftEdge, w->TopEdge, w->Width, w->Height,
                       w->Flags, w->IDCMPFlags, w->Title
                     );
           else
              sprintf( &NodeStrs[ i++ * 80 ], 
                       "%08LX  %3u,%3u %4u,%4u %08LX %08LX W: %-30.30s",
                       w, w->LeftEdge, w->TopEdge, w->Width, w->Height,
                       w->Flags, w->IDCMPFlags, w->Title
                     );
           
           w = w->NextWindow;

           } while ((w != NULL) && (i <= MAXNODE));

        s = s->NextScreen;

        } while ((s != NULL) && (i <= MAXNODE));
        
   UnlockIBase( ilock );

   return( numitems );
}

PRIVATE BOOL IsScreen( ULONG address )
{
   struct Screen *scr   = NULL;

   ULONG          ilock = 0L;
   BOOL           rval  = FALSE;
    
   ilock = LockIBase( 0 );

     scr  = IntuitionBase->FirstScreen;

     while (scr != NULL)
        {
        if (scr == (struct Screen *) address)
           {
           rval = TRUE;
           break;
           }

        scr = scr->NextScreen;
        }
     
   UnlockIBase( ilock );

   return( rval );
}

PRIVATE struct Window *selected_w = NULL;
PRIVATE struct Screen *selected_s = NULL;

PRIVATE int SLVClicked( int itemnum )
{
   ULONG addr = 0L;
   
//#  ifdef DEBUG
//   fprintf( stderr, "%-80.80s\n", ScrNodes[ itemnum ].ln_Name );
//#  endif

   if (itemnum == 0)   
      {
      GT_SetGadgetAttrs( ScrGadgets[ ScrMore ], Wnd, NULL,
                         GA_Disabled, TRUE, TAG_DONE 
                       );

      GT_SetGadgetAttrs( ScrGadgets[ ScrClose ], Wnd, NULL,
                         GA_Disabled, TRUE, TAG_DONE 
                       );

      GT_SetGadgetAttrs( ScrGadgets[ ScrSelection ], Wnd, NULL,
                         GTTX_Text, NULL,
                         TAG_DONE
                       );

      return( (int) TRUE );
      }
   else
      {
      GT_SetGadgetAttrs( ScrGadgets[ ScrMore ], Wnd, NULL,
                         GA_Disabled, FALSE, TAG_DONE 
                       );

      GT_SetGadgetAttrs( ScrGadgets[ ScrClose ], Wnd, NULL,
                         GA_Disabled, FALSE, TAG_DONE 
                       );

      GT_SetGadgetAttrs( ScrGadgets[ ScrSelection ], Wnd, NULL,
                         GTTX_Text, ScrNodes[ itemnum ].ln_Name, 
                         TAG_DONE
                       );

      // Now get address from the item & determine if it's a screen or
      // window.  Then set selected_s or selected_w.
      (void) stch_l( ScrNodes[ itemnum ].ln_Name, (long *) &addr );
      
      if (IsScreen( addr ) == TRUE)
         {
         selected_s = (struct Screen *) addr;
         selected_w = NULL;
         }
      else
         {
         selected_s = NULL;
         selected_w = (struct Window *) addr;
         }
      }

   return( (int) TRUE );
}


PRIVATE int UpdateClicked( int dummy )
{
   int i;
   
   GT_SetGadgetAttrs( ScrGadgets[ ScrSelection ], Wnd, NULL,
                      GTTX_Text, NULL,
                      TAG_DONE
                    );

   for (i = 1; i <= MAXNODE; i++)
       NodeStrs[ i * 80 ] = '\0'; // Kill old ListView strings.

   (void) MakeScrWindowList();    // Remake ListView strings.

   GT_RefreshWindow( Wnd, NULL );

   return( (int) TRUE );
}

PRIVATE int MoreClicked( int dummy )
{
   if (selected_s != NULL)
      {
      // Show all of the Screen Information:
      (void) HandleWindowInfo( (void *) selected_s, 0 );
      }
   else if (selected_w != NULL)
      {
      // Show all of the Window Information:
      (void) HandleWindowInfo( (void *) selected_w, 1 );
      }
   else
      {
      // Some sort of error:
      (void) Handle_Problem( "MoreClicked() internal error condition!",
                             "SysScreens() Internal ERROR:", NULL
                           );
      }   

   return( (int) TRUE );
}

PRIVATE BOOL CheckWindow( struct Window *findwin )
{
  struct Window *win;
  struct Screen *scr;
  ULONG          lock = 0L;
  BOOL           ret  = FALSE;

  lock = LockIBase( NULL );

  scr = IntuitionBase->FirstScreen;
  
  while ((scr != NULL) && (ret == FALSE))
     {
     win = scr->FirstWindow;
     
     while (win != NULL)
        {
        if (win == findwin)
           {
           ret = TRUE;
           break;
           }

        win = win->NextWindow;
        }

     scr = scr->NextScreen;
     }

  UnlockIBase( lock );

  return( ret );
}

PRIVATE BOOL CheckScreen( struct Screen *findscr )
{
  struct Screen *scr;
  ULONG          lock = 0L;
  BOOL           ret  = FALSE;

  lock = LockIBase( NULL );

  scr = IntuitionBase->FirstScreen;

  while (scr != NULL)
     { 
     if (scr == findscr)
        {
        ret = TRUE;
        break;
        } 

     scr = scr->NextScreen;
     }

  UnlockIBase( lock );

  return( ret );
}

PUBLIC void CloseTheWindow( struct Window *wind )
{
   if (CheckWindow( wind ) == TRUE)
      {
      if ((wind->ReqCount != 0) && wind->FirstRequest)
         {
         while (wind->ReqCount != 0)
            EndRequest( wind->FirstRequest, wind );
         }

      if (wind->DMRequest != NULL)
         ClearDMRequest( wind );

      if (wind->Pointer != NULL)
         ClearPointer( wind );

      if (wind->MenuStrip != NULL)
         ClearMenuStrip( wind );

      CloseWindow( wind );
      }

   return;
}

PUBLIC void CloseTheScreen( struct Screen *scr )
{
  struct Window *win = scr->FirstWindow, *markwin;

  if (CheckScreen( scr ) == TRUE)
     {
     while (win != NULL)
        {
        markwin = win->NextWindow;
        CloseTheWindow( win );
        win     = markwin;
	}

     CloseScreen( scr );
     }

   return;
}

PRIVATE int CloseClicked( int dummy )
{
   // Check selected_s & selected_w for a non-NULL value
   char ErrMsg[256];
   
   if (selected_s != NULL)
      {
      sprintf( ErrMsg, "Are you SURE you want to close %08lx?", 
                        selected_s
             );

      if (SanityCheck( ErrMsg ) == TRUE)
         {
         if (selected_s == Scr)
            {
            (void) Handle_Problem( "Screen %08lx CANNOT be closed!",
                                   "User ERROR:", (int *) &Scr
                                 );

            return( (int) TRUE );
            }

         CloseTheScreen( selected_s );

         (void) MakeScrWindowList();
         GT_RefreshWindow( Wnd, NULL );
         }
      else
         return( (int) TRUE );
      }
   else if (selected_w != NULL)
      {
      sprintf( ErrMsg, "Are you SURE you want to close %08lx?", 
                        selected_w
             );

      if (SanityCheck( ErrMsg ) == TRUE)
         {
         if (selected_w == Wnd)
            {
            (void) Handle_Problem( "Window %08lx CANNOT be closed!",
                                   "User ERROR:", (int *) &Wnd
                                 );

            return( (int) TRUE );
            }

         CloseTheWindow( selected_w );

         (void) MakeScrWindowList();
         GT_RefreshWindow( Wnd, NULL );
         }
      else
         return( (int) TRUE );
      }
   else
      {
      // Some sort of error:
      (void) Handle_Problem( "CloseClicked() internal error condition!",
                             "SysScreens() Internal ERROR:", NULL
                           );

      return( (int) TRUE );
      }   

   return( (int) TRUE );
}

PRIVATE void CloseScrWindow( void )
{
   if (Wnd)
      {
      CloseWindow( Wnd );
      Wnd = NULL;
      }

   if (GList)
      {
      FreeGadgets( GList );
      GList = NULL;
      }

   if (TFont)
      {
      CloseFont( TFont );
      TFont = NULL;
      }

   return;
}

PRIVATE int ScrCloseWindow( void )
{
   CloseScrWindow();
   return( (int) FALSE );
}

PRIVATE int CancelClicked( int dummy )
{
   return( ScrCloseWindow() );
}

PRIVATE int OpenScrWindow( void )
{
   struct NewGadget  ng;
   struct Gadget    *g;
   UWORD             lc, tc;
   UWORD             wleft = WLeft, wtop = WTop, ww, wh;

   ComputeFont( Scr, Font, &CFont, WWidth, WHeight );

   ww = ComputeX( CFont.FontX, WWidth );
   wh = ComputeY( CFont.FontY, WHeight );

   if ((wleft + ww + CFont.OffX + Scr->WBorRight) > Scr->Width)
      wleft = Scr->Width - ww;

   if ((wtop + wh + CFont.OffY + Scr->WBorBottom) > Scr->Height)
      wtop = Scr->Height - wh;

   if ( !(TFont = OpenDiskFont( Font )))
      return( -5 );

   if ( !(g = CreateContext( &GList )))
      return( -1 );

   for (lc = 0, tc = 0; lc < SCR_CNT; lc++)
      {
      CopyMem( (char *) &ScrNGad[ lc ], (char *) &ng, 
               (long) sizeof( struct NewGadget )
             );

      ng.ng_VisualInfo = VisualInfo;
      ng.ng_TextAttr   = Font;
      ng.ng_LeftEdge   = CFont.OffX + ComputeX( CFont.FontX, 
                                                ng.ng_LeftEdge 
                                              );

      ng.ng_TopEdge    = CFont.OffY + ComputeY( CFont.FontY, 
                                                ng.ng_TopEdge 
                                              );

      ng.ng_Width      = ComputeX( CFont.FontX, ng.ng_Width  );
      ng.ng_Height     = ComputeY( CFont.FontY, ng.ng_Height );

      ScrGadgets[lc] = g = CreateGadgetA( (ULONG) ScrGTypes[lc], 
                            g, 
                            &ng, 
                            (struct TagItem *) &ScrGTags[tc] );

      while (ScrGTags[tc])
         tc += 2;

      tc++;
      if (NOT g)
         return( -2 );
      }

   if ( !(Wnd = OpenWindowTags( NULL,

                 WA_Left,        wleft,
                 WA_Top,         wtop,
                 WA_Width,       ww + CFont.OffX + Scr->WBorRight,
                 WA_Height,      wh + CFont.OffY + Scr->WBorBottom,
                 WA_IDCMP,       LISTVIEWIDCMP | BUTTONIDCMP 
                   | IDCMP_CLOSEWINDOW | IDCMP_REFRESHWINDOW,

                 WA_Flags,       WFLG_DRAGBAR | WFLG_DEPTHGADGET 
                   | WFLG_CLOSEGADGET | WFLG_SMART_REFRESH | WFLG_ACTIVATE 
                   | WFLG_RMBTRAP,
                 
                 WA_Gadgets,     GList,
                 WA_Title,       WTitle,
                 WA_ScreenTitle, ScrTitle,
                 TAG_DONE ))
      )
      return( -4 );

   GT_RefreshWindow( Wnd, NULL );

   return( 0 );
}

PRIVATE int HandleScrIDCMP( void )
{
   struct IntuiMessage *m;
   int                 (*func)( int );
   BOOL                running = TRUE;

   while (running == TRUE)
      {
      if ((m = GT_GetIMsg( Wnd->UserPort )) == NULL)
         {
         (void) Wait( 1L << Wnd->UserPort->mp_SigBit );
         continue;
         }

      CopyMem( (char *) m, (char *) &IMsg, 
               (long) sizeof( struct IntuiMessage ) 
             );

      GT_ReplyIMsg( m );

      switch (IMsg.Class)
         {
         case IDCMP_REFRESHWINDOW:
            GT_BeginRefresh( Wnd );
            GT_EndRefresh( Wnd, TRUE );
            break;

         case IDCMP_CLOSEWINDOW:
            running = ScrCloseWindow();
            break;

         case IDCMP_GADGETUP:
            func    = (void *) ((struct Gadget *) IMsg.IAddress)->UserData;
            running = func( (int) IMsg.Code );
            break;
         }
      }

   return( running );
}

PUBLIC int HandleScreenLV( void )
{
   int i = 0;
   
   ScrNode.ln_Succ = (struct Node *) ScrList.mlh_Tail;
   ScrNode.ln_Pred = (struct Node *) ScrList.mlh_Head;
   ScrNode.ln_Type = 0;
   ScrNode.ln_Pri  = 100;
   ScrNode.ln_Name = "Address     Pos     Size    Flags    IDCMP       Title";

   ScrNodes[0]     = ScrNode;
       
   if (SetupSystemList( &OpenScrWindow ) < 0)
      {
      (void) Handle_Problem( "Couldn't open a System ListViewer!", 
                             "Allocation Problem:", NULL 
                           );
      return( -1 );
      }

   SetNotifyWindow( Wnd ); // For Handle_Problem().
  
   // ScrNodes[0] is already set up:

   for (i = 1; i <= MAXNODE; i++)
       {
       ScrNodes[i].ln_Name = &NodeStrs[ i * 80 ];
       ScrNodes[i].ln_Pri  = MAXNODE - i;
       }     

   NewList( (struct List *) &ScrList );

   for (i = 0; i < MAXNODE; i++)
      Enqueue( (struct List *) &ScrList, &ScrNodes[i] );

   (void) MakeScrWindowList();

   ModifyListView( ScrGadgets[ ScrLV ], Wnd, 
                   (struct List *) &ScrList, NULL
                 );

   GT_RefreshWindow( Wnd, NULL );

   (void) HandleScrIDCMP();
   
   ShutdownSystemList();
   return( 0 );
}

#ifdef DEBUG

PUBLIC int main( void )
{
   return( HandleScreenLV() );
}

#endif

/* --------------------- END of SysScreens.c file! -------------------- */
