#include "MPP.h"

// need to refresh Color display

#define MPVER  "4.6"
#define VER 4
#define REV 6


void FixScreenModeNames(void);

BOOL MyScreen;

UBYTE   Version[]   ="$VER: ModeProPrefs "MPVER" "__AMIGADATE__;
UBYTE   ModePro[]   ="ModeProPrefs "MPVER;
UBYTE   AboutText[]="ModePro\n"
                     "©1994-1995 by Michael Rivers\n"
                     "  DonationWare (see Docs)\n\n"
                     "%s\n"
                     "%s\n"
                     "  Internet:\n"
                     "    mrivers@tbag.tscs.com\n"
                     "  Mail:\n"
                     "    Michael Rivers\n"
                     "    4302 Wisconsin Court\n"
                     "    Tampa, FL, USA, 33616";


extern struct TextArea ColorDisp, PenNameDisp, FontDisp;

UBYTE EnvFile[]   ="ENV:ModePro.pref",
      EnvArcFile[]="ENVARC:ModePro.pref";

ULONG ActivateStrGad=0;
struct List PenList;
LONG ActivePen=0;
extern UBYTE PenNameGad[];
struct PenNode pennode[DRIPENS];
UWORD NumDriPens;
UWORD defaultpens[]=
{
  0,1,1,2,1,3,1,0,2,1,2,1
};
float XScale=1.0,
      YScale=1.0;
extern STRPTR MiscText[];
extern struct Hook StrHook;
extern struct Hook PenLVHook;
extern struct NewGadget nglist[];
extern ULONG gtype[];
extern ULONG gtags[];
extern struct BevelBox BBox[];
extern UBYTE PenNames[DRIPENS][32];
extern UWORD PenNumbers[];
extern struct GUI_String GText[];
extern WORD PenNameLength[],
            BevelBoxes,
            Gadgets;
struct TextAttr *TAttr, User;
struct Menu *MenuStrip;
extern struct   NewMenu nm[];      
struct TextAttr Topaz8 = { "topaz.font",8,0,0};

WORD LeftEdge,TopEdge; 

struct FontRequester *FontReq;
struct FileRequester *FileReq=NULL;
struct ScreenModeRequester *ScrReq;

APTR VI=0;
extern struct Gadget *gadlist[];
struct Gadget   *glist=0;
struct Screen   *Scr=0;
struct Window   *Win=0;
struct DrawInfo *DrawInfo;

BOOL    V39;

UBYTE   filename[513];

LONG   LVActive=0,NodeCnt=0;

ULONG  ArgEdit,ArgUse,ArgSave;
STRPTR ArgFrom,ArgPubscreen;
UBYTE  *UserFontName;
LONG   UserFontSize;

UBYTE *WindowName,
      *WinAdd,
      *Title1=" = <",
      *Title2=">";

struct Catalog *Catalog;

BOOL ClosePrefs=FALSE;
struct MPSem   *MPSem;
struct MsgPort *PrefsPort,*ReplyPort;

struct IntuitionBase *IntuitionBase; 
struct GfxBase       *GfxBase;
struct Library       *AslBase,
                     *CxBase,
                     *DiskfontBase,
                     *GadToolsBase,
                     *IconBase,
                     *IFFParseBase,
                     *LocaleBase,
                     *UtilityBase;

struct Libs MP_Libs[]=
{
  (APTR *)&AslBase,      "asl.library",        38,
  (APTR *)&CxBase,       "commodities.library",36,
  (APTR *)&DiskfontBase, "diskfont.library",   36,
  (APTR *)&GadToolsBase, "gadtools.library",   36,
  (APTR *)&GfxBase,      "graphics.library",   36,
  (APTR *)&IconBase,     "icon.library",       36,
  (APTR *)&IFFParseBase, "iffparse.library",   36,
  (APTR *)&IntuitionBase,"intuition.library",  36,
//  (APTR *)&LocaleBase,   "locale.library",     38,
  (APTR *)&UtilityBase,  "utility.library",    36,
  0,0,0
};

ULONG ListToCyc[]={1,0,2};
WORD  CurrentList_2=0,
      CurrentList=1;


void main(int argc, char **argv)
{
  ULONG l;
  struct Screen *ps;
  
  LONG gotsem=0;

  if(LocaleBase=OpenLibrary("locale.library",38))
    Catalog=OpenCatalog(NULL,(STRPTR)"modeproprefs.catalog", TAG_DONE);
  else
    Catalog=NULL;
  
  InitStrings();

  if(OpenLibs(ModePro,MP_Libs))
  {
    if(ps=LockPubScreen(NULL))
    {
      DrawInfo=GetScreenDrawInfo(ps);
      for(l=0;l<DrawInfo->dri_NumPens && l<NumDriPens;l++)
        defaultpens[l]=DrawInfo->dri_Pens[l];      
      FreeScreenDrawInfo(ps,DrawInfo);
      UnlockPubScreen(NULL,ps);
    }

    if(GetArgs(argc,argv))
    {
      if(Scr=GetScreen())
      {
        Forbid();
        MPSem=(struct MPSem *)FindSemaphore((UBYTE *)"ModePro");
        if(MPSem)
          gotsem=AttemptSemaphoreShared(&MPSem->SharedSem);
        Permit();
        
        if(!gotsem)
        {
          EZReq(0,0,ModePro,GetString(MSG_ERR_NOPATCH),GetString(MSG_REQ_OK),0);
        }
        else
        {
          if(AttemptSemaphore(&MPSem->PrefsSem))
          {
            if(MPSem->Version==VER && MPSem->Revision==REV)
            {
              
              if(ArgFrom)
              {
                //printf("ArgFrom = %s\n",ArgFrom);
                ObtainSemaphore(&MPSem->ListSem);
                ObtainSemaphore(&MPSem->NodeSem);
                FreeAllDefLists(MPSem->PromotionList);
                PrefLoadFile(ArgFrom);
                ReleaseSemaphore(&MPSem->NodeSem);
                ReleaseSemaphore(&MPSem->ListSem);
              }
              
              if(ArgEdit)
              {
                if(ReplyPort=CreateMsgPort())
                {
                  if(PrefsPort=CreateMsgPort())
                  {
                    ObtainSemaphore(&MPSem->PortSem);
                    MPSem->PrefsPort=PrefsPort;
                    ReleaseSemaphore(&MPSem->PortSem);
                    
                    gadlist[GD_LIST]=NULL;
          
                    StrHook.h_Entry=ExcludeHook;
                    PenLVHook.h_Entry=PensLVFunc;
                
                    if(((struct Library *)IntuitionBase)->lib_Version>38)
                    {
                      NumDriPens=12;
                      V39=TRUE;
                    }
                    else
                    {
                      NumDriPens=9;
                      V39=FALSE;
                    }
                    if(WinAdd=WindowName=AllocVec(strlen(MPSem->HotKey)+
                                                  strlen(GetString(MSG_WINDOW_TITLE))+
                                                  strlen(Title1)+
                                                  strlen(Title2)+1,MEMF_CLEAR|MEMF_PUBLIC))
                    {
                      strcat(WindowName,GetString(MSG_WINDOW_TITLE));
                      strcat(WindowName,Title1);
                      strcat(WindowName,MPSem->HotKey);
                      strcat(WindowName,Title2);
                    }
                    else
                      WindowName=ModePro; 
                     
  
                    SetupPenNodes();
      
                    ObtainSemaphoreShared(&MPSem->ListSem);
                    FixScreenModeNames();
                    if(ShowGUI())
                    {
                      struct Process *proc;
                      struct Window *winptr;
                      
                      proc=(struct Process *)FindTask(0);
                      winptr=proc->pr_WindowPtr;
                      proc->pr_WindowPtr=Win;
                      ProcessInput();
                      proc->pr_WindowPtr=winptr;
                      HideGUI();
                    }
                    ReleaseSemaphore(&MPSem->ListSem);
                     
                    FreeVec(WinAdd);
             
                    ObtainSemaphore(&MPSem->PortSem);
                    MPSem->PrefsPort=0;
                    ReleaseSemaphore(&MPSem->PortSem);
        
                    DeleteMsgPort(PrefsPort);
                  }// endif CreateMsgPort(PrefsPort)
                  DeleteMsgPort(ReplyPort);
                }// if CreateMsgPort(ReplyPort)
              }// endif(ArgEdit)
              else
                if(ArgSave)
                {
                  ObtainSemaphore(&MPSem->ListSem);
                  ObtainSemaphore(&MPSem->NodeSem);
                  PrefSaveFile(EnvArcFile);
                  PrefSaveFile(EnvFile);
                  ReleaseSemaphore(&MPSem->NodeSem);            
                  ReleaseSemaphore(&MPSem->ListSem);
                }
            }
            else
              EZReq(0,0,ModePro,GetString(MSG_ERR_WRONGVERSIONS),MiscText[OK],
                                         MPSem->Version,MPSem->Revision,VER,REV);          
            ReleaseSemaphore(&MPSem->PrefsSem);
          }//if(attemptsemshared()        
        }//endelse (gotsem)
        ReleaseScreen(Scr);
      }
      CleanupArgs();
    }
    CloseLibs(MP_Libs);
  } 
  if(LocaleBase)
  {
    CloseCatalog(Catalog);
    CloseLibrary(LocaleBase);
  }
}


void ProcessInput(void)
{
  struct IntuiMessage *imsg;
  ULONG  winsig, signal, prefsig, allsigs,replysig;
  
  replysig= 1 << ReplyPort->mp_SigBit;
  prefsig = 1 << PrefsPort->mp_SigBit; 
  winsig  = 1 << Win->UserPort->mp_SigBit;  
  allsigs = replysig | winsig | prefsig | SIGBREAKF_CTRL_C;
  
  while (!ClosePrefs)
  {

    signal=Wait(allsigs);
    
    if(replysig & signal)
    {
      struct MPMessage *mpm;
      while(mpm=(struct MPMessage *)GetMsg(ReplyPort))
      {
        //printf("Freeing Replied Msg %8x\n",mpm);
        FreeVec(mpm);
      }
    }
    
    
    if(SIGBREAKF_CTRL_C & signal)
      ClosePrefs=TRUE;

    if(winsig & signal)
    {
      while(imsg = GT_GetIMsg(Win->UserPort))
      {
        switch (imsg->Class)
        {
          case IDCMP_MOUSEMOVE:
            process_mousemoves(imsg);
            break;
          case IDCMP_GADGETUP:           
            process_gadgetups(imsg);
            break;
            /*
          case IDCMP_VANILLAKEY:
            Process_Keys(imsg);
            break;
            */
//          case IDCMP_CLOSEWINDOW:
//            ClosePrefs=TRUE;
//            break;
          case IDCMP_REFRESHWINDOW:
            GT_BeginRefresh(Win);
            RefreshGUI();
            GT_EndRefresh(Win,TRUE);
            break;
          case IDCMP_MENUPICK:
            process_menus(imsg);
            break;            
        }
        GT_ReplyIMsg(imsg);
      }
      {
        struct DefaultNode *n;
        
        if(n=GetActiveNode())
          switch(ActivateStrGad)
          {
            case GD_NAME:
              if(CurrentList==PL_SCREENMODES)
                ActivateStrGad=0;
            case GD_WIDTH:
            case GD_HEIGHT:
              if(n->ModeSelect!=MS_PROMOTE_SCREENMODE && n->ModeSelect!=MS_PROMOTE_REQUESTER)
                ActivateStrGad=0;
              break;
            case GD_PENVAL:
              if(!n->Look3D)
                ActivateStrGad=0;
              break;
            case GD_LOCKEDPENS:
              if(!(n->Flags & SHAREPENS))
                ActivateStrGad=0;
              break;
            case GD_PUBNAME:
              if(n->PubOptions==0)
                ActivateStrGad=0;
              break;
            case GD_HOTKEYSTR:
              if(!(n->Flags & SCRHOTKEY))
                ActivateStrGad=0;
              break;
          }
      }
      if(ActivateStrGad)
      {
        
        ActivateGadget(gadlist[ActivateStrGad],Win,NULL);
        ActivateStrGad=0;
      }
    }
    
    if(prefsig & signal)
      ProcessPrefsMessages();
  }
}       

struct TextFont *GUIFont=0;



BOOL ShowGUI(void)
{
  static ULONG firsttime=2;
  WORD WindowWidth=630,WindowHeight=204;  
  WORD zoom[4];
  ULONG skipbackdrop=2, skipgadgets=0;
  
  if(Win)
  {
    ActivateWindow(Win);
    WindowToFront(Win);
    ScreenToFront(Scr);
    return(TRUE);
  }
      
  if(VI=GetVisualInfo(Scr,TAG_END))
  {
    if(UserFontName)
    {
      User.ta_Name=UserFontName;
      User.ta_YSize=UserFontSize;
      User.ta_Style=0;
      User.ta_Flags=0;
      TAttr=&User;
    }
    else
      TAttr=Scr->Font;
    
    GetGUIScale(TAttr,GText,&XScale,&YScale);
    if(!CheckInnerWindowSize(Scr,WindowWidth,WindowHeight,XScale,YScale))
    {
      TAttr=&Topaz8;
      XScale=1;
      YScale=1;
    }
    if(GUIFont=OpenFont(TAttr))
    {
      SetupTextArea(&ColorDisp, GUIFont,   (MyScreen?0:Scr));
      SetupTextArea(&PenNameDisp, GUIFont, (MyScreen?0:Scr));
      SetupTextArea(&FontDisp, GUIFont, (MyScreen?0:Scr));
      /*
      ColorDisp_Left   *= XScale;
      ColorDisp_Right  *= XScale;
      ColorDisp_Top    *= YScale;
      ColorDisp_Bottom *= YScale;
      ColorDisp_Width =ColorDisp_Right-ColorDisp_Left;
   
      if(!MyScreen)
      {
        WORD wx,wy;
        
        wx=Scr->WBorLeft;
        wy=Scr->WBorTop + Scr->RastPort.TxHeight + 1;
        ColorDisp_Left  +=wx;
        ColorDisp_Top   +=wy;
        ColorDisp_Right +=wx;
        ColorDisp_Bottom+=wy;
      }
      ColorDisp_Baseline=(ColorDisp_Bottom-ColorDisp_Top-GUIFont->tf_YSize)/2 + GUIFont->tf_Baseline + ColorDisp_Top;
      */
          
      if(glist=MakeGadgets((MyScreen?0:Scr),VI,Gadgets,nglist,gtags,gtype,gadlist,TAttr,XScale,YScale))
      {
        WindowWidth *=XScale;
        WindowHeight*=YScale;
        zoom[2]=160;
        zoom[3]=Scr->WBorTop + Scr->RastPort.TxHeight + 1;
        if(V39)
        {
          zoom[0]=zoom[1]=~0;
        }
        else
        {
          zoom[0]=0;
          zoom[1]=zoom[3];
        }
        if(MyScreen)
        {
          skipbackdrop=0;
          skipgadgets=4;
        }
        if(Win=OpenWindowTags(NULL, 
                            WA_InnerWidth   , WindowWidth,
                            WA_InnerHeight  , WindowHeight,
                            TAG_SKIP        , firsttime,
                            WA_Left         , LeftEdge,
                            WA_Top          , TopEdge,
                            TAG_SKIP        , skipbackdrop,
                            WA_Backdrop     , MyScreen,
                            WA_Borderless   , TRUE,
                            TAG_SKIP        , skipgadgets,
                            WA_DragBar      , TRUE,
                            WA_DepthGadget  , TRUE,
                            WA_Zoom         , zoom,
                            WA_Title        , WindowName ,
                            WA_NewLookMenus , TRUE    ,
                            WA_Gadgets      , glist   ,
                            WA_AutoAdjust   , TRUE    ,
                            WA_Activate     , TRUE    ,
                            //WA_SmartRefresh , TRUE    ,
                            WA_SimpleRefresh,  TRUE    ,
                            WA_IDCMP        , MPP_IDCMP,
                            WA_PubScreen  ,   Scr  ))
        {
          SetFont(Win->RPort,GUIFont);
          FindMaxPenNameSize(TAttr);
          GT_RefreshWindow(Win,0);
          DrawBevelBoxes(Win,VI,BBox,BevelBoxes,XScale,YScale);
          firsttime=0;
          nm[4].nm_Flags =( nm[4].nm_Flags & ~CHECKED)|( MPSem->Enabled ? CHECKED:0);
           if(V39)
            nm[5].nm_Flags =( nm[5].nm_Flags & ~CHECKED)|(MPSem->EnabledNLM ? CHECKED:0);
          else
            nm[5].nm_Flags =((nm[5].nm_Flags | NM_ITEMDISABLED) & ~CHECKED);
          nm[15].nm_Flags=(nm[15].nm_Flags & ~CHECKED)|(MPSem->CatchPrograms ? CHECKED:0);
          nm[16].nm_Flags=(nm[16].nm_Flags & ~CHECKED)|(MPSem->CatchScreens ? CHECKED:0);
          nm[18].nm_Flags=(nm[18].nm_Flags & ~CHECKED)|(MPSem->CatchPopup ? CHECKED:0);
          nm[20].nm_Flags=(nm[20].nm_Flags & ~CHECKED)|(MPSem->Debug ? CHECKED:0);
          if((MenuStrip=CreateMenus(nm,TAG_END))!=NULL)
          {
            if((LayoutMenus(MenuStrip,VI,
                            GTMN_NewLookMenus,TRUE,
                            TAG_END))!=NULL)
            {          
              if((SetMenuStrip(Win,MenuStrip))!=NULL)
              {
                LVActive=0;
                
                GT_RefreshWindow(Win,NULL);
                UpdateGadgets();
                ScreenToFront(Scr);
                return(TRUE);
              }
            }
          }
        }
      }
    }
  }
  HideGUI();
  return(FALSE);
}


void HideGUI()
{
  CleanUp();
  if(Win)           
  { 
    ClearMenuStrip(Win);
    LeftEdge=Win->LeftEdge;
    TopEdge=Win->TopEdge;
    CloseWindow(Win);    
    
    Win=0;
  }
  
  if(GUIFont) CloseFont(GUIFont);
  
  /* These functions I KNOW are safe to call with a NULL */
  FreeGadgets(glist);         glist=0;
  FreeMenus(MenuStrip);       MenuStrip=0;
  FreeVisualInfo(VI);         VI=0;
}

struct Screen *GetScreen(void)
{
  struct Screen *gs;
  WORD pens[]={~0};
  ULONG dispid;
  
  MyScreen=FALSE;
  
  if(gs=LockPubScreen(ArgPubscreen))
  {
    if(gs->Height<217 || gs->Width<640)
    {
      MyScreen=TRUE;
      dispid=GetVPModeID(&(gs->ViewPort));
      UnlockPubScreen(0,gs);
      gs=OpenScreenTags(0, SA_LikeWorkbench, TRUE,
                           SA_Title        , ModePro,
                           SA_DisplayID    , dispid,
                           SA_Overscan     , OSCAN_TEXT,
                           SA_AutoScroll   , TRUE,
                           SA_Font         , &Topaz8,
                           SA_Width        , 640,
                           SA_Height       , 217,
                           SA_Depth        ,   2,
                           SA_Pens         , pens,
                           TAG_DONE);
    }
  }
  DrawInfo=GetScreenDrawInfo(gs);
  return(gs);
}

void ReleaseScreen(struct Screen *S)
{
  if(S)
  {
    FreeScreenDrawInfo(S,DrawInfo);
    if(MyScreen)
      CloseScreen(S);
    else
      UnlockPubScreen(0,S);
  }
}

void CleanUp(void)
{
  if(ScrReq)
  {
    FreeAslRequest(ScrReq);
    ScrReq=0;
  }
  if(FileReq)
  {
    FreeAslRequest(FileReq);
    FileReq=0;
  }
  if(FontReq)
  {
    FreeAslRequest(FontReq);
    FontReq=0;
  }
}

void CheckMenuItem(ULONG MenuItem, BOOL Checked);

void ProcessPrefsMessages(void)
{
  ULONG listupd=FALSE;
  struct MPMessage *mpm;

loopy:

  while(mpm=(struct MPMessage *)GetMsg(PrefsPort))
  {
    //printf("Recieved %8x - Command %d Code %d Data %8x\n",mpm,mpm->Command,mpm->Code,mpm->Data);   
    switch(mpm->Command)
    {
      case MP_QUIT:
      case MP_PREFSCLOSE:
        ClosePrefs=TRUE;
        break;
      case MP_PREFSTOFRONT:
        ScreenToFront(Scr);
        WindowToFront(Win);
        ActivateWindow(Win);
        break;
      case MP_LISTSTATUS:
        switch(mpm->Code)
        {
          case MPLS_UPDATING:
            listupd=TRUE;
            GT_SetGadgetAttrs(gadlist[GD_LIST],Win,NULL,
                         GTLV_Labels,~0,
                         TAG_DONE);
            
            ReleaseSemaphore(&MPSem->ListSem);
            break;
          case MPLS_NORMAL:
            listupd=FALSE;          
            ObtainSemaphoreShared(&MPSem->ListSem);
            LVActive=0;
            UpdateGadgets();
            break;
        }
        break;
      case MP_REFRESH:
      {
        CheckMenuItem(M_ENABLED   ,MPSem->Enabled);
        CheckMenuItem(M_ENABLENL  ,MPSem->EnabledNLM);  
        CheckMenuItem(M_CATPROG   ,MPSem->CatchPrograms);
        CheckMenuItem(M_CATSCR    ,MPSem->CatchScreens);
        CheckMenuItem(M_CATPOP    ,MPSem->CatchPopup);
        ResetMenuStrip(Win,MenuStrip);
      }
    }
    ReplyMsg((struct Message *)mpm);
  }
  if(listupd)
  {
    WaitPort(PrefsPort);
    goto loopy;
  }
}

void CheckMenuItem(ULONG MenuItem, BOOL Checked)
{
  struct MenuItem *mi;
  
  if(mi=ItemAddress(MenuStrip,MenuItem))
  {
    if(Checked)
      mi->Flags|=CHECKED;
    else
      mi->Flags&=(~CHECKED);
  }
}
    
void process_gadgetups(struct IntuiMessage *imsg)
{
  struct Gadget *gad;
  struct DefaultNode *n;
  UWORD  code,id,l;  
  
  code=imsg->Code;
  gad=(struct Gadget*)imsg->IAddress;
  id=gad->GadgetID;  
   
  switch(id)
  {
    case GD_TYPE:
      CurrentList_2=code;
      CurrentList=ListToCyc[code];
      LVActive=0;
      UpdateGadgets();
      break;

    case GD_NEW:
      if(n=AllocDefaultNode(0))
      {
        if(CurrentList!=PL_SCREENMODES)
          n->Def_Node.ln_Name=CopyString(MiscText[ITEM_NEW_NAME], MEMF_CLEAR | MEMF_PUBLIC);
        else
          n->Def_Node.ln_Name=GetModeName(0);
        
        n->Type=CurrentList;
        n->OverscanType=1;
        for(l=0;l<NumDriPens;l++)
          n->Pens[l]=defaultpens[l];
        
        ObtainSemaphore(&MPSem->NodeSem);
        GT_SetGadgetAttrs(gadlist[GD_LIST],Win,NULL,
                         GTLV_Labels,~0,
                         GTLV_Selected,0,TAG_DONE);
        AddHead(&MPSem->PromotionList[CurrentList],(struct Node *)n);
        LVActive=0;
        
        ReleaseSemaphore(&MPSem->NodeSem);
        UpdateGadgets();
        if(CurrentList!=PL_SCREENMODES)
          ActivateStrGad=GD_NAME;
      }
      break;

    case GD_SAVE:
      ClosePrefs=TRUE;
      ObtainSemaphore(&MPSem->NodeSem);
      PrefSaveFile(EnvArcFile);
      PrefSaveFile(EnvFile);
      ReleaseSemaphore(&MPSem->NodeSem);
      break;
    case GD_USE:
      ClosePrefs=TRUE;
      PrefSaveFile(EnvFile);
      break;
    case GD_CANCEL:
      ObtainSemaphore(&MPSem->NodeSem);
      GT_SetGadgetAttrs(gadlist[GD_LIST],Win,NULL,
                        GTLV_Labels,~0,TAG_DONE);
      FreeAllDefLists(MPSem->PromotionList);
      PrefLoadFile(EnvFile);
      ReleaseSemaphore(&MPSem->NodeSem);
      ClosePrefs=TRUE;
      break;
  }

  if(n=GetActiveNode())  
  switch(id)
  {
    case GD_LIST:
      LVActive=code;
      n=GetActiveNode();
      GT_SetGadgetAttrs(gadlist[GD_MOVE],Win,NULL,
                      GTSL_Max,       NodeCnt-1,
                      GTSL_Level,    (NodeCnt-1)-LVActive,
                      GA_Disabled,    FALSE,
                      TAG_DONE);
      //UpdateGadgets();
      SetDispGadgets(n);
      SetFontGadgets(n);
      SetSharedGadgets(n);
      SetPublicGadgets(n);
      SetHotKeyGadgets(n);
      SetOptionGadgets(n);
      Set3DGadgets(n);
      if(CurrentList!=PL_SCREENMODES)
        ActivateStrGad=GD_NAME;
      break;
    case GD_SELECT_NAME:
      GT_SetGadgetAttrs(gadlist[GD_LIST],Win,NULL,
                           GTLV_Labels,~0,
                           TAG_DONE);
      SelectName(n);
      GT_SetGadgetAttrs(gadlist[GD_LIST],Win,NULL,
                           GTLV_Labels,&MPSem->PromotionList[CurrentList],
                           TAG_DONE);
      break;
    case GD_NAME:
      GT_SetGadgetAttrs(gadlist[GD_LIST],Win,NULL,
                         GTLV_Labels,~0,TAG_DONE);
      if(GetGadString(gadlist[GD_NAME]))
      {
        ObtainSemaphore(&MPSem->NodeSem);
        FreeVec(n->Def_Node.ln_Name);
        if(n->Def_Node.ln_Name=AllocVec( 1+strlen(GetGadString(gadlist[GD_NAME])),MEMF_CLEAR|MEMF_PUBLIC))
          strcpy(n->Def_Node.ln_Name,GetGadString(gadlist[GD_NAME]));
        else
        {
          Remove((struct Node *)n);
          FreeDNode(n);
          UpdateGadgets();
        }
        ReleaseSemaphore(&MPSem->NodeSem);
      }
     
      GT_SetGadgetAttrs(gadlist[GD_LIST],Win,NULL,
                         GTLV_Labels,&MPSem->PromotionList[CurrentList],
                         TAG_DONE);

      break;
      
    case GD_MODESEL:
      n->ModeSelect=code;
      SetDispGadgets(n);
      //UpdateGadgets();
      break;

    case GD_SELMODE:
      switch(n->ModeSelect)
      {
        case 1:
          SelectScreenMode(Win,n,0);
          break;
        case 2:
        case 3:
          SelectScreenMode(Win,n,0);
          break;
      }
      SetDispGadgets(n);
      SetOptionGadgets(n);
      break;

    case GD_WIDTH:
      n->Width=GetGadNumber(gad);
      break;

    case GD_HEIGHT:
      n->Height=GetGadNumber(gad);
      break;

    case GD_OVERSCAN:
      n->OverscanType=code+1;
      break;

    case GD_REMOVE:
      ObtainSemaphore(&MPSem->NodeSem);
      GT_SetGadgetAttrs(gadlist[GD_LIST],Win,NULL,
                        GTLV_Labels,~0,TAG_DONE);
      if(!(n->Def_Node.ln_Succ->ln_Succ))
        if(LVActive>0)
          LVActive--;
      Remove((struct Node *)n);
      FreeDNode(n);
      ReleaseSemaphore(&MPSem->NodeSem);
      CountNodes();
      UpdateGadgets();
      break;

    case GD_LOOK3D:
      if(n->Look3D=gad->Flags & GFLG_SELECTED)
        SetPenValues(n->Pens);
      else
        SetPenValues(0);
      break;

    case GD_AUTOSCROLL:
      n->AutoScroll=gad->Flags & GFLG_SELECTED;
      break;


    case GD_PENLIST:
      ActivePen=code;
      if(n->Look3D)
      {
        ActivateStrGad=GD_PENVAL;
        SetPenValues(n->Pens);
       // ActivateGadget(gadlist[GD_PENVAL],Win,NULL);
      }
      else
        SetPenValues(0);
      break;

    case GD_PENVAL:
      n->Pens[ActivePen]=GetGadNumber(gadlist[GD_PENVAL]);
      if(imsg->Qualifier&3)
      {
        ActivePen--;
        if(ActivePen<0) ActivePen=NumDriPens-1;
      }
      else
      {
        ActivePen++;
        if(ActivePen>=NumDriPens) ActivePen=0;
      }
      ActivateStrGad=GD_PENVAL;
      SetPenValues(n->Pens);
   //   ActivateGadget(gadlist[GD_PENVAL],Win,NULL);
      break;

    case GD_RESETPENS:
      ObtainSemaphore(&MPSem->NodeSem);
      for(l=0;l<NumDriPens;l++)
        n->Pens[l]=defaultpens[l];
      ReleaseSemaphore(&MPSem->NodeSem);
      SetPenValues(n->Pens);
      break;

    case GD_PICKFONT:
      if(PickFont(Win,&n->Font))
      {
        SetFontGadgets(n);
      }
      break;

    case GD_INTERLEAVE:
      n->Flags&=(~INTERLEAVE);
      if(gad->Flags & GFLG_SELECTED)
        n->Flags|=INTERLEAVE;
      break;
      
    case GD_CENTER:
      n->CenterFlags=code;
      break;

    case GD_FASPECT:
      n->Flags&=(~FIXASPECT);
      if(gad->Flags & GFLG_SELECTED)
        n->Flags|=FIXASPECT;
      break;

    case GD_SFONT:
      n->FontType=code;
      SetFontGadgets(n);
      break;

    case GD_PUBOPT:
      if(gad->Flags & GFLG_SELECTED)
      {
        n->PubOptions=1;
        ActivateStrGad=GD_PUBNAME;
      }
      else
        n->PubOptions=0;
    
      SetPublicGadgets(n);

      break;
      
    case GD_PUBNAME:
      if(GetGadString(gadlist[GD_PUBNAME]))
      {
        ObtainSemaphore(&MPSem->NodeSem);
        FreeVec(n->PubName);
        if(n->PubName=AllocVec( 1+strlen(GetGadString(gadlist[GD_PUBNAME])),MEMF_CLEAR|MEMF_PUBLIC))
          strcpy(n->PubName,GetGadString(gadlist[GD_PUBNAME]));
        ReleaseSemaphore(&MPSem->NodeSem);
      }      
      break;
      
    case GD_DODEPTH:
      n->Flags&=(~DEPTH);
      if(gad->Flags & GFLG_SELECTED)
        n->Flags|=DEPTH;
      SetDepthGadgets(n);
      break;
      
    case GD_SHAREPENS:
      n->Flags&=(~SHAREPENS);
      if(gad->Flags & GFLG_SELECTED)
      {
        n->Flags|=SHAREPENS;
        ActivateStrGad=GD_LOCKEDPENS;
      }
      SetSharedGadgets(n);
      break;
      
    case GD_LOCKEDPENS:
      if(GetGadString(gadlist[GD_LOCKEDPENS]))
      {
        ObtainSemaphore(&MPSem->NodeSem);
        FreeVec(n->LockedPens);
        if(n->LockedPens=AllocVec( 1+strlen(GetGadString(gadlist[GD_LOCKEDPENS])),MEMF_CLEAR|MEMF_PUBLIC))
          strcpy(n->LockedPens,GetGadString(gadlist[GD_LOCKEDPENS]));
        ReleaseSemaphore(&MPSem->NodeSem);
      }      
      break;
    
    case GD_HOTKEYOPT:
      n->Flags&=(~SCRHOTKEY);
      if(gad->Flags & GFLG_SELECTED)
      {
        n->Flags|=SCRHOTKEY;
        ActivateStrGad=GD_HOTKEYSTR;
      }
      SetHotKeyGadgets(n);
      break;
      
    case GD_HOTKEYSTR:
      if(GetGadString(gadlist[GD_HOTKEYSTR]))
      {
        ObtainSemaphore(&MPSem->NodeSem);
        FreeVec(n->HotKey);
        if(n->HotKey=AllocVec( 1+strlen(GetGadString(gadlist[GD_HOTKEYSTR])),MEMF_CLEAR|MEMF_PUBLIC))
          strcpy(n->HotKey,GetGadString(gadlist[GD_HOTKEYSTR]));
        ReleaseSemaphore(&MPSem->NodeSem);
      }
      break;
    case GD_PALETTE:
      n->Flags&=(~DNF_PALETTE);
      if(gad->Flags & GFLG_SELECTED)
        n->Flags|=DNF_PALETTE;
      SetPaletteGadgets(n);
      break;
    case GD_EDITPALETTE:
      PaletteReq(n);
      break;
  } /* End Switch */  
}

void Process_Keys(struct IntuiMessage *IMsg)
{
  ULONG code,gadid;
  WORD dirchange=1;
  
  code=IMsg->Code;
  
  gadid=KeyGad(code);
  
  if(shifted) dirchange=-1;
  
  switch(gadid)
  {
    case GD_NAME:
    case GD_WIDTH:
    case GD_HEIGHT:
    case GD_LOCKEDPENS:
    case GD_PUBNAME:
    case GD_HOTKEYSTR:
    case GD_PENVAL:
      ActivateStrGad=gadid;
      break;
    case GD_TYPE:
      CurrentList_2+=dirchange;
      GD_Type(CurrentList_2);
      break;
    case GD_NEW:
      GD_New();
      break;
    case GD_SAVE:
      GD_Save();
      break;
    case GD_USE:
      GD_Use();
      break;
    case GD_CANCEL:
      GD_Cancel();
      break;
    case GD_LIST:
      LVActive+=dirchange;
      if(LVActive>=NodeCnt)
        LVActive=0;
      GD_List(LVActive);
      break;
    case GD_SELECTNAME:
      GD_SelectName(n);
      break;
    case GD_MODESEL:
      GD_ModeSel(n,n->ModeSelect+dirchange);
      break;
    case GD_SELMODE:
      GD_SelMode(n);
      break;
    case GD_OVERSCAN: 
      GD_Overscan(n,n->OverscanType+dirchange-1,TRUE);
      break;
    case GD_REMOVE:
      GD_Remove(n);
      break;
    case GD_PENLIST:
      GD_PenList(n,ActivePen+dirchange);
      break;
    case GD_RESETPENS:
      GD_ResetPens(n);
      break;
    case GD_PICKFONT:
      GD_PickFont(n);
      break;
    case GD_INTERLEAVE:
      GD_Interleave(n,!(n->Flags & INTERLEAVE),TRUE);
      break;
    case GD_LOOK3D:
      GD_Look3D(n,!(n->Look3D));
      break;
    case GD_AUTOSCROLL:
      GD_AutoScroll(n,!(n->AutoScroll),TRUE);
      break;
    case GD_RESETPENS:
      GD_ResetPens(n);
      break;
    case GD_PICKFONT:
      GD_PickFont(n);
      break;
    case GD_CENTER:
      GD_Center(n,n->CenterFlags+dirchange);
      break;
    case GD_FASPECT:
      GD_FAspect(n,!(n->Flags & FIXASPECT),TRUE);
      break;
    case GD_SFONT:
      GD_SFont(n,n->FontType+dirchange);
      break;
    case GD_PUBOPT:
      GD_PubOpt(n,!(n->PubOptions));
      break;
    case GD_DODEPTH:
      GD_DoDepth(n,!(n->Flags & DEPTH));
      break;
    case GD_SHAREPENS:
      GD_SharePens(n,!(n->Flags & SHAREPENS));
      break;
    case GD_HOTKEYOPT:
      GD_HotKeyOpt(n,!(n->Flags & SCRHOTKEY));
      break;
    case GD_PALETTE:
      GD_Palette(n,!(n->Flags & DNF_PALETTE));
      break;
    case GD_EDITPALETTE:
      GD_EditPalette(n);
      break;
    case GD_MOVE:
      GD_Move(LVActive+dirchange);
      break;
    case GD_DEPTH:
      GD_Depth(n,n->Depth+dirchange,TRUE);
      break;
  }
}

  }
}


void process_mousemoves(struct IntuiMessage *imsg)
{
  struct Gadget *gad;
  struct DefaultNode *n,*wn;
  UWORD  code,id,uplist=FALSE;  
  
  code=imsg->Code;
  gad=(struct Gadget*)imsg->IAddress;
  id=gad->GadgetID;
  if(n=GetActiveNode())
  {
    switch(id)
    {
      case GD_MOVE:
        ObtainSemaphore(&MPSem->NodeSem);
        code=(NodeCnt-1)-code;
        if(code<LVActive) uplist=TRUE;
        LVActive=code;
        if(wn=GetActiveNode())
        if(uplist) wn=(struct DefaultNode *)wn->Def_Node.ln_Pred;
          if(wn!=n)
          {
            GT_SetGadgetAttrs(gadlist[GD_LIST],Win,NULL,
                         GTLV_Labels,~0,
                         TAG_DONE);
            Remove((struct Node *)n);
            Insert(&MPSem->PromotionList[CurrentList],(struct Node *)n,(struct Node *)wn);
            GT_SetGadgetAttrs(gadlist[GD_LIST],Win,NULL,
                         GTLV_Labels,&MPSem->PromotionList[CurrentList],
                         GTLV_MakeVisible,LVActive,
                         GTLV_Selected,LVActive,TAG_DONE);

          }  
        ReleaseSemaphore(&MPSem->NodeSem); 
        break;
      case GD_DEPTH:
        n->Depth=code;
        WriteColorDisp(n);
        break;
    } /* End Switch */
  }  
}


void process_menus(struct IntuiMessage *imsg)
{
  UWORD  menunumber,ns;
  ULONG  menuid;
  struct MenuItem *mi;
  
  menunumber=imsg->Code;
  mi=ItemAddress(MenuStrip,menunumber);
  if(mi)
  do
  {
    menuid=(ULONG)(GTMENUITEM_USERDATA(mi));
    switch(menuid)
    {
      case M_OPEN:
        if(SelectFile(MiscText[LOAD_MP_PREFS],FALSE) )
        {
           ObtainSemaphore(&MPSem->NodeSem);
           GT_SetGadgetAttrs(gadlist[GD_LIST],Win,NULL,
                         GTLV_Labels,~0,TAG_DONE);
           FreeAllDefLists(MPSem->PromotionList);
           ReleaseSemaphore(&MPSem->NodeSem);
           PrefLoadFile(filename);

//           GT_SetGadgetAttrs(gadlist[GD_LIST],Win,NULL,
//                         GTLV_Labels,&MPSem->PromotionList[CurrentList],GTLV_Selected,0,TAG_DONE);
           LVActive=0;
           UpdateGadgets();
        }
        break;
        /*
      case M_SAVE:
        ObtainSemaphore(&MPSem->NodeSem);
        PrefSaveFile(EnvArcFile);
        PrefSaveFile(EnvFile);
        ReleaseSemaphore(&MPSem->NodeSem);
        break;
        */
      case M_SAVEAS:
        if(SelectFile(MiscText[SAVE_MP_PREFS],TRUE) )
        {
          PrefSaveFile(filename);     
        }
        break;
      case M_ENABLED:
        MPSem->Enabled=(mi->Flags & CHECKED ? 1:0);
        //ActivateCxObj(Broker,MPSem->Enabled);
        break;
      case M_ABOUT:
        {
          EZReq(0,0,ModePro,AboutText,MiscText[OK],(ULONG)GetString(MSG_ABOUT_TRANSLATOR),
                                                    (ULONG)GetString(MSG_ABOUT_FORINFO));
        }
        break;
      case M_HIDE:
        ClosePrefs=TRUE;
        //PrefSaveFile(EnvFile);
        break;
      case M_LASTSAVED:
        ObtainSemaphore(&MPSem->NodeSem);
        GT_SetGadgetAttrs(gadlist[GD_LIST],Win,NULL,
                                 GTLV_Labels,~0,TAG_DONE);
        FreeAllDefLists(MPSem->PromotionList);
        ReleaseSemaphore(&MPSem->NodeSem);
        PrefLoadFile(EnvArcFile);
//        GT_SetGadgetAttrs(gadlist[GD_LIST],Win,NULL,
  //                      GTLV_Labels,&MPSem->PromotionList[CurrentList],GTLV_Selected,0,TAG_DONE);
        LVActive=0;
        UpdateGadgets();
        break;   
      case M_RESTORE:
        ObtainSemaphore(&MPSem->NodeSem);
        GT_SetGadgetAttrs(gadlist[GD_LIST],Win,NULL,
                                 GTLV_Labels,~0,TAG_DONE);
        FreeAllDefLists(MPSem->PromotionList);
        ReleaseSemaphore(&MPSem->NodeSem);
        PrefLoadFile(EnvFile);
//        GT_SetGadgetAttrs(gadlist[GD_LIST],Win,NULL,
  //                      GTLV_Labels,&MPSem->PromotionList[CurrentList],GTLV_Selected,0,TAG_DONE);
        LVActive=0;
        UpdateGadgets();
        break;   
      case M_QUIT:
        SendDaemonMsg(MP_QUIT,0,0);
        break;
      case M_CATPROG:
        MPSem->CatchPrograms=(mi->Flags & CHECKED ? 1:0);
        break;
      case M_CATSCR:
        MPSem->CatchScreens=(mi->Flags & CHECKED ? 1:0);
        break;
      case M_CATPOP:
        MPSem->CatchPopup=(mi->Flags & CHECKED ? 1:0);
        break;
      case M_ENABLENL:
        MPSem->EnabledNLM=(mi->Flags & CHECKED ? 1:0);
        break;
      case M_DEBUG:
        MPSem->Debug=(mi->Flags & CHECKED ? 1:0);
    }
    ns=mi->NextSelect;
    mi=ItemAddress(MenuStrip,mi->NextSelect);
  }while(ns!= MENUNULL && mi);
}

void SetupPenNodes(void)
{
  ULONG pen;
  
  NewList(&PenList);
  for(pen=0;pen<NumDriPens;pen++)
  {
    pennode[pen].PenNumber       =PenNumbers[pen];
    pennode[pen].Pen_Node.ln_Name=PenNames[pen];
    pennode[pen].Pen_Node.ln_Succ=pennode[pen].Pen_Node.ln_Pred=0;
    AddTail(&PenList,(struct Node *)&pennode[pen]);
  }  
}

void SetPenValues(WORD *pens)
{
  ULONG pen,maxlenpng;


  GT_SetGadgetAttrs(gadlist[GD_PENLIST],Win,NULL,
                    GTLV_Labels,~0,TAG_DONE);  
  if(pens)
  {
    for(pen=0;pen<NumDriPens;pen++)
    {
      stci_d(&PenNames[pen][PenNameLength[pen]],pens[pen]);
    }
    
    GT_SetGadgetAttrs(gadlist[GD_PENVAL],Win,NULL,
                         GA_Disabled  ,FALSE,
                         GTIN_Number  ,pens[ActivePen],
                         TAG_DONE);
    GT_SetGadgetAttrs(gadlist[GD_RESETPENS],Win,NULL,
                         GA_Disabled  ,FALSE,
                         TAG_DONE);
  }
  else
  {
    for(pen=0;pen<NumDriPens;pen++)
    {
      PenNames[pen][PenNameLength[pen]]=0;
    }
    GT_SetGadgetAttrs(gadlist[GD_PENVAL],Win,NULL,
                         GA_Disabled  ,TRUE,
                         TAG_DONE);
    GT_SetGadgetAttrs(gadlist[GD_RESETPENS],Win,NULL,
                         GA_Disabled  ,TRUE,
                         TAG_DONE);

  }
  GT_SetGadgetAttrs(gadlist[GD_PENLIST],Win,NULL,
                         GTLV_Labels      ,&PenList,
                         GTLV_MakeVisible ,ActivePen,
                         GTLV_Selected    ,ActivePen,
                         GA_Disabled      ,!pens,
                         TAG_DONE);
  //GT_SetGadgetAttrs(gadlist[GD_PENNAME],Win,NULL,
  //                       GTTX_Text,NULL,TAG_DONE);
  
  
  maxlenpng=min(31,PenNameLength[ActivePen]);
  strncpy(PenNameGad,PenNames[ActivePen],maxlenpng);
  PenNameGad[maxlenpng]=0;
  //GT_SetGadgetAttrs(gadlist[GD_PENNAME],Win,NULL,
  //                       GTTX_Text,PenNameGad,TAG_DONE);
  WritePenNameDisp(PenNameGad);
}    

LONG SendDaemonMsg(ULONG Command, ULONG Code, APTR Data)
{
  LONG rv=0;
  struct MPMessage *mpm;

  if(mpm=AllocVec(sizeof(struct MPMessage),MEMF_PUBLIC|MEMF_CLEAR))
  {
    mpm->Command=Command;
    mpm->Code=Code;
    mpm->Data=Data;
    mpm->mp_Message.mn_ReplyPort=ReplyPort;

    //printf("Sending  %8x - Command %d Code %d Data %8x\n",mpm,mpm->Command,mpm->Code,mpm->Data);   
    PutMsg(MPSem->DaemonPort,(struct Message *)mpm);
    rv=1;
  }

  return(rv);
}

BOOL PrefLoadFile(STRPTR FileName)
{
  LONG error;
  BOOL rv;
  
  ObtainSemaphore(&MPSem->NodeSem);
  rv=LoadFile(MPSem->PromotionList,FileName);
  ReleaseSemaphore(&MPSem->NodeSem);
  if(error=IoErr())
  {
    UBYTE errstr[91];

    Fault(error,MiscText[LOAD_ERROR],errstr,90);
    EZReq(0,0,ModePro,errstr,MiscText[OK],0);
  }
  return(rv);
}    


BOOL PrefSaveFile(STRPTR FileName)
{
  LONG error;
  BOOL rv;
  
  ObtainSemaphore(&MPSem->NodeSem);
  rv=SaveFile(MPSem->PromotionList,FileName);
  ReleaseSemaphore(&MPSem->NodeSem);

  if(error=IoErr())
  {
    UBYTE errstr[91];

    Fault(error,MiscText[SAVE_ERROR],errstr,90);
    EZReq(0,0,ModePro,errstr,MiscText[OK],0);
  }
  return(rv);
}    

void FixScreenModeNames(void)
{
  struct DefaultNode *dn;
  STRPTR newname;

  ObtainSemaphore(&MPSem->NodeSem);
  dn=(struct DefaultNode *)MPSem->PromotionList[PL_SCREENMODES].lh_Head;
  while(dn->Def_Node.ln_Succ)
  {
    if(newname=GetModeName(dn->OrigDisplayID))
    {
      FreeVec(dn->Def_Node.ln_Name);
      dn->Def_Node.ln_Name=newname;
    }
    dn=(struct DefaultNode *)dn->Def_Node.ln_Succ;
  }
  ReleaseSemaphore(&MPSem->NodeSem);
}

void SetupTextArea(struct TextArea *TA, struct TextFont *Font, struct Screen *Screen)
{
  TA->LeftEdge   *= XScale;
  TA->RightEdge  *= XScale;
  TA->TopEdge    *= YScale;
  TA->BottomEdge *= YScale;
  TA->Width       = TA->RightEdge  - TA->LeftEdge;
  TA->Height      = TA->BottomEdge - TA->TopEdge;
  if(Screen)
  {
    WORD wx,wy;
    
    wx=Screen->WBorLeft;
    wy=Screen->WBorTop + Screen->RastPort.TxHeight + 1;
    TA->LeftEdge  +=wx;
    TA->TopEdge   +=wy;
    TA->RightEdge +=wx;
    TA->BottomEdge+=wy;
  }
  TA->Baseline=(TA->BottomEdge - TA->TopEdge - Font->tf_YSize)/2 
                      + Font->tf_Baseline + TA->TopEdge;
}
