#include <debug.h>
#include <intuition/intuition.h>
#include <graphics/text.h>
#include "mpp.h"
#include <intuition/intuitionbase.h>
#include <exec/execbase.h>
#include <clib/extras_protos.h>
#include <stdio.h>
#include <math.h>
#include <dos/dosextens.h>
#include <extras/layoutgt.h>
#include "mppexterns.h"

#define LGD_LIST 0
#define LGD_OK      1
#define LGD_CANCEL  2

struct ListRequester
{
  struct Window     *lr_Window;
  APTR               lr_VisualInfo;
  struct LG_Control *lr_GadControl;
  struct List       *lr_List;
  BOOL   lr_RetVal;
};

void   CreateDefaultModeList(struct List *List);
struct ModeNode *CreateModeNode(ULONG ID);

struct LG_Control *LayoutListGads(struct ListRequester *LReq);

//void FreeDefaultModeList(struct List *List);


/*
struct Gadget  *MakeListGadget  (struct List *List);
void            RemListGadget    (void);
*/

BOOL SelectName(struct DefaultNode *DN)
{
  STRPTR name,namework;
  struct List namelist;
  struct Node *namenode;
  LONG l,
       ok=TRUE,
       item;
  BOOL rv=FALSE;
  ULONG type;

  
  if(DN)
  {
    NewList(&namelist);
    if(DN->Type<4)
    {
      switch(DN->Type)
      {
        case PL_PROGRAMNAMES:
          {
            struct Task   *task;
            struct List *tasklist;
            struct Node *execnode;
            UBYTE cliname[256];
            
            // Create a list of program names
            Disable();
            tasklist=&SysBase->TaskReady;
            for(l=0;l<2;l++)
            {
              task=(struct Task *)tasklist[l].lh_Head;
  
              while(task->tc_Node.ln_Succ)
              {
                execnode=(struct Node *)task;
                name=execnode->ln_Name;
                type=execnode->ln_Type;
                
                if(type==NT_PROCESS)
                {
                  struct Process *proc;
                  struct CommandLineInterface *cli;
                  
                  //kprintf("Process ");
                  
                  proc=(struct Process *)task;
                  
                  if(proc->pr_CLI)
                  {
                    cli=(struct CommandLineInterface *)BADDR(proc->pr_CLI);
                    namework=(STRPTR)BADDR(cli->cli_CommandName);
                    if(namework[0])
                    {
                      strncpy(cliname,&namework[1],namework[0]);
                      cliname[namework[0]]=0;
                      name=cliname;
                    }
                  }
                }
                //else
                  //kprintf("Task    ");
                  
                //kprintf("%s %ld\n",name,type);  
                
                if(name)
                {
                  if(namenode=AllocNameNode(name))
                  {
                    namenode->ln_Type=type;
                    namenode->ln_Pri=execnode->ln_Pri;
                    EnqueueName(&namelist,namenode);
                    
                  }
                  //else
                  //  ok=FALSE;
                }
                task=(struct Task *)task->tc_Node.ln_Succ;
              }
            }
            Enable();
          }
          break;
        case PL_SCREENNAMES:          
          {
            struct Screen *scr;
            ULONG  lock;
            // Create a list of screens
            lock=LockIBase(0);
            scr=IntuitionBase->FirstScreen;
            while(scr && ok)
            {
              if(scr->Title)
              {
                if(namenode=AllocNameNode(scr->Title))
                  EnqueueName(&namelist,namenode);
                else
                  ok=FALSE;
              }
              scr=scr->NextScreen;
            }
            UnlockIBase(lock);
          }
          break;
        case PL_PUBLICSCREENS:       
          {   
            struct Node *n;
            struct List *list;
            
            // Create a list of public screens
            list=LockPubScreenList();
            n=list->lh_Head;
            while(n->ln_Succ && ok)
            {
              if(n->ln_Name)
              {
                if(namenode=AllocNameNode(n->ln_Name))
                  EnqueueName(&namelist,namenode);
                else
                  ok=FALSE;
              }
              n=n->ln_Succ;
            }
            UnlockPubScreenList();
          }
          break;
        case PL_SCREENMODES:
          CreateDefaultModeList(&namelist);
          break;
      }
      
      if((item=SelectReq(&namelist,GetString(MSG_SELWIN_PROGRAMS + DN->Type))) >=0)
      {
        STRPTR dummy;
        
        namenode=namelist.lh_Head;
        while(item)
        {
          namenode=namenode->ln_Succ;
          item--;
        }
        
        dummy=DN->Def_Node.ln_Name;  /* The old name will be freed with FreeNameNodes() */
        DN->Def_Node.ln_Name=namenode->ln_Name;
        namenode->ln_Name=dummy;
        if(DN->Type==PL_SCREENMODES)
        {
          DN->OrigDisplayID=((struct ModeNode *)namenode)->mn_DisplayID;
        }
        rv=TRUE;
      }
      FreeNameNodes(&namelist);
    }
  }
  return(rv);
}

struct Node *AllocNameNode(STRPTR Name)
{
  struct Node *n;
  LONG l;
  
  if(n=AllocVec(sizeof(struct Node),MEMF_PUBLIC|MEMF_NO_EXPUNGE|MEMF_CLEAR))
  {
    n->ln_Pri=0;
    l=strlen(Name);
    if(n->ln_Name=AllocVec(l+1,MEMF_PUBLIC|MEMF_NO_EXPUNGE))
    {
      strncpy(n->ln_Name,Name,l);
      n->ln_Name[l]=0;
      return(n);
    }
    FreeVec(n);
  }
  return(0);
}

void FreeNameNodes(struct List *List)
{
  struct Node *n;
  
  while(n=RemHead(List))
  {
    FreeVec(n->ln_Name);
    FreeVec(n);
  }
}

void CreateDefaultModeList(struct List *List)
{
  struct DisplayInfo di;
  struct ModeNode    *mn;
  ULONG previd=MONITOR_ID_MASK,id;
  
  id=NextDisplayInfo(INVALID_ID);

  while(id!=INVALID_ID)
  {
    if(previd != (id & MONITOR_ID_MASK))
    { // create an entry for all screen modes.
      previd=(id & MONITOR_ID_MASK);
      if(mn=CreateModeNode(id | ALL_MODES))
        EnqueueName(List,(struct Node *)mn);      
    } 
    
    if(GetDisplayInfoData(0,(UBYTE *)&di,sizeof(di),DTAG_DISP,id))
    //if(!(di.PropertyFlags & SPECIAL_FLAGS)) // no HAM, EHB, 2PF etc.
    if(!(di.PropertyFlags & DIPF_IS_PF2PRI)) // no PF2 etc.
    {
      if(mn=CreateModeNode(id))
      {
        EnqueueName(List,(struct Node *)mn);
      }
    }
    id=NextDisplayInfo(id);
  }
}

struct ModeNode *CreateModeNode(ULONG ID)
{
  struct ModeNode *mn;
  
  if(mn=AllocVec(sizeof(struct ModeNode),MEMF_PUBLIC|MEMF_CLEAR))
  {
    if(mn->mn_Node.ln_Name=GetModeName(ID))
    {
      mn->mn_DisplayID=ID;
      return(mn);
    }
    FreeVec(mn);
  }
  return(0);
}

/********************************************************/
/********************************************************/

WORD ListWinLeft,ListWinTop,ListWinWidth,ListWinHeight;
BOOL ListFirstTime=TRUE;
//APTR ListVI;
//ULONG ListGadCount;
//struct Window *ListWin;
//struct Gadget *ListContext,*ListLV;

/* Opens the list requester */
LONG SelectReq(struct List *List, STRPTR WinTitle)
{
  LONG nodes;
  struct Requester *req;
  LONG rv=-1;
  struct IntuiMessage *imsg;
  BOOL ok=TRUE;
  WORD x1,y1,x2,y2;
  LONG PrevSeconds =0,
       PrevMicros  =0,
       PrevCode    =-1;
  struct ListRequester listreq;
  
  if(ListFirstTime)
  {
    ListWinWidth=   Win->Width/2;
    ListWinHeight=  Win->Height-16;
    ListWinLeft=    Win->LeftEdge+Win->Width/2-ListWinWidth/2;
    ListWinTop=     Win->TopEdge+8;
    ListWinWidth=   max(ListWinWidth,50);
    ListWinHeight=  max(ListWinHeight,50);
    ListFirstTime=FALSE;
  }
  
  req=Busy(Win);
  if(listreq.lr_Window=OpenWindowTags(0,
                              WA_Left,          ListWinLeft,
                              WA_Top,           ListWinTop,
                              WA_Width,         ListWinWidth,
                              WA_Height,        ListWinHeight,
                              WA_MinWidth,      50,
                              WA_MinHeight,     50,
                              WA_MaxWidth,      -1,
                              WA_MaxHeight,     -1,
                              WA_Title,         WinTitle,
                              WA_DragBar,       TRUE,
                              WA_SizeGadget,    TRUE,
                              WA_SizeBBottom,   TRUE,
                              WA_DepthGadget,   TRUE,
                              WA_SimpleRefresh, TRUE    ,
                              WA_CloseGadget,   TRUE,
                              WA_CustomScreen,  Scr,
                              WA_Activate,      TRUE,
                              WA_IDCMP,         IDCMP_REFRESHWINDOW |
                                                IDCMP_CLOSEWINDOW   |
                                                IDCMP_NEWSIZE       |
                                                IDCMP_VANILLAKEY    |
                                                IDCMP_RAWKEY        |
                                                LISTVIEWIDCMP,
                              TAG_DONE))
  {
    x1=listreq.lr_Window->BorderLeft;
    y1=listreq.lr_Window->BorderTop;
    listreq.lr_List=List;
    if(listreq.lr_VisualInfo=GetVisualInfo(listreq.lr_Window->WScreen,0))
    {
      if(LayoutListGads(&listreq))
      {
        LG_AddGadgets(listreq.lr_Window,listreq.lr_GadControl);
        nodes=CountNodes(listreq.lr_List);
        while(ok)
        {
          WaitPort(listreq.lr_Window->UserPort);
          while(imsg=GT_GetIMsg(listreq.lr_Window->UserPort))
          {
            switch(imsg->Class)
            {
              case IDCMP_REFRESHWINDOW:
                GT_BeginRefresh(listreq.lr_Window);
                GT_EndRefresh(listreq.lr_Window,TRUE);
                break;
              case IDCMP_CLOSEWINDOW:
                ok=FALSE;
                rv=-1;
                break;
              case IDCMP_GADGETUP:
                if(DoubleClick(PrevSeconds,PrevMicros,imsg->Seconds,imsg->Micros) 
                   && PrevCode==imsg->Code)
                {
                  ok=FALSE;
                  rv=imsg->Code;
                }
                else
                {
                  PrevSeconds=imsg->Seconds;
                  PrevMicros =imsg->Micros;
                  PrevCode   =imsg->Code;
                }
                break;
              case IDCMP_NEWSIZE:
                x2=listreq.lr_Window->Width -listreq.lr_Window->BorderRight-1;
                y2=listreq.lr_Window->Height-listreq.lr_Window->BorderBottom-1;
                
                LG_FreeGadgets(listreq.lr_GadControl);
                if(x2>x1 && y2>y1)
                  EraseRect(listreq.lr_Window->RPort,x1,y1,x2,y2);
                RefreshWindowFrame(listreq.lr_Window);
                if(!LayoutListGads(&listreq))
                { 
                  ok=FALSE;
                  rv=-1;
                }
                else
                {
                  LG_AddGadgets(listreq.lr_Window,listreq.lr_GadControl);
                  ListWinWidth=   listreq.lr_Window->Width;
                  ListWinHeight=  listreq.lr_Window->Height;
                  ListWinLeft=    listreq.lr_Window->LeftEdge;
                  ListWinTop=     listreq.lr_Window->TopEdge;
                }
                break;
              case IDCMP_VANILLAKEY:
                switch(imsg->Code)
                {
                  case '':
                    ok=FALSE;
                    rv=-1;
                    break;
                  case 13:
                  case ' ':
                    ok=FALSE;
                    rv=PrevCode;
                    break;
                  
                }
                break; 
              case IDCMP_RAWKEY:
                switch(imsg->Code)
                {
                  case CURSORUP:
                    PrevCode--;
                    if(PrevCode<0)
                      PrevCode=nodes-1;
                    break;
                  case CURSORDOWN:
                    PrevCode++;
                    if(PrevCode>=nodes)
                      PrevCode=0;
                    break;
                }
                LG_SetGadgetAttrs(listreq.lr_GadControl,LGD_LIST,
                                                    GTLV_Selected       ,PrevCode,
                                                    GTLV_MakeVisible    ,PrevCode,
                                                    TAG_SKIP            ,( V39 ? 1:0),
                                                    GTLV_Top            ,PrevCode,
                                                    TAG_DONE);
                break;
            }
            GT_ReplyIMsg(imsg);
          }
        }
        LG_FreeGadgets(listreq.lr_GadControl);
      }
      FreeVisualInfo(listreq.lr_VisualInfo);
    }
    CloseWindow(listreq.lr_Window);
  }
  NotBusy(Win,req);
  return(rv);
}




struct LG_Control *LayoutListGads(struct ListRequester *LReq)
{
  WORD width,height;
  struct LG_Control *lr_control=0;
  //STRPTR ok,cancel;

  if(LReq)
  {
    if(LReq->lr_VisualInfo && LReq->lr_Window)
    {
//      rp=LReq->lr_Window->RPort; 
 
      width =LReq->lr_Window->Width  - LReq->lr_Window->BorderLeft- LReq->lr_Window->BorderRight  - 8;
      height=LReq->lr_Window->Height - LReq->lr_Window->BorderTop - LReq->lr_Window->BorderBottom - 8;
 
      lr_control=LG_CreateGadgets( LG_VisualInfo        ,LReq->lr_VisualInfo,
                                   LG_UseWindowOffsets  ,LReq->lr_Window,
                                   LG_EraseRemoved      ,FALSE,
                                   LG_OffsetX           ,4,
                                   LG_OffsetY           ,4,
                                   LG_TextAttr          ,TAttr,
                                   
                                   /* List Gadget */
                                   LG_GadgetKind        ,LISTVIEW_KIND,
                                   LG_GadgetID          ,LGD_LIST,
                                   LG_Width             ,width,
                                   LG_Height            ,height,
                                   LG_GadgetTags        ,2,
                                   GTLV_Labels          ,LReq->lr_List,
                                   GTLV_ShowSelected    ,0,
                                   LG_CreateGadget      ,0,
                                 
                                   TAG_DONE);
    }
  }
  LReq->lr_GadControl=lr_control;
  return(lr_control);
}                                 



/*

struct Gadget *MakeListGadget(struct List *List)
{
  struct Gadget *gad;
  struct NewGadget listng={0};
 
  listng.ng_VisualInfo=ListVI;
  listng.ng_TextAttr  =TAttr;
  listng.ng_LeftEdge  =listreq.lr_Window->BorderLeft  +4;
  listng.ng_TopEdge   =listreq.lr_Window->BorderTop   +4;
  listng.ng_Width     =listreq.lr_Window->Width-listreq.lr_Window->BorderLeft-listreq.lr_Window->BorderRight-8;
  listng.ng_Height    =listreq.lr_Window->Height-listreq.lr_Window->BorderTop-listreq.lr_Window->BorderBottom-8;
  
  gad=CreateContext(&ListContext);

  ListLV=gad=CreateGadget(LISTVIEW_KIND, gad, &listng,
                          GTLV_Labels           ,List,
                          GTLV_ShowSelected     ,0,
                          TAG_DONE);
  if(!gad)
  {
    FreeGadgets(ListContext);
    ListContext=0;
    return(0);
  }
  else
  {
    struct Gadget *cgad;
    
    ListGadCount=0;
    cgad=ListContext;
    
    while(cgad)
    {
      ListGadCount++;
      cgad=cgad->NextGadget;
    }
    
    AddGList(listreq.lr_Window,ListContext,-1,-1,0);
    RefreshGList(ListContext,listreq.lr_Window,0,ListGadCount);
    GT_RefreshWindow(listreq.lr_Window,NULL);
  }
  return(gad);
}

void RemListGadget(void)
{
  if(ListContext)
  {
    RemoveGList(listreq.lr_Window,ListContext,ListGadCount);
    FreeGadgets(ListContext);
    ListContext=0;
  }
}

*/
