#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 list,UBYTE *Name);
//void PrintTags(struct TagItem *tags);
//UBYTE *FindTagSting(ULONG ID);
void CloneTextAttr(struct TTextAttr *Source, struct TTextAttr *Dest);

extern ULONG CenterAll;
extern struct MPSem *MPSem;
extern CxObj  *Broker;
extern struct MsgPort *BrokerPort;
extern STRPTR MiscText[];
extern BOOL V39;
extern BYTE PublicSignal;
extern struct Process  *MPTask;
extern UWORD NumDriPens;
// extern defaultpens[];
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 struct Window ASM *(*OldOpenWindow)(REG __a0 struct NewWindow *nw,
                                             REG __a6 struct IntuitionBase *lib);
extern struct Window ASM *(*OldOpenWindowTagList)(REG __a0 struct NewWindow *nw,
                                                    REG __a1 struct TagItem *tags,
                                                    REG __a6 struct IntuitionBase *lib);
extern BOOL ASM *(*OldLayoutMenusA)(REG __a0 struct Menu *fm,
                                      REG __a1 APTR vi, 
                                      REG __a2 struct TagItem *tags,
                                      REG __a6 struct Library *lib);
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 ));
}

struct DimensionInfo diminfo;
struct DisplayInfo   dispinfo;

UBYTE *Topaz="topaz.font";

struct Screen *scr;
struct TextFont *textfont;
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;
       //likewb;
BOOL   changed,modechanged;
       
WORD   pens[]={~0},
       *screenpens;
       
struct Task *task;
struct DefaultNode *n;
struct TagItem ti[23],
              *tag;
/*
struct TagItem VCTags[2]=
{
  VC_NoColorPaletteLoad, TRUE,
  TAG_DONE,0
};
*/
              
struct TagItem fonttags[]=
{
  TA_DeviceDPI,(1<<16) | 1,TAG_DONE,0
};


ULONG  TagNum,ehbham;

struct TextAttr *storedfont;

UBYTE  CLIName[41],*taskname;
UBYTE *title;
       
struct OpenNode *ON;
 
LONG custombm;

WORD dripens[DRIPENS+1];   

struct DisplayInfo P_DispInfo;
      
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 fakedn={0};

  ObtainSemaphoreShared(&MPSem->ListSem); 
  ObtainSemaphore(&MPSem->NodeSem); 
  
#ifdef ADD_DEBUG_CODE
  if(MPSem->Debug)
  {
    kprintf("\n--------------------------------\nOpenScreen(%8lx) -- %s\n",ns,FindTask(0)->tc_Node.ln_Name);
    kprintf("  IntuitionBase=%8lx\n",IBase);
    if(ns)
    {
      kprintf("  NewScreen structure:\n");
      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;

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

  if(GetProgramName(CLIName,40)) /* Get cli program's name */
    if(CLIName[0]!=0)            /* make sure CLIName contains something */
      taskname=CLIName;
  
  /* 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)
  {
    //likewb=(ULONG)FindTagItem(SA_LikeWorkbench,TagList);
    //kprintf("\n---------\n");
    //PrintTags(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 *)&P_DispInfo,sizeof(P_DispInfo),DTAG_DISP,modeid))
    ehbham=P_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=&fakedn;
    
    fakedn.CenterFlags=MPSem->CenterAll;
  } 
    

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

  if(!wbscr)
  {
    switch(n->ModeSelect)
    {
      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;
        }
      case 0:          
        autoscroll  =n->AutoScroll;
        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;
        autoscroll  =n->AutoScroll;
        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;
            }
          }
          FreeAslRequest(sr);  
        }
        break; 
/*
      case 4:
#ifdef ADD_DEBUG_CODE
      if(MPSem->Debug)
      {
        kprintf("Promoting to PubScreen\n");
      }
#endif
  */      
    }/* end switch*/
  
    /**** Setup promoted taglist ****/


     
    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(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(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=&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(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 && 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,&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(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(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(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(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("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

  
}

struct Window __saveds ASM *NewOpenWindow(REG __a0 struct ExtNewWindow *nw,
                                          REG __a6 struct IntuitionBase *IBase)
{
  struct Window *w;
  ULONG oldflags;
  
  
#ifdef ADD_DEBUG_CODE
  if(MPSem->Debug)
  {
    kprintf("--------------------------------\nOpenWindow(%8lx) -- %s\n",nw,FindTask(0)->tc_Node.ln_Name);
  }
#endif

  oldflags=nw->Flags;
  if(MPSem->EnabledNLM)  
  {
    nw->Flags|=WFLG_NEWLOOKMENUS;
  }

  w=OldOpenWindow((struct NewWindow *)nw,IBase);
  
  nw->Flags=oldflags;
  
#ifdef ADD_DEBUG_CODE
  if(MPSem->Debug)
  {
    kprintf("  RV=%8lx\n",w);
  }
#endif
  return(w);
}

struct Window __saveds ASM *NewOpenWindowTagList(REG __a0 struct ExtNewWindow *nw,
                                                 REG __a1 struct TagItem *TagList,
                                                 REG __a6 struct IntuitionBase *IBase)
{
  struct Window *w;
  struct TagItem ti[]={WA_NewLookMenus , TRUE , 
                       TAG_DONE , 0};

//  ObtainSemaphoreShared(&MPSem->ListSem);

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

  if(MPSem->EnabledNLM)  
  {
    if(TagList)
    {
      ti[1].ti_Tag =TAG_MORE;
      ti[1].ti_Data=(ULONG)TagList;
    }
    TagList=ti;              
  }

  w=(struct Window *)OldOpenWindowTagList((struct NewWindow *)nw,TagList,IBase);

#ifdef ADD_DEBUG_CODE
  if(MPSem->Debug)
  {
    kprintf("  RV=%8lx\n",w);
  }
#endif

//  ReleaseSemaphore(&MPSem->ListSem);
  
  return(w); 
}

BOOL __saveds ASM NewLayoutMenusA(REG __a0 struct Menu *fm,
                                  REG __a1 APTR vi, 
                                  REG __a2 struct TagItem *tags)
{
  BOOL rv;
  struct TagItem ti[2]=
  {
    GTMN_NewLookMenus,TRUE,
    TAG_DONE,0
  };

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

//  ObtainSemaphoreShared(&MPSem->ListSem);

  if(MPSem->EnabledNLM)    
  {
    if(tags)
    {
      ti[1].ti_Tag=TAG_MORE;
      ti[1].ti_Data=(ULONG)tags;
    }
    rv=(BOOL)OldLayoutMenusA(fm,vi,ti,GadToolsBase);
  }
  else
    rv=(BOOL)OldLayoutMenusA(fm,vi,tags,GadToolsBase);
#ifdef ADD_DEBUG_CODE
  if(MPSem->Debug)
  {
    kprintf("  RV=%8lx\n",rv);
  }
#endif
  
//  ReleaseSemaphore(&MPSem->ListSem);
  return(rv); 
}

//void CDN(Name, Type, Width, Height, AutoScroll, ModeID, OScan, Look3D, Depth, Interleave

void CatchDNode(ULONG dest, UBYTE *Name)
{
  struct DefaultNode *dnode;
  LONG l;
  
  if(dnode=AllocDefaultNode(Name))
  {
    dnode->Type         =dest;
    dnode->Width        =width;
    dnode->Height       =height;
    dnode->AutoScroll   =autoscroll;
    dnode->ModeSelect   =0;
    dnode->ModeID       =modeid;
    dnode->OverscanType =overscan;
    dnode->Look3D       =look3d;
    dnode->Flags        =0;
    dnode->Depth        =depth;
    if(interleave)
      dnode->Flags|=INTERLEAVE;

    l=0;
    if(screenpens)
      for(;l<NumDriPens && screenpens[l]!=(~0);l++)
        dnode->Pens[l]=screenpens[l]; 

    for(;l<NumDriPens;l++)
      dnode->Pens[l]=0;//defaultpens[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;
  }
}


