#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

#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);

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

UBYTE *Topaz="topaz.font";

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

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

struct Screen ASM __saveds  *NewOpenScreenTagList(REG __a0 struct ExtNewScreen *ns,
                                                  REG __a1 struct TagItem *TagList,
                                                  REG __a6 struct IntuitionBase *IBase)
{
  struct OpenNode *ON;
  struct BitMap *bitmap;
  struct Rectangle odclip;
  struct DefaultNode *n;
  struct DefaultNode workdn={0},
                     centeralldn={0};
  UBYTE  *title;
  LONG   custombm,wbscr;
  BOOL   changed,modechanged;
  WORD   pens[]={~0},
         *screenpens,
         dripens[DRIPENS+1];         
  ULONG  tagnum,ehbham;

  struct Screen *scr;
  struct DimensionInfo diminfo;
  struct DisplayInfo   dispinfo;
  
  struct ScreenModeRequester *sr;
  
  struct ColorSpec Colors4[257];
  ULONG  Colors32[256*3+2];
  
  struct Task *task;
  UBYTE  cli_name[41],*taskname;

  struct TagItem ti[23],
                *tag;

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


  ObtainSemaphoreShared(&MPSem->ListSem); 
  ObtainSemaphore(&MPSem->NodeSem); 
  
#ifdef ADD_DEBUG_CODE
  if(MPSem->Debug)
  {
    kprintf("\n---------------%s-----------------\nOpenScreenX()\n",ns,FindTask(0)->tc_Node.ln_Name);
    kprintf("  IntuitionBase=%8lx\n",IBase);
    if(ns)
    {
      kprintf("  struct NewScreen %8lx\n",ns);
      kprintf("    LeftEdge=%7ld TopEdge=%7ld\n    Width=%7ld    Height=%7ld\n    Depth=%7ld\n   dpen=%7ld     bpen=%7ld\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)
    {
      kprintf("  TagList\n");
      PrintTags(TagList);
    }
    kprintf("..................................\n");
  }
#endif
  
  /* Now that we've got the semaphore all globals are mine */
  /* initialize everything */

  tagnum=0;

  title=NULL;

  ON=NULL;   //likewb=0;
  
  custombm=changed=modechanged=workdn.Look3D=workdn.OverscanType=workdn.Flags=0;
  workdn.Depth  =1;
  
  wbscr=0;  
  workdn.Flags=0;
  
  workdn.Width= workdn.Height= workdn.AutoScroll= workdn.ModeID= -1;
 
  workdn.Pens[0]=~0;
  screenpens=workdn.Pens;
  
  task=FindTask(0);
  taskname=task->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;
    workdn.Width    =ns->Width;
    workdn.Height   =ns->Height;
    workdn.ModeID   =ns->ViewModes;
    workdn.Depth    =ns->Depth;
    title           =ns->DefaultTitle;
    custombm        =ns->Type & CUSTOMBITMAP;
    wbscr           =(ns->Type & SCREENTYPE)==WBENCHSCREEN;
  }

  if(TagList)
  {
    custombm            =GetTagData(SA_BitMap           ,custombm               ,TagList);
    workdn.Width        =GetTagData(SA_Width            ,workdn.Width           ,TagList);
    workdn.Height       =GetTagData(SA_Height           ,workdn.Height          ,TagList);
    workdn.AutoScroll   =GetTagData(SA_AutoScroll       ,workdn.AutoScroll      ,TagList);
    workdn.OverscanType =GetTagData(SA_Overscan         ,workdn.OverscanType    ,TagList);
    workdn.ModeID       =GetTagData(SA_DisplayID        ,workdn.ModeID          ,TagList);
    workdn.Depth        =GetTagData(SA_Depth            ,workdn.Depth           ,TagList);
    workdn.Flags       =(GetTagData(SA_Interleaved      ,workdn.Flags & INTERLEAVE,TagList) ? INTERLEAVE : 0);
    title      =(UBYTE *)GetTagData(SA_Title            ,(ULONG)title           ,TagList);
    wbscr              =(GetTagData(SA_Type             ,wbscr                  ,TagList) & SCREENTYPE)==WBENCHSCREEN;

    if(tag=FindTagItem(SA_Overscan,TagList))
      if(!FindTagItem(SA_DClip,TagList))
        workdn.OverscanType=tag->ti_Data;
    if(tag=FindTagItem(SA_Pens,TagList))
    {
      LONG pcounter=0;
      
      screenpens=(UWORD *)(tag->ti_Data);
      if(screenpens)
      {
        for(pcounter=0;pcounter<DRIPENS && screenpens[pcounter]!=~0;pcounter++)
          workdn.Pens[pcounter]=screenpens[pcounter];
      }
/************************************************************************************/
//      workdn.Pens[pcounter]=~0;
    }
  }

  n=NULL;

  ehbham=0;

  if(GetDisplayInfoData(0, (UBYTE *)&dispinfo, sizeof(dispinfo), DTAG_DISP, workdn.ModeID))
    ehbham=dispinfo.PropertyFlags & (DIPF_IS_DUALPF | DIPF_IS_HAM | 
                                     DIPF_IS_PF2PRI | DIPF_IS_EXTRAHALFBRITE);
  
#ifdef ADD_DEBUG_CODE
  if(MPSem->Debug)
  {
    kprintf("..................................\n");
    kprintf("\n    wbscr=%lx\n",wbscr);
    kprintf("..................................\n");
  }
#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  mode_monall,orig_monall;
      
      //modenorm    =workdn.ModeID;// & ~HAM_EHB_DP_KEY;
      mode_monall  =workdn.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 == workdn.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,&workdn);
      if(MPSem->CatchScreens) 
        CatchDNode(1,title,&workdn);
    }
  }
  
#ifdef ADD_DEBUG_CODE
  if(MPSem->Debug)
  {
    if(n)
      PrintDefNode(n);
    kprintf("..................................\n");
  }
#endif

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

  if(!MPSem->Enabled || !n)
  {
    scr=OldOpenScreenTagList(ns,TagList,IBase);
    ReleaseSemaphore(&MPSem->ListSem);
    ReleaseSemaphore(&MPSem->NodeSem);
    return(scr);
  }
  
  workdn.Look3D     =n->Look3D;
  workdn.Flags     |=( n->Flags & INTERLEAVE );
  screenpens        =n->Pens;

  if(!wbscr)
  {
    switch(n->ModeSelect)
    {
      case 1:
#ifdef ADD_DEBUG_CODE
      if(MPSem->Debug)
      {
        kprintf("Promoting Monitor\n");
        kprintf("..................................\n");
      }
#endif  
        if(workdn.ModeID > -1)
        {
          if(V39)
          {
            workdn.ModeID=BestModeID(BIDTAG_SourceID,workdn.ModeID,
                              BIDTAG_MonitorID      ,n->ModeID & MONITOR_ID_MASK,
                              BIDTAG_Depth          ,workdn.Depth,
                              BIDTAG_DIPFMustHave   ,ehbham,
                              TAG_SKIP              ,(workdn.Width==-1 ? 1:0),
                              BIDTAG_DesiredWidth   ,workdn.Width,
                              TAG_SKIP              ,(workdn.Height==-1 ? 1:0),
                              BIDTAG_DesiredHeight  ,workdn.Height,
                              TAG_DONE);
          }
          else
          {
            workdn.ModeID= (n->ModeID & MONITOR_ID_MASK) | (workdn.ModeID & (~MONITOR_ID_MASK));
          }
          if(workdn.ModeID==INVALID_ID) 
             workdn.ModeID=n->ModeID;
              
          modechanged=TRUE;
        }
      case 0:          
        workdn.AutoScroll  =n->AutoScroll;
        break;
      case 2:
#ifdef ADD_DEBUG_CODE
      if(MPSem->Debug)
      {
        kprintf("Promoting ScreenMode\n");
        kprintf("..................................\n");
      }
#endif  
        workdn.ModeID       =n->ModeID;
        workdn.OverscanType =n->OverscanType;
        workdn.Width        =n->Width;
        workdn.Height       =n->Height;
        workdn.AutoScroll   =n->AutoScroll;
        workdn.Depth        =n->Depth;
        workdn.Flags        |=n->Flags & n->Depth;
        changed=TRUE;
        break;
      case 3:
#ifdef ADD_DEBUG_CODE
      if(MPSem->Debug)
      {
        kprintf("Promoting with Requester\n");
        kprintf("..................................\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))
          {
            workdn.ModeID    =sr->sm_DisplayID | ehbham;
            workdn.OverscanType  =sr->sm_OverscanType;
            workdn.Width     =sr->sm_DisplayWidth;
            workdn.Height    =sr->sm_DisplayHeight;    
            changed   =TRUE;
            workdn.Depth  =sr->sm_DisplayDepth;
            workdn.Flags  |=n->Flags & DEPTH;
          }
          FreeAslRequest(sr);  
        }
        break; 
    }/* end switch*/
  
    /**** Setup promoted taglist ****/
     
    if( (n->Flags & DNF_FORCEPLANAR)  && 
        (workdn.Width  > 0)           && 
        (workdn.Height > 0)           &&
        (!custombm)                   &&
        (V39)                         &&
        (workdn.Depth  > 0)  )
    {

      if(bitmap=AllocBitMap(workdn.Width,workdn.Height,workdn.Depth,BMF_CLEAR|BMF_DISPLAYABLE,0))
      {
        if(ON=AllocOpenNode(ON))
        {
          ON->Flags|=ON_BITMAP;
        
          ON->BitMap=bitmap;
          ti[tagnum].ti_Tag=SA_BitMap;
          ti[tagnum].ti_Data=(ULONG)bitmap;
          tagnum++;
        }
        else
          FreeBitMap(bitmap);
      }
#ifdef ADD_DEBUG_CODE
      if(MPSem->Debug)
      {
        kprintf("  Force Planar: Bitmap %8lx\n",bitmap);
      }
#endif
    }
    
  
    if(changed && !(custombm))
    {
      if(workdn.Width!=0)
      {
        ti[tagnum].ti_Tag=SA_Width;
        ti[tagnum].ti_Data=workdn.Width;
        tagnum++;
      }
      if(workdn.Height!=0)
      {
        ti[tagnum].ti_Tag=SA_Height;
        ti[tagnum].ti_Data=workdn.Height;
        tagnum++;
      }
      
      if(FindTagItem(SA_DClip,TagList))
      { // if it specifies a dclip, i need to override it.
        if(QueryOverscan(workdn.ModeID,&odclip,workdn.OverscanType))
        {
          ti[tagnum].ti_Tag=SA_DClip;
          ti[tagnum].ti_Data=(ULONG)&odclip;
          tagnum++;
        }
      }
      else
      {
        ti[tagnum].ti_Tag=SA_Overscan;
        ti[tagnum].ti_Data=workdn.OverscanType;
        tagnum++;
      }
    }
  
    if(modechanged || changed)
    {
      ti[tagnum].ti_Tag=SA_DisplayID;
      ti[tagnum].ti_Data=workdn.ModeID;
      tagnum++;
    }

    if(n->Flags & SHAREPENS)
    {
      ti[tagnum].ti_Tag=SA_SharePens;
      ti[tagnum].ti_Data=TRUE;
      tagnum++;
    }

    if((workdn.Flags & DEPTH) && !(custombm) && !(ehbham))
    {
      ti[tagnum].ti_Tag=SA_Depth;
      ti[tagnum].ti_Data=workdn.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(ON=AllocOpenNode(ON))
          {
            ON->Flags|=ON_FONT;
          
            ti[tagnum].ti_Tag  =SA_Font;
            ti[tagnum].ti_Data =(ULONG)&ON->TA;
            tagnum++;
  
            if(n->Flags & FIXASPECT && workdn.ModeID != -1)
            {
              if(GetDisplayInfoData(NULL,(UBYTE *)&dispinfo,sizeof(dispinfo),DTAG_DISP,workdn.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,&ON->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(ON=AllocOpenNode(ON))
        {
          struct OpenNode *won;
          UBYTE number[8];
          ULONG cnt=1,len;
          
          strncpy(ON->PubName,n->PubName,MAXPUBSCREENNAME);
          ON->PubName[MAXPUBSCREENNAME]=0;
          len=strlen(ON->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);        
              ON->PubName[len]=0;
              strncat(ON->PubName,number,MAXPUBSCREENNAME);
              ON->PubName[MAXPUBSCREENNAME]=0;
            }
            
            if(0==strcmp(ON->PubName,won->PubName))
            {
              won=(struct OpenNode *)MPSem->OpenList.lh_Head;
              cnt++;
            }
            else
              won=(struct OpenNode *)won->on_Node.ln_Succ;
          }
          
          ON->PubName[MAXPUBSCREENNAME]=0;
          ON->Flags|=ON_PUBLIC|ON_OPEN;
          
          ti[tagnum].ti_Tag=SA_Title;
          ti[tagnum].ti_Data=(ULONG)ON->PubName;
          tagnum++;
  
          ti[tagnum].ti_Tag=SA_PubName;
          ti[tagnum].ti_Data=(ULONG)ON->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(!(ON->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)
            {
              ON->Flags|=ON_FONT;
  
              CloneTextAttr(ot,&ON->TA);
  
              ti[tagnum].ti_Tag =SA_Font;
              ti[tagnum].ti_Data=(ULONG)&ON->TA;
              tagnum++;
            }
          }
        }
      }
    }

  }/* end if !wbscr */
  else  /* Yes, this is the Workbench screen */
  {
    if(ON=AllocOpenNode(ON))
      ON->Flags|=ON_WORKBENCH;
  }

  if(workdn.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(workdn.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,workdn.ModeID))
    {
      if(n->CenterFlags & 1)
      {
        if(workdn.Width>-1)
        {
          ti[tagnum].ti_Tag=SA_Left;
          ti[tagnum].ti_Data=((diminfo.StdOScan.MaxX-diminfo.StdOScan.MinX)-workdn.Width)/2;
          tagnum++;
        }
      }
      if(n->CenterFlags & 2)
      {
        if(workdn.Height>-1)
        {
          ti[tagnum].ti_Tag=SA_Top;
          ti[tagnum].ti_Data=((diminfo.StdOScan.MaxY-diminfo.StdOScan.MinY)-workdn.Height)/2;
          tagnum++;
        }
      }
    }
  }

  if(n->Flags & SCRHOTKEY)
  {
    if(ON=AllocOpenNode(ON))
    {
      if(ON->HotKey=AllocVec(strlen(n->HotKey)+1,MEMF_CLEAR|MEMF_PUBLIC))
      {
        strcpy(ON->HotKey,n->HotKey);
        ON->Cx=AddHotKey(Broker,BrokerPort,ON->HotKey,(ULONG)ON);
      }
    }
  }
  

  if((workdn.Flags & INTERLEAVE) && !(custombm))
  {
    ti[tagnum].ti_Tag=SA_Interleaved;
    ti[tagnum].ti_Data=TRUE;
    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(ON)
  {
    if(ON->Flags & ON_FONT)
      textfont=OpenDiskFont((struct TextAttr *)&ON->TA);
  }
#ifdef ADD_DEBUG_CODE  
  if(MPSem->Debug)
  {
    kprintf("  NewTags\n");
    PrintTags(ti);
    kprintf("..................................\n");
    kprintf("Opening\n");
  }
#endif

  scr=OldOpenScreenTagList(ns,ti,IBase);

#ifdef ADD_DEBUG_CODE  
  if(MPSem->Debug)
  {
    kprintf("Screen Addr %8lx\n",scr);
  }
#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:
       //     kprintf("obtaining %d\n",num);
            ObtainPen(cm,num,0,0,0, PEN_EXCLUSIVE | PEN_NO_SETCOLOR);
            break;
          case 2:
            for(num2=num1+1;num2<=num;num2++)
            {
         //     kprintf("obtaining %d\n",num2);
              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(ON)
  {
    if(ON->Flags & ON_FONT)
      if(textfont)
        CloseFont(textfont);
    
    if(scr)
    {
      ON->Screen=scr;
      if(ON->Flags & ON_PUBLIC)
      {
        if(n->PubOptions == 1)
        {
          PubScreenStatus(scr,0);
        }
      }
      AddHead(&MPSem->OpenList,(struct Node *)ON);
    }
    else
      FreeOpenNode(ON);
  }
  
/*
  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;
  }
}


