#include "MP.h"
//#include "/modepro.h"
#include <graphics/videocontrol.h>
#include <graphics/displayinfo.h>
#include "patchdata.h"

//#define DEBUG
#include <debug.h>

void WaitForReply(struct Message *Msg);

ULONG Colors[]={1<<16|0,~0,0,0,0};

//#define ADD_DEBUG_CODE



#define HAM_EHB_DP_KEY (HAM_KEY | 0x400 | EXTRAHALFBRITE_KEY)
//                                DualPF
//BOOL MPSem->Debug=FALSE;



/* kprintf

#ifdef ADD_DEBUG_CODE
      if(MPSem->Debug)
      {
      }
#endif

*/

#define AllocOpenNode(on)  (on ? on: AllocMem(sizeof(struct OpenNode),MEMF_CLEAR|MEMF_PUBLIC))
  
void CatchDNode(ULONG Dest, UBYTE *Name, struct DefaultNode *SrcNode);

extern LONG InPatch;
extern UBYTE   ModePro[];
extern ULONG CenterAll;
extern CxObj  *Broker;
extern struct MsgPort *BrokerPort;
extern BOOL   V39;
extern BYTE   PublicSignal;
extern struct MPSem *MPSem;
extern struct Process  *MPTask;
extern struct MsgPort *CatchPort;
extern struct Screen ASM *(*OldOpenScreen)(REG __a0 struct NewScreen *,
                                           REG __a6 struct IntuitionBase *);
extern struct Screen ASM *(*OldOpenScreenTagList)(REG __a0 struct ExtNewScreen *ns,
                                                  REG __a1 struct TagItem *taglist,
                                                  REG __a6 struct IntuitionBase * );
extern BOOL ASM (*OldCloseScreen)   (REG __a0 struct Screen *,REG __a6 struct IntuitionBase *);
extern LONG ASM (*OldCloseWorkBench)(REG __a6 struct IntuitionBase *lib);

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

struct Screen ASM __saveds  *NewOpenScreen(REG __a0 struct ExtNewScreen *ns,
                                           REG __a6 struct IntuitionBase *IBase)
{
  struct TagItem *taglist;
  struct Screen *scr;
  
  InPatch++;
  taglist=0;

  if(ns)
  {
    if(ns->Type & NS_EXTENDED)
      taglist=ns->Extension;
  }
  
  scr=NewOpenScreenTagList(ns,taglist,IBase );
  InPatch--;
  return(scr);
}


struct DefaultNode CenterAllNode={0};
      
struct Screen ASM __saveds  *NewOpenScreenTagList(REG __a0 struct ExtNewScreen *ns,
                                                  REG __a1 struct TagItem *TagList,
                                                  REG __a6 struct IntuitionBase *IBase)
{
  struct Screen *RetScreen;
  struct PatchData *pd;
  struct TagItem fonttags[]= { TA_DeviceDPI , (1<<16) | 1 , TAG_DONE,0 };

/**** END VARS ****/

  InPatch++;

  ObtainSemaphoreShared(&MPSem->ListSem); 
//  ObtainSemaphore(&MPSem->NodeSem); 

  if(!MPSem->Enabled)
  {
    RetScreen=OldOpenScreenTagList(ns,TagList,IBase);
    ReleaseSemaphore(&MPSem->ListSem);
//    ReleaseSemaphore(&MPSem->NodeSem);
    InPatch--;
    return(RetScreen);
  }
  
  if(pd=AllocVec(sizeof(struct PatchData),MEMF_CLEAR | MEMF_PUBLIC))
  {
    
    pd->NullPens[0]=(~0);
    pd->Promote=TRUE;
    
#ifdef ADD_DEBUG_CODE
    if(MPSem->Debug)
    {
      KP("pd=%8lx\n",pd);
      
      KP("\n\n%s--------------------------------\nOpenScreenX()\n",FindTask(0)->tc_Node.ln_Name);
      KP("  IntuitionBase: %8lx\n",IBase);
      if(ns)
      {
        KP("  NewScreen    : %8lx\n",ns);
        KP("    LeftEdge=%ld TopEdge=%ld\n    Width=%ld Height=%ld\n    Depth=%ld\n    dpen=%ld bpen=%ld\n    vm=%8lx type=%ld\n    font=%8lx\n",
          ns->LeftEdge, ns->TopEdge, ns->Width, ns->Height, ns->Depth,
          ns->DetailPen, ns->BlockPen, ns->ViewModes, ns->Type, ns->Font);
        if(ns->DefaultTitle)
          KP("    defaulttitle=%s\n", ns->DefaultTitle);
        KP("    gadgets=%8lx  bitmap=%8lx\n",
          ns->Gadgets, ns->CustomBitMap);
        if(ns->Type & NS_EXTENDED)
          KP("    * is NS_EXTENDED\n");
      }  
      if(TagList)
      {
        KP("  TagList:\n");
        PrintTags(TagList);
      }
    }
#endif
    
    /* Now that we've got the semaphore all globals are mine */
    /* initialize everything */

    /* 0'ed by MEMF_CLEAR
    pd->DNode=NULL;  
    pd->EHB_HAM=0;
    pd->TagNumber=0;
    pd->ScrTitle=NULL;
    pd->OpenNode=NULL;
    pd->HasCustomBM=pd->Changed=pd->ModeChanged=pd->SetLook3D=pd->OverscanType=pd->Interleave=0L;

    pd->SetDepth=FALSE;
    pd->IsWorkbench=0;  
    */
    pd->Depth=1;
    pd->Width=pd->Height=pd->AutoScroll=pd->ModeID=-1;
    pd->ScreenPens=pd->NullPens;
    pd->TaskName=FindTask(0)->tc_Node.ln_Name;
  
    if(GetProgramName(pd->CLI_Name,40)) /* Get cli program's name */
      if(pd->CLI_Name[0]!=0)            /* make sure pd->CLI_Name contains something */
        pd->TaskName=pd->CLI_Name;
    
    /* Initialization Done */
  
    /**** Extract screen info from ns and TagList ****/  
    if(ns)                     
    {
      pd->StoredFont  =ns->Font;
      pd->Width       =ns->Width;
      pd->Height      =ns->Height;
      pd->ModeID      =ns->ViewModes;
      pd->Depth       =ns->Depth;
      pd->ScrTitle    =ns->DefaultTitle;
      pd->HasCustomBM =ns->Type & CUSTOMBITMAP;
      pd->IsWorkbench =(ns->Type & SCREENTYPE)==WBENCHSCREEN;
    }
  
    if(TagList)
    {
      pd->HasCustomBM          =GetTagData(SA_BitMap,    pd->HasCustomBM,       TagList);
      pd->Width                =GetTagData(SA_Width,     pd->Width,             TagList);
      pd->Height               =GetTagData(SA_Height,    pd->Height,            TagList);
      pd->AutoScroll           =GetTagData(SA_AutoScroll,pd->AutoScroll,        TagList);
      pd->OverscanType         =GetTagData(SA_Overscan,  pd->OverscanType,      TagList);
      pd->ModeID               =GetTagData(SA_DisplayID, pd->ModeID,            TagList);
      pd->Depth                =GetTagData(SA_Depth,     pd->Depth,             TagList);
      pd->ScrTitle    =(UBYTE *)GetTagData(SA_Title,    (ULONG)pd->ScrTitle,    TagList);
      pd->IsWorkbench         =(GetTagData(SA_Type,      pd->IsWorkbench,       TagList) & SCREENTYPE)==WBENCHSCREEN;
      pd->Interleave           =GetTagData(SA_Interleaved,pd->Interleave,       TagList);
      
      if(pd->Tag=FindTagItem(SA_Overscan,TagList))
        if(!FindTagItem(SA_DClip,TagList))
          pd->OverscanType=pd->Tag->ti_Data;
      
      if(pd->Tag=FindTagItem(SA_Pens,TagList))
      {
        pd->ScreenPens=(UWORD *)(pd->Tag->ti_Data);
      }
    }
  
#ifdef ADD_DEBUG_CODE
    if(MPSem->Debug)
    {
      if(pd->IsWorkbench)
        KP("** This is the Workbench screen, special restrictions apply **\n");
    }
#endif
  
    if(GetDisplayInfoData(0,(UBYTE *)&pd->DispInfo,sizeof(pd->DispInfo),DTAG_DISP,pd->ModeID))
    {
      pd->EHB_HAM=pd->DispInfo.PropertyFlags & (DIPF_IS_DUALPF | DIPF_IS_HAM | 
                                       DIPF_IS_PF2PRI | DIPF_IS_EXTRAHALFBRITE);
    }

    if(!pd->ScrTitle)
    {
      pd->ScrTitle=GetString(MSG_ITEM_NO_NAME); /* Just in case ther isn't a pd->ScrTitle */
    }

    ObtainSemaphore(&MPSem->NodeSem);    

    if(pd->DNode=(struct DefaultNode *)GetTagData(SA_ModeProNode, (ULONG)MatchDNode(pd->TaskName, pd->ScrTitle, pd->ModeID) ,TagList))
    {
      pd->DNode=DupDNode(pd->DNode); // Duplicate the node so we can release the node semaphore 
    }
    
    ReleaseSemaphore(&MPSem->NodeSem);    

/*  
    if(pd->DNode=(struct DefaultNode *)GetTagData(SA_ModeProNode, (ULONG)MatchDNode(pd->TaskName, pd->ScrTitle, pd->ModeID) ,TagList))
    {
      pd->DNode=DupDNode(pd->DNode); // Duplicate the node so we can release the node semaphore 
      ReleaseSemaphore(&MPSem->NodeSem);    
    }
    else
*/
    if(!pd->DNode)
    {
//      ReleaseSemaphore(&MPSem->NodeSem);     /*********************************/
      
      if(!pd->IsWorkbench)
      {
        UBYTE *modename;
        STRPTR dname="";
        
        if(MPSem->CatchScreens && MPSem->Enabled)
        {
          if(modename=GetModeName(pd->ModeID));
          {
            //if(EZReq(0,0,ModePro,GetString(MSG_NEW_SCREEN_1),GetString(MSG_NEW_SCREEN_1_BUTTONS),pd->ScrTitle,pd->TaskName,(ULONG)modename))
            {
              ULONG listnum=1,button;
            
              if(button=EZReq(0,0,ModePro,GetString(MSG_NEW_SCREEN_2),GetString(MSG_NEW_SCREEN_2_BUTTONS),(ULONG)pd->ScrTitle,(ULONG)pd->TaskName,(ULONG)modename))
              {
                switch(button)
                {
                  case 1:
                    dname=pd->ScrTitle;
                    listnum=1;
                    break;
                  case 2:
                    dname=pd->TaskName;
                    listnum=0;
                    break;
                  case 3:
                    dname=modename;
                    listnum=2;
                    break;
                }
                
                if(pd->DNode=AllocDefaultNode(dname))
                {
                  LONG l;
                  
                  pd->DNode->Type         =listnum;
                  pd->DNode->Width        =pd->Width;
                  pd->DNode->Height       =pd->Height;
                  pd->DNode->AutoScroll   =pd->AutoScroll;
                  pd->DNode->ModeSelect   =0;
                  pd->DNode->ModeID       =pd->DNode->OrigDisplayID   =pd->ModeID;
                  pd->DNode->OverscanType =pd->OverscanType;
                  pd->DNode->Look3D       =pd->SetLook3D;
                  pd->DNode->Flags        =0;//DNF_NODELETE;  /* So MPP can't delete me */
                  pd->DNode->Depth        =pd->Depth;
                  
                  for(l=0;l<DRIPENS && pd->ScreenPens[l]!=(~0);l++)
                    pd->DNode->Pens[l]=pd->ScreenPens[l];
                  
                  pd->DNode=ForceEdit(pd->DNode);
                }
              }
            }
            FreeVec(modename);
          }
        }
      }
    }

    if(!pd->DNode && MPSem->CenterAll)
    {
      //pd->DNode=&CenterAllNode;
      CenterAllNode.CenterFlags=MPSem->CenterAll;
      pd->DNode=DupDNode(&CenterAllNode);
    } 
  
    if(pd->DNode)
    {
      if(pd->DNode->Flags & DNF_NEVER_PROMOTE)
      {
        FreeDNode(pd->DNode);
        pd->DNode=0;
      }
      else
      if(!(pd->OpenNode=AllocVec(sizeof(struct OpenNode),MEMF_CLEAR|MEMF_PUBLIC)))
      {
        FreeDNode(pd->DNode);
        pd->DNode=0;
      }
    }
      
#ifdef ADD_DEBUG_CODE
    if(MPSem->Debug)
    {
      if(pd->DNode)
        PrintDefNode(pd->DNode);
    }
#endif
    
    if(!pd->DNode)
    {
      RetScreen=OldOpenScreenTagList(ns,TagList,IBase);
      FreeVec(pd);
      ReleaseSemaphore(&MPSem->ListSem);
      InPatch--;
      return(RetScreen);
    }
  
    if(!pd->IsWorkbench)
    {
      switch(pd->DNode->ModeSelect)
      {
        case 0:
          break;
        case 1:
#ifdef ADD_DEBUG_CODE
        if(MPSem->Debug)
        {
          Delay(50*2);
          KP("Promoting Monitor\n");
        }
#endif  
          if(pd->ModeID > -1)
          {
            if(V39)
            {
              pd->ModeID=BestModeID(BIDTAG_SourceID       ,pd->ModeID,
                                BIDTAG_MonitorID      ,pd->DNode->ModeID & MONITOR_ID_MASK,
                                BIDTAG_Depth          ,pd->Depth,
                                BIDTAG_DIPFMustHave   ,pd->EHB_HAM,
                                TAG_SKIP              ,(pd->Width==-1 ? 1:0),
                                BIDTAG_DesiredWidth   ,pd->Width,
                                TAG_SKIP              ,(pd->Height==-1 ? 1:0),
                                BIDTAG_DesiredHeight  ,pd->Height,
                                TAG_DONE);
            }
            else
            {
              pd->ModeID= (pd->DNode->ModeID & MONITOR_ID_MASK) | (pd->ModeID & (~MONITOR_ID_MASK));
            }
            if(pd->ModeID==INVALID_ID) 
               pd->ModeID=pd->DNode->ModeID;
                
            pd->ModeChanged=TRUE;
          }
          break;
        case 2:
#ifdef ADD_DEBUG_CODE
        if(MPSem->Debug)
        {
          Delay(50*2);
          KP("Promoting ScreenMode\n");
        }
#endif  
          pd->ModeID        =pd->DNode->ModeID/* | pd->EHB_HAM*/;
          pd->OverscanType  =pd->DNode->OverscanType;
          pd->Width         =pd->DNode->Width;
          pd->Height        =pd->DNode->Height;
      
          if(pd->DNode->Flags & DEPTH)
          {
            pd->Depth=pd->DNode->Depth;
            pd->SetDepth=TRUE;
          }
          pd->Changed=TRUE;
          break;
        case 3:
#ifdef ADD_DEBUG_CODE
        if(MPSem->Debug)
        {
          Delay(50*2);
          KP("Promoting with Requester\n");
        }
#endif  
          if((pd->SReq=(struct ScreenModeRequester *)AllocAslRequestTags(ASL_ScreenModeRequest,
                      ASLSM_TitleText             ,pd->ScrTitle,
                      ASLSM_DoWidth               ,TRUE ,
                      ASLSM_DoHeight              ,TRUE ,
                      ASLSM_DoOverscanType        ,TRUE ,
                      ASLSM_DoAutoScroll          ,TRUE ,
                      ASLSM_DoDepth               ,pd->DNode->Flags & DEPTH,
                      ASLSM_InitialAutoScroll     ,pd->DNode->AutoScroll,
                      ASLSM_InitialDisplayWidth   ,pd->DNode->Width,
                      ASLSM_InitialDisplayHeight  ,pd->DNode->Height,
                      ASLSM_InitialDisplayID      ,pd->DNode->ModeID,
                      ASLSM_InitialDisplayDepth   ,pd->DNode->Depth,
                      ASLSM_NegativeText          ,GetString(MSG_REQ_USE_DEFAULT),
                      ASLSM_PropertyFlags         ,0,
                      ASLSM_PropertyMask          ,BADMODES,                      
                      TAG_END 
                      )))
          {
            if(AslRequest(pd->SReq,NULL))
            {
              pd->ModeID        =pd->SReq->sm_DisplayID /* | pd->EHB_HAM */; // Can't OR display ID's to get HAM or EHB!
              pd->OverscanType  =pd->SReq->sm_OverscanType;
              pd->Width         =pd->SReq->sm_DisplayWidth;
              pd->Height        =pd->SReq->sm_DisplayHeight;    
              pd->Changed       =TRUE;
              if(pd->DNode->Flags & DEPTH)
              {
                pd->Depth=pd->SReq->sm_DisplayDepth;
                pd->SetDepth=TRUE;
              }
            }
            else
            {
              pd->Promote=FALSE;
            }
            FreeAslRequest(pd->SReq);  
          }
          break; 
      }/* end switch*/
      
#ifdef ADD_DEBUG_CODE
//      KP("end switch\n");
      //Delay(50*1);
#endif  
  
      /**** Setup promoted taglist ****/
      if(pd->Promote)
      {
        pd->SetLook3D   = pd->DNode->Look3D;
        pd->Interleave  =(pd->DNode->Flags & INTERLEAVE) | pd->Interleave;
        pd->ScreenPens  = pd->DNode->Pens;
        pd->AutoScroll  = pd->DNode->AutoScroll;
        pd->BlankBorder = pd->DNode->Flags & DNF_BLANK_BORDER;
        pd->Behind      = pd->DNode->Flags & DNF_BEHIND;
                 
        if( (pd->DNode->Flags & DNF_FORCEPLANAR)        && 
            (pd->Width>0)                               && 
            (pd->Height>0)                              &&
            (!pd->HasCustomBM)                          &&
            (V39)                                       &&
            (pd->Depth>0)  )
        {
    
          if(pd->BitMap=AllocBitMap(pd->Width,pd->Height,pd->Depth,BMF_CLEAR|BMF_DISPLAYABLE,0))
          {
            {
              pd->OpenNode->Flags|=ON_BITMAP;
            
              pd->OpenNode->BitMap=pd->BitMap;
              pd->NewTags[pd->TagNumber].ti_Tag=SA_BitMap;
              pd->NewTags[pd->TagNumber].ti_Data=(ULONG)pd->BitMap;
              pd->TagNumber++;
            }
          }
        }
        
      
        if(pd->Changed && !(pd->HasCustomBM))
        {
          if(pd->Width!=0)
          {
            pd->NewTags[pd->TagNumber].ti_Tag=SA_Width;
            pd->NewTags[pd->TagNumber].ti_Data=pd->Width;
            pd->TagNumber++;
          }
          if(pd->Height!=0)
          {
            pd->NewTags[pd->TagNumber].ti_Tag=SA_Height;
            pd->NewTags[pd->TagNumber].ti_Data=pd->Height;
            pd->TagNumber++;
          }
          
          if(FindTagItem(SA_DClip,TagList))
          { // if it specifies a dclip, i need to override it.
            if(QueryOverscan(pd->ModeID,&pd->ODClip,pd->OverscanType))
            {
              pd->NewTags[pd->TagNumber].ti_Tag=SA_DClip;
              pd->NewTags[pd->TagNumber].ti_Data=(ULONG)&pd->ODClip;
              pd->TagNumber++;
            }
          }
          else
          {
            pd->NewTags[pd->TagNumber].ti_Tag=SA_Overscan;
            pd->NewTags[pd->TagNumber].ti_Data=pd->OverscanType;
            pd->TagNumber++;
          }
        }
      
        if(pd->ModeChanged || pd->Changed)
        {
          pd->NewTags[pd->TagNumber].ti_Tag=SA_DisplayID;
          pd->NewTags[pd->TagNumber].ti_Data=pd->ModeID;
          pd->TagNumber++;
        }
    
        if(pd->DNode->Flags & SHAREPENS)
        {
          pd->NewTags[pd->TagNumber].ti_Tag=SA_SharePens;
          pd->NewTags[pd->TagNumber].ti_Data=TRUE;
          pd->TagNumber++;
        }
    
        if(pd->SetDepth && !(pd->HasCustomBM) && !(pd->EHB_HAM))
        {
          pd->NewTags[pd->TagNumber].ti_Tag=SA_Depth;
          pd->NewTags[pd->TagNumber].ti_Data=pd->Depth;
          pd->TagNumber++;
    
        }
    
        
        if((pd->DNode->Flags & DNF_PALETTE) && pd->DNode->Palette && pd->DNode->Colors)
        {
          if(V39)
          {    
            pd->Colors32[0]=pd->DNode->Colors<<16;
            CopyMemQuick(pd->DNode->Palette,&pd->Colors32[1],pd->DNode->Colors*3*sizeof(ULONG));
            pd->Colors32[pd->DNode->Colors*3+2]=0;
            
            pd->NewTags[pd->TagNumber].ti_Tag=SA_Colors32;
            pd->NewTags[pd->TagNumber].ti_Data=(ULONG)pd->Colors32;
            pd->TagNumber++;
          }
          else
          {
            ULONG c;
      
            for(c=0;c<pd->DNode->Colors;c++)
            {
              pd->ColorSpec[c].ColorIndex=c;
              pd->ColorSpec[c].Red   =pd->DNode->Palette[c].Red>>28;
              pd->ColorSpec[c].Green =pd->DNode->Palette[c].Green>>28;
              pd->ColorSpec[c].Blue  =pd->DNode->Palette[c].Blue>>28;
            }
            pd->ColorSpec[c].ColorIndex=-1;
            
            pd->NewTags[pd->TagNumber].ti_Tag=SA_Colors; 
            pd->NewTags[pd->TagNumber].ti_Data=(ULONG)pd->ColorSpec;
            pd->TagNumber++;
          }
        }
    
        switch(pd->DNode->FontType)
        {
          case SFONT_SYS:
            if(ns) ns->Font=0;
            pd->NewTags[pd->TagNumber].ti_Tag=SA_SysFont;
            pd->NewTags[pd->TagNumber].ti_Data=1;
            pd->TagNumber++;
            break;
          case SFONT_MP:
            if(pd->DNode->Font.tta_Name)
            {
//              if(pd->OpenNode=AllocOpenNode(pd->OpenNode))
              {
                pd->OpenNode->Flags|=ON_FONT;
              
                pd->NewTags[pd->TagNumber].ti_Tag  =SA_Font;
                pd->NewTags[pd->TagNumber].ti_Data =(ULONG)&pd->OpenNode->TA;
                pd->TagNumber++;
      
                if(pd->DNode->Flags & FIXASPECT && pd->ModeID != -1)
                {
                  if(GetDisplayInfoData(NULL,(UBYTE *)&pd->DispInfo,sizeof(struct DisplayInfo),DTAG_DISP,pd->ModeID))
                  {
                    fonttags[0].ti_Data=(ULONG)pd->DispInfo.Resolution.x|(((ULONG)pd->DispInfo.Resolution.y)<<16);
                    pd->DNode->Font.tta_Style |= FSF_TAGGED;
                    pd->DNode->Font.tta_Tags   =fonttags;
                  }
                }
                CloneTextAttr(&pd->DNode->Font,&pd->OpenNode->TA);
      
                pd->DNode->Font.tta_Style &= (~FSF_TAGGED);
                pd->DNode->Font.tta_Tags=NULL;
              }
            }
            break;
        }
    
        if(pd->DNode->PubOptions==1 && pd->DNode->PubName)
        {
          ULONG error=FALSE;
          struct TagItem badtags[]=
          {
            SA_BitMap,    1<<0,
//          SA_PubName,   1<<1,
            SA_PubSig,    1<<2,
            SA_PubTask,   1<<3,
            SA_BackFill,  1<<4,
            TAG_DONE,     0
          };
          
          if(TagList) error =PackBoolTags(0,TagList,badtags);
          if(ns)      error|=(ns->Type & CUSTOMBITMAP);
          
          if(error==0)
          {
//            if(pd->OpenNode=AllocOpenNode(pd->OpenNode))
            {
              struct OpenNode *won;
              UBYTE number[8];
              ULONG cnt=1,len;
              
              strncpy(pd->OpenNode->PubName,pd->DNode->PubName,MAXPUBSCREENNAME);
              pd->OpenNode->PubName[MAXPUBSCREENNAME]=0;
              len=strlen(pd->OpenNode->PubName);
              len=min(len,MAXPUBSCREENNAME-9);
              
              ObtainSemaphore(&MPSem->OpenListSem);
              
              won=(struct OpenNode *)MPSem->OpenList.lh_Head;
              while(won->on_Node.ln_Succ)
              {
                if(cnt > 1)   
                {
                  number[0]='.';
                  stci_d(&number[1],cnt);        
                  pd->OpenNode->PubName[len]=0;
                  strncat(pd->OpenNode->PubName,number,MAXPUBSCREENNAME);
                  pd->OpenNode->PubName[MAXPUBSCREENNAME]=0;
                }
                
                if(0==strcmp(pd->OpenNode->PubName,won->PubName))
                {
                  won=(struct OpenNode *)MPSem->OpenList.lh_Head;
                  cnt++;
                }
                else
                  won=(struct OpenNode *)won->on_Node.ln_Succ;
              }
              
              ReleaseSemaphore(&MPSem->OpenListSem);
              
              pd->OpenNode->ScreenTitle=CopyString(pd->ScrTitle,MEMF_PUBLIC); 
              // Name cloned, when app CloseScreen's this title replaces the app supplied one
              
              pd->OpenNode->PubName[MAXPUBSCREENNAME]=0;
              pd->OpenNode->Flags|= ON_PUBLIC | ON_OPEN;
              
              /*
              pd->NewTags[pd->TagNumber].ti_Tag=SA_Title;
              pd->NewTags[pd->TagNumber].ti_Data=(ULONG)pd->OpenNode->ScreenTitle;
              pd->TagNumber++;
              */
      
              pd->NewTags[pd->TagNumber].ti_Tag=SA_PubName;
              pd->NewTags[pd->TagNumber].ti_Data=(ULONG)pd->OpenNode->PubName;
              pd->TagNumber++;
          
              pd->NewTags[pd->TagNumber].ti_Tag=SA_PubSig;
              pd->NewTags[pd->TagNumber].ti_Data=PublicSignal;
              pd->TagNumber++;
              
              pd->NewTags[pd->TagNumber].ti_Tag=SA_PubTask;
              pd->NewTags[pd->TagNumber].ti_Data=(ULONG)MPTask;
              pd->TagNumber++;
              
              
              if(!(pd->OpenNode->Flags & ON_FONT))
              {
                struct TTextAttr *ot=NULL;
                
                if(ns)  ot=(struct TTextAttr *)ns->Font;          
                ot=(struct TTextAttr *)GetTagData(SA_Font,(ULONG)ot,TagList);
                
                if(ot)
                {
                  pd->OpenNode->Flags|=ON_FONT;
      
                  CloneTextAttr(ot,&pd->OpenNode->TA);
      
                  pd->NewTags[pd->TagNumber].ti_Tag =SA_Font;
                  pd->NewTags[pd->TagNumber].ti_Data=(ULONG)&pd->OpenNode->TA;
                  pd->TagNumber++;
                }
              }
            }
          }
        }
      } /* end - if(pd->Promote) */
    }/* end - if(!pd->IsWorkbench) */
    else  
    { /* Yes, this is the Workbench screen */
//      if(pd->OpenNode=AllocOpenNode(pd->OpenNode))
        pd->OpenNode->Flags|=ON_WORKBENCH;
    }
  
    if(pd->Promote)
    {
      if(pd->SetLook3D)
      {
        LONG dp;
        
        if(pd->DNode->Flags & DNF_3D_DEFAULT)
        {
          if(V39 && pd->Depth>1 && MPSem->PPrefsSet)
          {
            /* Use 4 color palette from prefs */
            for(dp=0;dp<DRIPENS;dp++)
              pd->DriPens[dp]=MPSem->PPrefs.pap_4ColorPens[dp] & 0xff;
            pd->DriPens[dp]=~0;
          }
          else
            pd->DriPens[0]=~0;
        }
        else
        {
          for(dp=0;dp<DRIPENS;dp++)
            pd->DriPens[dp]=pd->DNode->Pens[dp] & 0xff;
          pd->DriPens[dp]=~0;
        }
        
        pd->NewTags[pd->TagNumber].ti_Tag=SA_Pens;
        pd->NewTags[pd->TagNumber].ti_Data=(ULONG)pd->DriPens;
        pd->TagNumber++;
        /*
        if(pd->Depth==1)
        {
          pd->Depth=2;  // This nolonger works
          pd->SetDepth=TRUE;
          //  pd->NewTags[pd->TagNumber].ti_Tag=SA_Depth;
          //  pd->NewTags[pd->TagNumber].ti_Data=2;
          //   pd->TagNumber++;
        }*/
      }
    
      if(pd->AutoScroll)
      {
        pd->NewTags[pd->TagNumber].ti_Tag=SA_AutoScroll;
        pd->NewTags[pd->TagNumber].ti_Data=TRUE;
        pd->TagNumber++;
      }

      if(pd->Behind)
      {
        pd->NewTags[pd->TagNumber].ti_Tag=SA_Behind;
        pd->NewTags[pd->TagNumber].ti_Data=TRUE;
        pd->TagNumber++;
      }    
      
      if(pd->DNode->CenterFlags)
      {    
        if(QueryOverscan(pd->ModeID,&pd->ODClip,pd->OverscanType))
        //if(GetDisplayInfoData(NULL,(UBYTE *)&pd->DimInfo,sizeof(struct DimensionInfo),DTAG_DIMS,pd->ModeID))
        {
          if(pd->DNode->CenterFlags & 1)
          {
            if(pd->Width>-1 && pd->ODClip.MaxX > pd->ODClip.MinX)
            {
#ifdef ADD_DEBUG_CODE
              if(MPSem->Debug)
              {
                KP("  ODClip.MinX=%ld  ODClip.MaxX=%ld  Width=%ld\n",pd->ODClip.MinX,pd->ODClip.MaxX,pd->Width);
              }
#endif

              pd->NewTags[pd->TagNumber].ti_Tag=SA_Left;
              pd->NewTags[pd->TagNumber].ti_Data=((pd->ODClip.MaxX-pd->ODClip.MinX)-pd->Width)/2+pd->ODClip.MinX;
              pd->TagNumber++;
            }
          }
          if(pd->DNode->CenterFlags & 2)
          {
            if(pd->Height>-1 && pd->ODClip.MaxX > pd->ODClip.MinX)
            {
#ifdef ADD_DEBUG_CODE
              if(MPSem->Debug)
              {
                KP("  ODClip.MinY=%ld  ODClip.MaxY=%ld  Height=%ld\n",pd->ODClip.MinY,pd->ODClip.MaxY,pd->Height);
              }
#endif
              
              pd->NewTags[pd->TagNumber].ti_Tag=SA_Top;
              pd->NewTags[pd->TagNumber].ti_Data=((pd->ODClip.MaxY-pd->ODClip.MinY)-pd->Height)/2+pd->ODClip.MinY;
              pd->TagNumber++;
            }
          }
          
#ifdef ADD_DEBUG_CODE         
          PrintOverscanInfo(pd);
#endif
          
        }
      }
       
      if(pd->DNode->Flags & SCRHOTKEY && pd->DNode->HotKey)
      {
//        if(pd->OpenNode=AllocOpenNode(pd->OpenNode))
        {
          if(pd->OpenNode->HotKey=AllocVec(strlen(pd->DNode->HotKey)+1,MEMF_CLEAR|MEMF_PUBLIC))
          {
            strcpy(pd->OpenNode->HotKey,pd->DNode->HotKey);
            pd->OpenNode->Cx=AddHotKey(Broker,BrokerPort,pd->OpenNode->HotKey,(ULONG)pd->OpenNode);
          }
        }
      }
      
    
      if(pd->Interleave && !(pd->HasCustomBM))
      {
        pd->NewTags[pd->TagNumber].ti_Tag=SA_Interleaved;
        pd->NewTags[pd->TagNumber].ti_Data=TRUE;
        pd->TagNumber++;
      }
        
      pd->NewTags[pd->TagNumber].ti_Tag=SA_MinimizeISG; /*** just a little extra for v40 ***/
      pd->NewTags[pd->TagNumber].ti_Data=TRUE;
      pd->TagNumber++;
    
      if(TagList)
      {
        pd->NewTags[pd->TagNumber].ti_Tag=TAG_MORE;
        pd->NewTags[pd->TagNumber].ti_Data=(ULONG)TagList;
      }
      else
      {
        pd->NewTags[pd->TagNumber].ti_Tag=TAG_DONE;
        pd->NewTags[pd->TagNumber].ti_Data=0;
      }
      /**** End Setup TagList ****/
      
//      if(pd->OpenNode)
      {
        if(pd->OpenNode->Flags & ON_FONT)
          pd->TextFont=OpenDiskFont((struct TextAttr *)&pd->OpenNode->TA);
      }
    } /* end - if(pd->Promote) */
  
  
#ifdef ADD_DEBUG_CODE  
    if(MPSem->Debug)
    {
      Delay(50*1);
      KP("  %ld new tags\n",pd->TagNumber);
      KP("  New TagList\n");
      PrintTags(pd->NewTags);
     
      KP("  Opening\n");
    }
#endif
  
    RetScreen=OldOpenScreenTagList(ns,pd->NewTags,IBase);
    if(ns)
    {
      ns->Font=pd->StoredFont;
    }
  
    if(RetScreen)
    {
      pd->OpenNode->Screen=RetScreen;
      
      if(pd->BlankBorder)
      {
        ULONG vrt;
        VideoControlTags(RetScreen->ViewPort.ColorMap,
                          VTAG_BORDERBLANK_SET, TRUE,
                          VTAG_IMMEDIATE        ,&vrt,
                          TAG_DONE);
        MakeScreen(RetScreen);
      }
      
      AddBackdrop(RetScreen,pd->DNode);
  
#ifdef ADD_DEBUG_CODE  
      if(MPSem->Debug)
      {
        Delay(50*1);
        KP("  Screen Addr %8lx\n",RetScreen);
      }
#endif

      mpObtainPens(pd);
      /**************/    
      
      if(pd->OpenNode->Flags & ON_FONT)
        if(pd->TextFont)
          CloseFont(pd->TextFont);
      
      if(pd->OpenNode->Flags & ON_PUBLIC)
      {
        PubScreenStatus(RetScreen,0);
      }
          
      ObtainSemaphore(&MPSem->OpenListSem);
      AddHead(&MPSem->OpenList,(struct Node *)pd->OpenNode);
      ReleaseSemaphore(&MPSem->OpenListSem);
    }
    else
    {
      FreeOpenNode(pd->OpenNode);
      
      RetScreen=OldOpenScreenTagList((struct ExtNewScreen *)ns,TagList,IBase);
    }
    
    FreeVec(pd);
    
    ReleaseSemaphore(&MPSem->ListSem);
    InPatch--;
    return(RetScreen);
  }
//  ReleaseSemaphore(&MPSem->NodeSem); 
  ReleaseSemaphore(&MPSem->ListSem);
  InPatch--;
  return(0);
}

BOOL __saveds ASM NewCloseScreen(REG __a0 struct Screen *S,
                                 REG __a6 struct IntuitionBase *IBase)
{
  struct OpenNode *on;
  BOOL rv,found=FALSE;

  InPatch++;

#ifdef ADD_DEBUG_CODE  
  if(MPSem->Debug)
  {
    KP("--------------------------------\nCloseScreen(%8lx) -- %s\n",S,FindTask(0)->tc_Node.ln_Name);
  }
#endif

  ObtainSemaphore(&MPSem->OpenListSem);
  
  RemoveBackdrop(S);
  
  on=(struct OpenNode *)MPSem->OpenList.lh_Head;
  while(on->on_Node.ln_Succ)
  {
    if(on->Screen==S)
    {
      Remove((struct Node *)on);
      found=TRUE;
      break;
    }
    on=(struct OpenNode *)on->on_Node.ln_Succ;
  }
  
  if(found)
  {
    if(on->Flags & ON_PUBLIC)
    {
      on->Flags&=(~ON_OPEN);
      S->DefaultTitle=S->Title=on->ScreenTitle;
      ShowTitle(S,TRUE);
      AddHead(&MPSem->OpenList,(struct Node *)on);
      rv=TRUE;
      Signal((struct Task *)MPTask,1<<PublicSignal);
    }
    else // Not public
    {
      /*
      if(on)
        SendOptionMsg(MP_SCREENCLOSING,0,0,on);
        */
      PreCloseOpenNode(on);
      if(rv=OldCloseScreen(S,IBase))
        FreeOpenNode(on);
      else
        if(on)
          AddHead(&MPSem->OpenList,(struct Node *)on);  
    }
              
  }

#ifdef ADD_DEBUG_CODE  
  if(MPSem->Debug)
  {
    KP("  RV=%d\n",rv);
  }
#endif
 
  InPatch--;
  
  ReleaseSemaphore(&MPSem->OpenListSem);
  
  return(rv);
}


LONG __saveds ASM NewCloseWorkBench(REG __a6 struct IntuitionBase *IBase)
{   
  LONG retval;
  
#ifdef ADD_DEBUG_CODE  
  if(MPSem->Debug)
  {
    KP("--------------------------------\nCloseWorkBench() -- %s\n",FindTask(0)->tc_Node.ln_Name);
  }
#endif

  //ObtainSemaphore(&MPSem->OpenListSem);
  //SendOptionMsg(MP_SCREENCLOSING,0,0,ON);
  PreCloseWBOpenNode();
  if(retval=OldCloseWorkBench(IBase))
    FreeWBOpenNode();
  
  //ReleaseSemaphore(&MPSem->OpenListSem);

#ifdef ADD_DEBUG_CODE  
  if(MPSem->Debug)
  {
    KP("  RV=%d\n",retval);
  }
#endif
  return(retval);
}

void CatchDNode(ULONG Dest, UBYTE *Name, struct DefaultNode *SrcNode)
{
  struct DefaultNode *dnode;
  LONG l;
  
  if(dnode=AllocDefaultNode(Name))
  {
    dnode->Type         =Dest;
    dnode->Width        =SrcNode->Width;
    dnode->Height       =SrcNode->Height;
    dnode->AutoScroll   =SrcNode->AutoScroll;
    dnode->ModeSelect   =0;
    dnode->ModeID       =SrcNode->ModeID;
    dnode->OverscanType =SrcNode->OverscanType;
    dnode->Look3D       =SrcNode->Look3D;
    dnode->Flags        =SrcNode->Flags;
    dnode->Depth        =SrcNode->Depth;
/******* change to <= */
    for(l=0;l<DRIPENS;l++)
      dnode->Pens[l]      =SrcNode->Pens[l];
    
    PutMsg(CatchPort,(struct Message *)dnode);
  }
  return;
}

/* Go into forced edit mode, user must edit this node before returning */
struct DefaultNode *ForceEdit(struct DefaultNode *DNode)
{
  struct DefaultNode *retval;
  struct MsgPort *rport;
  struct MPMessage *mpm;

  retval=0;
  
  if(rport=CreateMsgPort())
  {
    if(mpm=AllocVec(sizeof(struct MPMessage),MEMF_PUBLIC|MEMF_CLEAR))
    {
      mpm->mp_Message.mn_Length=sizeof(struct MPMessage);
      mpm->mp_Message.mn_ReplyPort=rport;
      
      /* send message to Daemon - SHOWGUI */
      mpm->Command=MP_SHOWGUI;
      
      PutMsg(MPSem->DaemonPort,(struct Message *)mpm);
      WaitForReply((struct Message *)mpm);
    
      if(mpm->Code)
      {
        ObtainSemaphore(&MPSem->PortSem);
        
        /* send message to ForceEditPort owner */
        mpm->Data=DNode;
        mpm->Command=MP_FORCEDEDIT;

        
        PutMsg(&MPSem->ForcedEditPort,(struct Message *)mpm);

        ReleaseSemaphore(&MPSem->PortSem);
        
        WaitForReply((struct Message *)mpm);
  
  /*
        rm=0;
        while(rm!=mpm)
        {
          WaitPort(rport);
          rm=(struct MPMessage *)GetMsg(rport);
        }
    */  
        switch(mpm->Code)
        {
          case MPFE_USEDELETE:
            retval=DNode; // return DNode for use.
            break;
            
          case MPFE_NEVER:
            DNode->Flags=DNF_NEVER_PROMOTE;  // Set flag and give to MP
            PutMsg(CatchPort,(struct Message *)DNode);
            retval =0;
            break;
            
          case MPFE_SAVEUSE:
            {
              retval =DNode;
              if(DNode  =DupDNode(retval))   /* Duplicate, give copy to MP and then use orignal for promotion */
              {
                PutMsg(CatchPort,(struct Message *)DNode);
              }
            }
            break;
            
          case MPFE_CANCEL:
          default:
            /* Delete the new node */
            FreeDNode(DNode);
        }//END SWITCH
      }
      FreeVec(mpm);
    }
    DeleteMsgPort(rport);
  }
  return(retval);
}

void WaitForReply(struct Message *Msg)
{
  struct Message *m;
  struct MsgPort *port;
  
  m=0;
  port=Msg->mn_ReplyPort;
  
  while(m!=Msg)
  {
    WaitPort(port);
    m=GetMsg(port);
  }
}


/*
BOOL SendOptionsMsg(ULONG Command, ULONG Code, struct DefaultNode *DN, struct OpenNode *ON)
{
  struct MsgPort *mport;
  struct MPScreenMessage mpsm;
  
  if(mport=CreateMsgPort())
  {
    mpm.mp_Message.mn_ReplyPort=mport;
    mpm.mp_Message.mn_Length=sizeof(mpsm);
    mpm.Command=Command;
    mpm.Code=Code;
    mpm.DN=DN;
    mpm.ON=ON;

    ObtainSemaphore(&MPSem->OptionSem);
    PutMsg(&MPSem->OptionPort,(struct Message *)mpsm);
    ReleaseSemaphore(&MPSem->OptionSem);

    WaitForReply((struct Message *)mpsm);

    DeleteMsgPort(mport);
    return(1);
  }
  return(0);
}

*/


/*
  
      if(pd->DNode->Flags & SHAREPENS && 
         pd->DNode->LockedPens        && 
         V39)
      {
        UBYTE *str,state=0,done=FALSE;
        WORD num=0,num1=0,num2;
        struct ColorMap *cm;
        
        cm=RetScreen->ViewPort.ColorMap;
        
        str=pd->DNode->LockedPens;
        
        while(!done)
        {
          if(!*str) done=TRUE;
          
          if(*str>='0' && *str<='9')
          {
            if(state==0)
              state=1;
            num=0;
            while(*str>='0' && *str<='9')
            {
              num*=10;
              num+=*str - '0';
              str++;
            }
            
            switch(state)
            {
              case 1:
#ifdef ADD_DEBUG_CODE  
                if(MPSem->Debug)
                {
                  KP("  obtaining pen %ld\n",num);
                }
#endif        
                if(!pd->OpenNode->ObtainedPens[num])
                {
                  if(-1!=ObtainPen(cm,num,0,0,0, PEN_EXCLUSIVE | PEN_NO_SETCOLOR)))
                    pd->OpenNode->ObtainedPens[num]=1;
                }
                break;
              case 2:
                for(num2=num1+1;num2<=num;num2++)
                {
#ifdef ADD_DEBUG_CODE  
                  if(MPSem->Debug)
                  {
                    KP("  obtaining pen %ld\n",num2);
                  }
#endif
                  if(!pd->OpenNode->ObtainedPens[num2])
                  {
                    if(-1!=ObtainPen(cm,num2,0,0,0, PEN_EXCLUSIVE | PEN_NO_SETCOLOR))
                      pd->OpenNode->ObtainedPens[num2]=1;
                  }
                }
                break;
            }
            state=0;
           
          }
          
          if(*str==' ')
            for(;*str==' ';str++);
          else
            if(*str=='-')
            {
              num1=num;
              state=2;
              str++;
            }
            else
              str++;
        }
      }
      
      */
