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

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

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

#define ADD_DEBUG_CODE

/* kprintf

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

*/

#ifdef ADD_DEBUG_CODE
void PrintTags(struct TagItem *tags);
UBYTE *FindTagSting(ULONG id);
void PrintDefNode(struct DefaultNode *DN);
#endif

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

extern ULONG CenterAll;
extern struct MPSem *MPSem;
extern CxObj  *Broker;
extern struct MsgPort *BrokerPort;
extern BOOL   V39;
extern BYTE   PublicSignal;
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)
{
  return(NewOpenScreenTagList(ns,(ns->Type & NS_EXTENDED ?ns->Extension:0),IBase ));
}

UBYTE *Topaz="topaz.font";

struct PatchData
{
  struct BitMap *bitmap;
  struct Rectangle odclip;
  struct DefaultNode *n;
  struct DimensionInfo diminfo;
  struct DisplayInfo   dispinfo;


  struct Screen *scr;

  struct ScreenModeRequester *sr;
  struct ColorSpec Colors4[257];
  ULONG  Colors32[256*3+2];

  WORD  width,
        height,
        depth;
  BOOL  dodepth;

  LONG  autoscroll,
        look3d,
        modeid,
        overscan,
        interleave,
        wbscr;
        
  BOOL  changed,modechanged;
  BOOL  promote;
       
  WORD  pens[1],
        *screenpens,
        dripens[DRIPENS+1];   
       
  struct TagItem ti[30],
                 *tag;

  struct TextAttr *storedfont;              
  struct TextFont *textfont;              
  struct TagItem fonttags[2];

  ULONG  tagnum,ehbham;

  UBYTE  cli_name[41],*taskname;
  UBYTE *title;
       
  struct OpenNode *opennode;
 
  LONG custombm;
};

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 BitMap *bitmap;
  struct Rectangle odclip;
  struct DefaultNode *n;
  struct DimensionInfo diminfo;
  struct DisplayInfo   dispinfo;

  struct Screen *scr;

  struct ScreenModeRequester *sr;
  struct ColorSpec Colors4[257];
  ULONG  Colors32[256*3+2];

  WORD  width,
        height,
        depth;
  BOOL  dodepth;

  LONG  autoscroll,
        look3d,
        modeid,
        overscan,
        interleave,
        wbscr;
        
  BOOL  changed,modechanged;
  BOOL  promote=TRUE;
       
  WORD  pens[]={~0},
        *screenpens,
        dripens[DRIPENS+1];   
       
  struct TagItem ti[30],
                 *tag;

  struct TextAttr *storedfont;              
  struct TextFont *textfont;              
  struct TagItem fonttags[]= { TA_DeviceDPI , (1<<16) | 1 , TAG_DONE,0 };

  ULONG  tagnum,ehbham;

  UBYTE  cli_name[41],*taskname;
  UBYTE *title;
       
  struct OpenNode *opennode;
 
  LONG custombm;

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

  ObtainSemaphoreShared(&MPSem->ListSem); 
  ObtainSemaphore(&MPSem->NodeSem); 
  
  pens[0]=(~0);
  
#ifdef ADD_DEBUG_CODE
  if(MPSem->Debug)
  {
    kprintf("sizeof(struct PatchData) %8lx\n",sizeof(struct PatchData));
    
    kprintf("\n--------------%s------------------\nOpenScreenX()\n",FindTask(0)->tc_Node.ln_Name);
    kprintf("  IntuitionBase: %8lx\n",IBase);
    if(ns)
    {
      kprintf("  NewScreen: %8lx\n",ns);
      kprintf("    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)
        kprintf("    defaulttitle=%s\n", ns->DefaultTitle);
      kprintf("    gadgets=%8lx  bitmap=%8lx\n",
        ns->Gadgets, ns->CustomBitMap);
      if(ns->Type & NS_EXTENDED)
        kprintf("    * is NS_EXTENDED\n");
    }  
    if(TagList)
      PrintTags(TagList);
  }
#endif
  
  /* Now that we've got the semaphore all globals are mine */
  /* initialize everything */

  tagnum=0;

  title=NULL;

  opennode=NULL;   //likewb=0;
  
  custombm=changed=modechanged=look3d=overscan=interleave=0L;
  depth=1;
  dodepth=FALSE;
  
  wbscr=0;  
  
  width=height=autoscroll=modeid=-1;
 
  screenpens=pens;
  
  taskname=FindTask(0)->tc_Node.ln_Name;

  if(GetProgramName(cli_name,40)) /* Get cli program's name */
    if(cli_name[0]!=0)            /* make sure cli_name contains something */
      taskname=cli_name;
  
  /* Initialization Done */

  /**** Extract screen info from ns and TagList ****/  
  if(ns)                     
  {
    storedfont=ns->Font;
    width    =ns->Width;
    height   =ns->Height;
    modeid   =ns->ViewModes;
    depth    =ns->Depth;
    title    =ns->DefaultTitle;
    custombm =ns->Type & CUSTOMBITMAP;
    wbscr    =(ns->Type & SCREENTYPE)==WBENCHSCREEN;
  }

  if(TagList)
  {
    custombm  =GetTagData(SA_BitMap,    custombm,TagList);
    width     =GetTagData(SA_Width,     width,   TagList);
    height    =GetTagData(SA_Height,    height,  TagList);
    autoscroll=GetTagData(SA_AutoScroll,autoscroll,TagList);
    overscan  =GetTagData(SA_Overscan,  overscan,TagList);
    modeid    =GetTagData(SA_DisplayID, modeid,  TagList);
    depth     =GetTagData(SA_Depth,     depth,   TagList);
    title     =(UBYTE *)GetTagData(SA_Title,(ULONG)title,TagList);
    wbscr     =(GetTagData(SA_Type,wbscr,TagList) & SCREENTYPE)==WBENCHSCREEN;
    interleave=GetTagData(SA_Interleaved,interleave,TagList);
    if(tag=FindTagItem(SA_Overscan,TagList))
      if(!FindTagItem(SA_DClip,TagList))
        overscan=tag->ti_Data;
    if(tag=FindTagItem(SA_Pens,TagList))
    {
      screenpens=(UWORD *)(tag->ti_Data);
      //look3d=TRUE;
    }
  }

#ifdef ADD_DEBUG_CODE
  if(MPSem->Debug)
  {
    kprintf("..................................\n");
    kprintf("w=%ld h=%ld d=%ld custombm=%8lx\n",width,height,depth,custombm);
    kprintf("..................................\n");
  }
#endif

  n=NULL;

  ehbham=0;

  if(GetDisplayInfoData(0,(UBYTE *)&dispinfo,sizeof(dispinfo),DTAG_DISP,modeid))
    ehbham=dispinfo.PropertyFlags & (DIPF_IS_DUALPF | DIPF_IS_HAM | 
                                     DIPF_IS_PF2PRI | DIPF_IS_EXTRAHALFBRITE);
  
#ifdef ADD_DEBUG_CODE
  if(MPSem->Debug)
  {
    kprintf("wbscr=%lx\n",wbscr);
  }
#endif
  
  if(!title) title=GetString(MSG_ITEM_NO_NAME); /* Just in case ther isn't a title */

  if(!(n=FindDNode(&MPSem->PromotionList[1],title)))
    if(!(n=FindDNode(&MPSem->PromotionList[0],taskname)))
    { 
      struct DefaultNode *smnode;
      BOOL   smgo=TRUE;
      ULONG  /*modenorm,*/ mode_monall,orig_monall;
      
      //modenorm    =modeid;// & ~HAM_EHB_DP_KEY;
      mode_monall  =modeid | ALL_MODES;
      
      smnode=(struct DefaultNode *)MPSem->PromotionList[PL_SCREENMODES].lh_Head;
      while(smnode->Def_Node.ln_Succ && smgo)
      {
        orig_monall =smnode->OrigDisplayID & ALL_MODES;
      
        if( (smnode->OrigDisplayID == modeid) ||
            (smnode->OrigDisplayID == mode_monall) )     
        {
          n=smnode;
          smgo=FALSE;
        }
        smnode=(struct DefaultNode *)smnode->Def_Node.ln_Succ;
      }
      /*
      if(MPSem->CatchPrograms && taskname)   //Catch new names only.
        CatchDNode(0,taskname);
      if(MPSem->CatchScreens) 
        CatchDNode(1,title);
      */
    }

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

  if(!n && MPSem->CenterAll)
  {
    n=&CenterAll;
    CenterAll.CenterFlags=MPSem->CenterAll;
  } 

  if(!MPSem->Enabled || !n )
  {
    scr=OldOpenScreenTagList(ns,TagList,IBase);
    ReleaseSemaphore(&MPSem->ListSem);
    ReleaseSemaphore(&MPSem->NodeSem);
    return(scr);
  }
  

  if(!wbscr)
  {
    switch(n->ModeSelect)
    {
      case 0:
        break;
      case 1:
#ifdef ADD_DEBUG_CODE
      if(MPSem->Debug)
      {
        kprintf("Promoting Monitor\n");
      }
#endif  
        if(modeid > -1)
        {
          if(V39)
          {
            modeid=BestModeID(BIDTAG_SourceID       ,modeid,
                              BIDTAG_MonitorID      ,n->ModeID & MONITOR_ID_MASK,
                              BIDTAG_Depth          ,depth,
                              BIDTAG_DIPFMustHave   ,ehbham,
                              TAG_SKIP              ,(width==-1 ? 1:0),
                              BIDTAG_DesiredWidth   ,width,
                              TAG_SKIP              ,(height==-1 ? 1:0),
                              BIDTAG_DesiredHeight  ,height,
                              TAG_DONE);
            //kprintf("%8lx\n",modeid);
          }
          else
          {
            modeid= (n->ModeID & MONITOR_ID_MASK) | (modeid & (~MONITOR_ID_MASK));
          }
          if(modeid==INVALID_ID) 
             modeid=n->ModeID;
              
          modechanged=TRUE;
        }
        break;
      case 2:
#ifdef ADD_DEBUG_CODE
      if(MPSem->Debug)
      {
        kprintf("Promoting ScreenMode\n");
      }
#endif  
        modeid      =n->ModeID/* | ehbham*/;
        overscan    =n->OverscanType;
        width       =n->Width;
        height      =n->Height;
    
        if(n->Flags & DEPTH)
        {
          depth=n->Depth;
          dodepth=TRUE;
        }
        changed=TRUE;
        break;
      case 3:
#ifdef ADD_DEBUG_CODE
      if(MPSem->Debug)
      {
        kprintf("Promoting with Requester\n");
      }
#endif  
        if((sr=(struct ScreenModeRequester *)AllocAslRequestTags(ASL_ScreenModeRequest,
                    ASLSM_TitleText             ,title,
                    ASLSM_DoWidth               ,TRUE ,
                    ASLSM_DoHeight              ,TRUE ,
                    ASLSM_DoOverscanType        ,TRUE ,
                    ASLSM_DoAutoScroll          ,TRUE ,
                    ASLSM_DoDepth               ,n->Flags & DEPTH,
                    ASLSM_InitialAutoScroll     ,n->AutoScroll,
                    ASLSM_InitialDisplayWidth   ,n->Width,
                    ASLSM_InitialDisplayHeight  ,n->Height,
                    ASLSM_InitialDisplayID      ,n->ModeID,
                    ASLSM_InitialDisplayDepth   ,n->Depth,
                    ASLSM_NegativeText          ,GetString(MSG_REQ_USE_DEFAULT),
                    ASLSM_PropertyFlags         ,0,
                    ASLSM_PropertyMask          ,BADMODES,                      
                    TAG_END 
                    )))
        {
          if(AslRequest(sr,NULL))
          {
            modeid    =sr->sm_DisplayID | ehbham;
            overscan  =sr->sm_OverscanType;
            width     =sr->sm_DisplayWidth;
            height    =sr->sm_DisplayHeight;    
            changed   =TRUE;
            if(n->Flags & DEPTH)
            {
              depth=sr->sm_DisplayDepth;
              dodepth=TRUE;
            }
          }
          else
          {
            promote=FALSE;
          }
          FreeAslRequest(sr);  
        }
        break; 
    }/* end switch*/
    
#ifdef ADD_DEBUG_CODE
    kprintf("end switch\n");
    Delay(50*1);
#endif  

    /**** Setup promoted taglist ****/
    if(promote)
    {
      look3d     =n->Look3D;
      interleave =(n->Flags & INTERLEAVE) | interleave;
      screenpens =n->Pens;
      autoscroll  =n->AutoScroll;
       
      if( (n->Flags & DNF_FORCEPLANAR)  && 
          (width>0)                     && 
          (height>0)                    &&
          (!custombm)                   &&
          (V39)                         &&
          (depth>0)  )
      {
  
        if(bitmap=AllocBitMap(width,height,depth,BMF_CLEAR|BMF_DISPLAYABLE,0))
        {
  
          if(opennode=AllocOpenNode(opennode))
          {
            opennode->Flags|=ON_BITMAP;
          
            opennode->BitMap=bitmap;
            ti[tagnum].ti_Tag=SA_BitMap;
            ti[tagnum].ti_Data=(ULONG)bitmap;
            tagnum++;
          }
          else
            FreeBitMap(bitmap);
        }
      }
      
    
      if(changed && !(custombm))
      {
        if(width!=0)
        {
          ti[tagnum].ti_Tag=SA_Width;
          ti[tagnum].ti_Data=width;
          tagnum++;
        }
        if(height!=0)
        {
          ti[tagnum].ti_Tag=SA_Height;
          ti[tagnum].ti_Data=height;
          tagnum++;
        }
        
        if(FindTagItem(SA_DClip,TagList))
        { // if it specifies a dclip, i need to override it.
          if(QueryOverscan(modeid,&odclip,overscan))
          {
            ti[tagnum].ti_Tag=SA_DClip;
            ti[tagnum].ti_Data=(ULONG)&odclip;
            tagnum++;
          }
        }
        else
        {
          ti[tagnum].ti_Tag=SA_Overscan;
          ti[tagnum].ti_Data=overscan;
          tagnum++;
        }
      }
    
      if(modechanged || changed)
      {
        ti[tagnum].ti_Tag=SA_DisplayID;
        ti[tagnum].ti_Data=modeid;
        tagnum++;
      }
  
      if(n->Flags & SHAREPENS)
      {
        ti[tagnum].ti_Tag=SA_SharePens;
        ti[tagnum].ti_Data=TRUE;
        tagnum++;
      }
  
      if(dodepth && !(custombm) && !(ehbham))
      {
        ti[tagnum].ti_Tag=SA_Depth;
        ti[tagnum].ti_Data=depth;
        tagnum++;
  
      }
  
      
      if((n->Flags&DNF_PALETTE) && n->Palette && n->Colors)
      {
        if(V39)
        {    
          Colors32[0]=n->Colors<<16;
          CopyMemQuick(n->Palette,&Colors32[1],n->Colors*3*sizeof(ULONG));
          Colors32[n->Colors*3+2]=0;
          
          ti[tagnum].ti_Tag=SA_Colors32;
          ti[tagnum].ti_Data=(ULONG)Colors32;
          tagnum++;
        }
        else
        {
          ULONG c;
    
          for(c=0;c<n->Colors;c++)
          {
            Colors4[c].ColorIndex=c;
            Colors4[c].Red   =n->Palette[c].Red>>28;
            Colors4[c].Green =n->Palette[c].Green>>28;
            Colors4[c].Blue  =n->Palette[c].Blue>>28;
          }
          Colors4[c].ColorIndex=-1;
          
          ti[tagnum].ti_Tag=SA_Colors; 
          ti[tagnum].ti_Data=(ULONG)Colors4;
          tagnum++;
        }
      }
  
      switch(n->FontType)
      {
        case SFONT_SYS:
          if(ns) ns->Font=0;
          ti[tagnum].ti_Tag=SA_SysFont;
          ti[tagnum].ti_Data=1;
          tagnum++;
          break;
        case SFONT_MP:
          if(n->Font.tta_Name)
          {
            if(opennode=AllocOpenNode(opennode))
            {
              opennode->Flags|=ON_FONT;
            
              ti[tagnum].ti_Tag  =SA_Font;
              ti[tagnum].ti_Data =(ULONG)&opennode->TA;
              tagnum++;
    
              if(n->Flags & FIXASPECT && modeid != -1)
              {
                if(GetDisplayInfoData(NULL,(UBYTE *)&dispinfo,sizeof(struct DisplayInfo),DTAG_DISP,modeid))
                {
                  fonttags[0].ti_Data=(ULONG)dispinfo.Resolution.x|(((ULONG)dispinfo.Resolution.y)<<16);
                  n->Font.tta_Style |= FSF_TAGGED;
                  n->Font.tta_Tags   =fonttags;
                }
              }
              CloneTextAttr(&n->Font,&opennode->TA);
    
              n->Font.tta_Style &= (~FSF_TAGGED);
              n->Font.tta_Tags=NULL;
            }
          }
          break;
      }
  
      if(n->PubOptions==1)
      {
        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(opennode=AllocOpenNode(opennode))
          {
            struct OpenNode *won;
            UBYTE number[8];
            ULONG cnt=1,len;
            
            strncpy(opennode->PubName,n->PubName,MAXPUBSCREENNAME);
            opennode->PubName[MAXPUBSCREENNAME]=0;
            len=strlen(opennode->PubName);
            len=min(len,MAXPUBSCREENNAME-9);
            
            won=(struct OpenNode *)MPSem->OpenList.lh_Head;
            while(won->on_Node.ln_Succ)
            {
              if(cnt > 1)   
              {
                number[0]='.';
                stci_d(&number[1],cnt);        
                opennode->PubName[len]=0;
                strncat(opennode->PubName,number,MAXPUBSCREENNAME);
                opennode->PubName[MAXPUBSCREENNAME]=0;
              }
              
              if(0==strcmp(opennode->PubName,won->PubName))
              {
                won=(struct OpenNode *)MPSem->OpenList.lh_Head;
                cnt++;
              }
              else
                won=(struct OpenNode *)won->on_Node.ln_Succ;
            }
            
            opennode->PubName[MAXPUBSCREENNAME]=0;
            opennode->Flags|= ON_PUBLIC | ON_OPEN;
            
            ti[tagnum].ti_Tag=SA_Title;
            ti[tagnum].ti_Data=(ULONG)opennode->PubName;
            tagnum++;
    
            ti[tagnum].ti_Tag=SA_PubName;
            ti[tagnum].ti_Data=(ULONG)opennode->PubName;
            tagnum++;
        
            ti[tagnum].ti_Tag=SA_PubSig;
            ti[tagnum].ti_Data=PublicSignal;
            tagnum++;
            
            ti[tagnum].ti_Tag=SA_PubTask;
            ti[tagnum].ti_Data=(ULONG)MPTask;
            tagnum++;
            
            
            if(!(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)
              {
                opennode->Flags|=ON_FONT;
    
                CloneTextAttr(ot,&opennode->TA);
    
                ti[tagnum].ti_Tag =SA_Font;
                ti[tagnum].ti_Data=(ULONG)&opennode->TA;
                tagnum++;
              }
            }
          }
        }
      }
    } /* end - if(promote) */
  }/* end - if(!wbscr) */
  else  
  { /* Yes, this is the Workbench screen */
    if(opennode=AllocOpenNode(opennode))
      opennode->Flags|=ON_WORKBENCH;
  }

  if(promote)
  {
    if(look3d)
    {
      LONG dp;
      
      for(dp=0;dp<DRIPENS;dp++)
        dripens[dp]=n->Pens[dp];
      dripens[dp]=~0;
      
      ti[tagnum].ti_Tag=SA_Pens;
      ti[tagnum].ti_Data=(ULONG)dripens;
      tagnum++;
      /*
      if(depth==1)
      {
        depth=2;  // This nolonger works
        dodepth=TRUE;
        //  ti[tagnum].ti_Tag=SA_Depth;
        //  ti[tagnum].ti_Data=2;
        //   tagnum++;
      }*/
    }
  
    if(autoscroll)
    {
      ti[tagnum].ti_Tag=SA_AutoScroll;
      ti[tagnum].ti_Data=TRUE;
      tagnum++;
    }
  
    
    if(n->CenterFlags)
    {    
      if(GetDisplayInfoData(NULL,(UBYTE *)&diminfo,sizeof(struct DimensionInfo),DTAG_DIMS,modeid))
      {
        if(n->CenterFlags & 1)
        {
          if(width>-1)
          {
            ti[tagnum].ti_Tag=SA_Left;
            ti[tagnum].ti_Data=((diminfo.StdOScan.MaxX-diminfo.StdOScan.MinX)-width)/2;
            tagnum++;
          }
        }
        if(n->CenterFlags & 2)
        {
          if(height>-1)
          {
            ti[tagnum].ti_Tag=SA_Top;
            ti[tagnum].ti_Data=((diminfo.StdOScan.MaxY-diminfo.StdOScan.MinY)-height)/2;
            tagnum++;
          }
        }
      }
    }
  
    if(n->Flags & SCRHOTKEY)
    {
      if(opennode=AllocOpenNode(opennode))
      {
        if(opennode->HotKey=AllocVec(strlen(n->HotKey)+1,MEMF_CLEAR|MEMF_PUBLIC))
        {
          strcpy(opennode->HotKey,n->HotKey);
          opennode->Cx=AddHotKey(Broker,BrokerPort,opennode->HotKey,(ULONG)opennode);
        }
      }
    }
    
  
    if(interleave && !(custombm))
    {
      ti[tagnum].ti_Tag=SA_Interleaved;
      ti[tagnum].ti_Data=TRUE;
      tagnum++;
    }
  
  
      
/*
    ti[tagnum].ti_Tag=SA_VideoControl; /*** just a little extra for v40 ***/
    ti[tagnum].ti_Data=VCTags;
    tagnum++;
  */
    
    ti[tagnum].ti_Tag=SA_MinimizeISG; /*** just a little extra for v40 ***/
    ti[tagnum].ti_Data=TRUE;
    tagnum++;
  
    if(TagList)
    {
      ti[tagnum].ti_Tag=TAG_MORE;
      ti[tagnum].ti_Data=(ULONG)TagList;
    }
    else
    {
      ti[tagnum].ti_Tag=TAG_DONE;
      ti[tagnum].ti_Data=0;
    }
    /**** End Setup TagList ****/
    
    if(opennode)
    {
      if(opennode->Flags & ON_FONT)
        textfont=OpenDiskFont((struct TextAttr *)&opennode->TA);
    }
  } /* end - if(promote) */


#ifdef ADD_DEBUG_CODE  
  if(MPSem->Debug)
  {
    kprintf("  %ld new tags\n",tagnum);
    kprintf("  New TagList\n");
    PrintTags(ti);
    Delay(50*5);
    kprintf("  Opening\n");
  }
#endif

  scr=OldOpenScreenTagList(ns,ti,IBase);

#ifdef ADD_DEBUG_CODE  
  if(MPSem->Debug)
  {
    kprintf("  Screen Addr %8lx\n",scr);
    Delay(50*5);
  }
#endif

  if(scr && n->Flags & SHAREPENS && n->LockedPens && V39)
  {
    UBYTE *str,state=0,done=FALSE;
    WORD num=0,num1=0,num2;
    struct ColorMap *cm;
    
    cm=scr->ViewPort.ColorMap;
    
    str=n->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  
            kprintf("  obtaining pen %d\n",num);
#endif
            ObtainPen(cm,num,0,0,0, PEN_EXCLUSIVE | PEN_NO_SETCOLOR);
            break;
          case 2:
            for(num2=num1+1;num2<=num;num2++)
            {
#ifdef ADD_DEBUG_CODE  
              kprintf("  obtaining pen %d\n",num2);
#endif
              ObtainPen(cm,num2,0,0,0, PEN_EXCLUSIVE | PEN_NO_SETCOLOR);
            }
            break;
        }
        state=0;
       
      }
      
      if(*str==' ')
        for(;*str==' ';str++);
      else
        if(*str=='-')
        {
          num1=num;
          state=2;
          str++;
        }
        else
          str++;
    }
  }



  if(opennode)
  {
    if(opennode->Flags & ON_FONT)
      if(textfont)
        CloseFont(textfont);
    
    if(scr)
    {
      opennode->Screen=scr;
      if(opennode->Flags & ON_PUBLIC)
      {
        if(n->PubOptions == 1)
        {
          PubScreenStatus(scr,0);
        }
      }
      AddHead(&MPSem->OpenList,(struct Node *)opennode);
    }
    else
      FreeOpenNode(opennode);
  }
  
/*
  if(scr)
  {
    VideoControlTags(scr->ViewPort.ColorMap,
                      VTAG_BORDERSPRITE_SET,TRUE,
                      TAG_DONE);
  }
*/
  if(ns) ns->Font=storedfont;


  if(!scr) scr=OldOpenScreenTagList((struct ExtNewScreen *)ns,TagList,IBase);

  ReleaseSemaphore(&MPSem->ListSem);
  ReleaseSemaphore(&MPSem->NodeSem);

  return(scr);
}

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

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


  ObtainSemaphore(&MPSem->OpenListSem);
  
  on=(struct OpenNode *)MPSem->OpenList.lh_Head;
  while(on->on_Node.ln_Succ)
  {
    if(on->Screen==S)
    {
      Remove((struct Node *)on);
      pub=on->Flags & ON_PUBLIC;
      ok=TRUE;
      break;
    }
    on=(struct OpenNode *)on->on_Node.ln_Succ;
  }
  
  if(!ok) on=NULL;
  
  if(!pub)
  {
    if(rv=OldCloseScreen(S,IBase))
      FreeOpenNode(on);
    else
      if(on)
        AddHead(&MPSem->OpenList,(struct Node *)on);  
  }
  else  // Public
  {
    on->Flags&=(~ON_OPEN);
    S->DefaultTitle=S->Title=on->PubName;
    ShowTitle(S,TRUE);
    AddHead(&MPSem->OpenList,(struct Node *)on);
    rv=TRUE;
    Signal((struct Task *)MPTask,1<<PublicSignal);
  }          
  ReleaseSemaphore(&MPSem->OpenListSem);   

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

/*
struct Screen *New LockPubScreen(REG STRPTR Name)
{
  struct Screen *scr;
  
  if(scr=LockPubScreen(Name))
    return(scr);
    
  if(!(n=FindDNode(&MPSem->PromotionList[1],title)))
*/

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

//  ObtainSemaphore(&MPSem->OpenListSem);
  
  if(retval=OldCloseWorkBench(IBase))
    FreeWBOpenNode();
  
//  ReleaseSemaphore(&MPSem->OpenListSem);

#ifdef ADD_DEBUG_CODE  
  if(MPSem->Debug)
  {
    kprintf("  RV=%d\n",retval);
  }
#endif
  return(retval);
}
  
void FreeOpenNode(struct OpenNode *on)
{
#ifdef ADD_DEBUG_CODE  
  if(MPSem->Debug)
  {
    kprintf("--------------------------------\nFreeOpenNode(%8lx)\n",on);
  }
#endif
  if(on) 
  { 
    /* All these are safe to call with NULL */
    FreeVec(on->TA.tta_Name);
    FreeVec(on->TA.tta_Tags);
    DeleteCxObjAll(on->Cx);
    FreeVec(on->HotKey);
    if(V39)
      FreeBitMap(on->BitMap);
    FreeMem(on,sizeof(struct OpenNode));

#ifdef ADD_DEBUG_CODE  
    if(MPSem->Debug)
    {
      kprintf("  Freed\n");
    }
#endif
  }
}

void FreeWBOpenNode(void)
{
  struct OpenNode *on;

#ifdef ADD_DEBUG_CODE  
  if(MPSem->Debug)
  {
    kprintf("--------------------------------\nFreeWBOpenNode()\n");
  }
#endif

  on=(struct OpenNode *)MPSem->OpenList.lh_Head;
  while(on->on_Node.ln_Succ)
  {
    if((on->Flags & ON_WORKBENCH))
    {
      Remove((struct Node *)on);
      FreeOpenNode(on);
      return;
    }
    on=(struct OpenNode *)on->on_Node.ln_Succ;
  }
#ifdef ADD_DEBUG_CODE  
  if(MPSem->Debug)
  {
    kprintf("  Not Freed\n");
  }
#endif
}


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;
}




#ifdef ADD_DEBUG_CODE
#include <tagitemmacros.h>
void PrintTags(struct TagItem *tags)
{
  struct TagItem *tag,*tstate;
  

  ProcessTagList(tags,tag,tstate)
  {
    kprintf(FindTagSting(tag->ti_Tag),tag->ti_Data);
    kprintf("\n");
  }
}


ULONG TagID[]=
{
  SA_Left,
  SA_Top,
  SA_Width,
  SA_Height,
  SA_Depth,
  SA_DetailPen,
  SA_BlockPen,
  SA_Title,
  SA_Colors,
  SA_ErrorCode,
  SA_Font,
  SA_SysFont,
  SA_Type,
  SA_BitMap,
  SA_PubName,
  SA_PubSig,
  SA_PubTask,
  SA_DisplayID,
  SA_DClip,
  SA_Overscan,
  SA_Obsolete1,
  SA_ShowTitle,
  SA_Behind,
  SA_Quiet,
  SA_AutoScroll,
  SA_Pens,
  SA_FullPalette,
  SA_ColorMapEntries,
  SA_Parent,
  SA_Draggable,
  SA_Exclusive,
  SA_SharePens,
  SA_BackFill,
  SA_Interleaved,
  SA_Colors32,
  SA_VideoControl,
  SA_FrontChild,
  SA_BackChild,
  SA_LikeWorkbench,
  SA_Reserved,
  SA_MinimizeISG,
  0xffffffff,
};

UBYTE *TagStrings[]=
{
  "SA_Left            %ld",
  "SA_Top             %ld",
  "SA_Width           %ld",
  "SA_Height          %ld",
  "SA_Depth           %ld",
  "SA_DetailPen       %ld",
  "SA_BlockPen        %ld",
  "SA_Title           %s",
  "SA_Colors          %lx",
  "SA_ErrorCode       %lx",
  "SA_Font            %lx",
  "SA_SysFont         %ld",
  "SA_Type            %lx",
  "SA_BitMap          %lx",
  "SA_PubName         %s",
  "SA_PubSig          %lx",
  "SA_PubTask         %lx",
  "SA_DisplayID       %lx",
  "SA_DClip           %lx",
  "SA_Overscan        %ld",
  "SA_Obsolete1       %ld",
  "SA_ShowTitle       %ld",
  "SA_Behind          %ld",
  "SA_Quiet           %ld",
  "SA_AutoScroll      %ld",
  "SA_Pens            %lx",
  "SA_FullPalette     %ld",
  "SA_ColorMapEntries %ld",
  "SA_Parent          %lx",
  "SA_Draggable       %ld",
  "SA_Exclusive       %ld",
  "SA_SharePens       %ld",
  "SA_BackFill        %lx",
  "SA_Interleaved     %ld",
  "SA_Colors32        %lx",
  "SA_VideoControl    %lx",
  "SA_FrontChild      %lx",
  "SA_BackChild       %lx",
  "SA_LikeWorkbench   %ld",
  "SA_Reserved        %ld",
  "SA_MinimizeISG     %ld",
  "Unknown Tag        %ld"
};

UBYTE *FindTagSting(ULONG id)
{
  ULONG l;
  
  for(l=0;;l++)
  {
    if(TagID[l]==id || TagID[l]==0xffffffff)
      return(TagStrings[l]);
  }
  return(TagStrings[l]);
}

void PrintDefNode(struct DefaultNode *DN)
{
  kprintf("DefaultNode(%8lx)\n Def_Node.ln_Name: %s\n",DN,DN->Def_Node.ln_Name);
  kprintf(" Type: %ld\n ModeSelect: %ld\n ModeID: %8lx\n Width: %ld Height: %ld\n"
         " OverscanType:%ld\n AutoScroll: %ld\n Look3D: %ld\n Flags: %8lx\n "
         "OrigDisplayID: %8lx\n",
         DN->Type,DN->ModeSelect,DN->ModeID,DN->Width,DN->Height,DN->OverscanType,
         DN->AutoScroll,DN->Look3D,DN->Flags,
         DN->OrigDisplayID);
}
#endif


void CloneTextAttr(struct TTextAttr *Source, struct TTextAttr *Dest)
{
  CopyMem(Source,Dest,sizeof(struct TextAttr));
    
  if(Dest->tta_Name=AllocVec(strlen(Source->tta_Name)+1,MEMF_CLEAR|MEMF_PUBLIC))
  {
    strcpy(Dest->tta_Name,Source->tta_Name);
    if(Dest->tta_Style & FSF_TAGGED)
    {
      if(!(Dest->tta_Tags=CloneTagItems(Source->tta_Tags)))
        Dest->tta_Style &= (~FSF_TAGGED);
    }
  }
  else
  {
    Dest->tta_Name=Topaz;
    Dest->tta_YSize=8;
    Dest->tta_Style=0;
    Dest->tta_Flags=0;
  }
}


