#include <CrashPrefs.h>

struct Hook ChangeManyHelpHook = { {NULL}, HelpHookEntry,NULL,(APTR)HELP_CHANGEMANY};

#define CHANGENODE_AREATYPE      0
#define CHANGENODE_PATH          1
#define CHANGENODE_GROUP         2
#define CHANGENODE_AKA           3
#define CHANGENODE_DEFAULTCHRS   4
#define CHANGENODE_EXPORTCHRS    5
#define CHANGENODE_KEEPNUM       6
#define CHANGENODE_KEEPDAYS      7
#define CHANGENODE_ADDNODE       8
#define CHANGENODE_REMNODE       9

struct ChangeNode
{
   struct Node Node;
   UBYTE nodedesc[100];

   UWORD Type;
   UWORD num;

   UBYTE AreaType_AreaType;

   UBYTE Path_Path[80];

   UBYTE Group_Group;

   struct Aka *Aka_Aka;

   UBYTE *DefCHRS_DefCHRS;
   UBYTE *ExpCHRS_ExpCHRS;

   ULONG KeepNum_KeepNum;
   ULONG KeepDays_KeepDays;

   struct ConfigNode *AddNode_CNode;
   UWORD AddNode_Flags;

   struct ConfigNode *RemNode_CNode;
};

struct List Change_DoList;

struct ChangeNode *Change_CurrentNode;

STRPTR *Change_Pagenames[]={"Type","Path","Group","Aka","Default CHRS","Export CHRS",
                            "Keep num","Keep days","Add node","Remove node",NULL};

STRPTR *Change_Nodeflags[]={"Normal","Read-only","Write-only","Feed",NULL};

#define CHARSET_ASCII 1

STRPTR *Change_ExportCHRS[]={"IBMPC","SWEDISH","MAC","ASCII","LATIN-1",NULL};
UBYTE *Change_ExportData[]={AmigaToIbm,AmigaToSF7,AmigaToMac,(UBYTE *)CHARSET_ASCII,NULL,NULL};

STRPTR *Change_DefaultCHRS[]={"IBMPC","SWEDISH","DEFAULT","MAC","LATIN-1",NULL};
UBYTE *Change_DefaultData[]={IbmToAmiga,SF7ToAmiga,DefToAmiga,MacToAmiga,NULL,NULL};

STRPTR *Change_AreaTypes[]={"Pass-through","UMS","*.msg",NULL};

UBYTE Change_Akabuf[40];
UBYTE Change_Groupbuf[40];
UBYTE Change_Addnodebuf[40];
UBYTE Change_Remnodebuf[40];

extern APTR mempool;

struct LayoutHandle *changehandle;
struct Window *changewin;

UBYTE Change_SelectGroups[50];
UBYTE Change_SelectGroupsbuf[50];
UBYTE Change_SelectPattern[100]="#?";

void Change_ChangedNum(void)
{
   if(!Change_DoList.lh_Head->ln_Succ)
   {
      LT_SetAttributes(changehandle,511,GA_Disabled,TRUE,TAG_END);

      LT_SetAttributes(changehandle,100,GA_Disabled,TRUE,TAG_END);

      LT_SetAttributes(changehandle,1000,GA_Disabled,TRUE,TAG_END);
      LT_SetAttributes(changehandle,1100,GA_Disabled,TRUE,TAG_END);
      LT_SetAttributes(changehandle,1200,GA_Disabled,TRUE,TAG_END);
      LT_SetAttributes(changehandle,1300,GA_Disabled,TRUE,TAG_END);
      LT_SetAttributes(changehandle,1400,GA_Disabled,TRUE,TAG_END);
      LT_SetAttributes(changehandle,1500,GA_Disabled,TRUE,TAG_END);
      LT_SetAttributes(changehandle,1600,GA_Disabled,TRUE,TAG_END);
      LT_SetAttributes(changehandle,1700,GA_Disabled,TRUE,TAG_END);
      LT_SetAttributes(changehandle,1800,GA_Disabled,TRUE,TAG_END);
      LT_SetAttributes(changehandle,1801,GA_Disabled,TRUE,TAG_END);
      LT_SetAttributes(changehandle,1900,GA_Disabled,TRUE,TAG_END);
   }
   else
   {
      LT_SetAttributes(changehandle,511,GA_Disabled,FALSE,TAG_END);

      LT_SetAttributes(changehandle,100,GA_Disabled,FALSE,TAG_END);

      LT_SetAttributes(changehandle,1000,GA_Disabled,FALSE,TAG_END);
      LT_SetAttributes(changehandle,1100,GA_Disabled,FALSE,TAG_END);
      LT_SetAttributes(changehandle,1200,GA_Disabled,FALSE,TAG_END);
      LT_SetAttributes(changehandle,1300,GA_Disabled,FALSE,TAG_END);
      LT_SetAttributes(changehandle,1400,GA_Disabled,FALSE,TAG_END);
      LT_SetAttributes(changehandle,1500,GA_Disabled,FALSE,TAG_END);
      LT_SetAttributes(changehandle,1600,GA_Disabled,FALSE,TAG_END);
      LT_SetAttributes(changehandle,1700,GA_Disabled,FALSE,TAG_END);
      LT_SetAttributes(changehandle,1800,GA_Disabled,FALSE,TAG_END);
      LT_SetAttributes(changehandle,1801,GA_Disabled,FALSE,TAG_END);
      LT_SetAttributes(changehandle,1900,GA_Disabled,FALSE,TAG_END);
   }
}

void Change_SetCurrent(ULONG num)
{
   ULONG c;

   if(!Change_DoList.lh_Head->ln_Succ)
   {
      Change_CurrentNode=NULL;
      return;
   }

   Change_CurrentNode=(struct ChangeNode *)Change_DoList.lh_Head;

   for(c=0;c<num;c++)
      Change_CurrentNode=(struct ChangeNode *)Change_CurrentNode->Node.ln_Succ;

   LT_SetAttributes(changehandle,501,
      GTLV_Selected,    num,
      GTLV_MakeVisible, num,
      TAG_DONE);

   LT_SetAttributes(changehandle,99,LAGR_ActivePage,Change_CurrentNode->Type,TAG_END);
   LT_SetAttributes(changehandle,100,GTCY_Active,Change_CurrentNode->Type,TAG_END);

   switch(Change_CurrentNode->Type)
   {
      case CHANGENODE_AREATYPE:
         LT_SetAttributes(changehandle,1000,GTCY_Active,Change_CurrentNode->AreaType_AreaType,TAG_END);
         break;

      case CHANGENODE_PATH:
         LT_SetAttributes(changehandle,1100,GTST_String,Change_CurrentNode->Path_Path,TAG_END);
         break;

      case CHANGENODE_GROUP:
         if(Change_CurrentNode->Group_Group == 0)
            strcpy(Change_Groupbuf,"<No group>");

         else
            sprintf(Change_Groupbuf,"%lc: %s",
               Change_CurrentNode->Group_Group,cfg_GroupNames[Change_CurrentNode->Group_Group-'A']);

         LT_SetAttributes(changehandle,1200,GTTX_Text,Change_Groupbuf,TAG_END);
         break;

      case CHANGENODE_AKA:
         if(Change_CurrentNode->Aka_Aka)
            PrintFull4D(&Change_CurrentNode->Aka_Aka->Node,Change_Akabuf);

         else
            strcpy(Change_Akabuf,"No aka");

         LT_SetAttributes(changehandle,1300,GTTX_Text,Change_Akabuf,TAG_END);
         break;

      case CHANGENODE_DEFAULTCHRS:
         for(c=0;Change_DefaultCHRS[c];c++)
            if(Change_DefaultData[c]==Change_CurrentNode->DefCHRS_DefCHRS) break;

         LT_SetAttributes(changehandle,1400,GTCY_Active,c,TAG_END);
         break;

      case CHANGENODE_EXPORTCHRS:
         for(c=0;Change_ExportCHRS[c];c++)
            if(Change_ExportData[c]==Change_CurrentNode->ExpCHRS_ExpCHRS) break;

         LT_SetAttributes(changehandle,1500,GTCY_Active,c,TAG_END);
         break;

      case CHANGENODE_KEEPNUM:
         LT_SetAttributes(parthandle,1600,GTIN_Number,Change_CurrentNode->KeepNum_KeepNum,TAG_END);
         break;

      case CHANGENODE_KEEPDAYS:
         LT_SetAttributes(parthandle,1700,GTIN_Number,Change_CurrentNode->KeepDays_KeepDays,TAG_END);
         break;

      case CHANGENODE_ADDNODE:
         if(Change_CurrentNode->AddNode_CNode)
            PrintFull4D(&Change_CurrentNode->AddNode_CNode->Node,Change_Addnodebuf);

         else
            strcpy(Change_Addnodebuf,"No node");

         LT_SetAttributes(changehandle,1800,GTTX_Text,Change_Addnodebuf,TAG_END);

         if(Change_CurrentNode->AddNode_Flags & TOSSNODE_READONLY)
            LT_SetAttributes(parthandle,1801,GTCY_Active,1,TAG_END);

         else if(Change_CurrentNode->AddNode_Flags & TOSSNODE_WRITEONLY)
            LT_SetAttributes(parthandle,1801,GTCY_Active,2,TAG_END);

         else if(Change_CurrentNode->AddNode_Flags & TOSSNODE_FEED)
            LT_SetAttributes(parthandle,1801,GTCY_Active,3,TAG_END);

         else
            LT_SetAttributes(parthandle,1801,GTCY_Active,0,TAG_END);

         break;

      case CHANGENODE_REMNODE:
         if(Change_CurrentNode->RemNode_CNode)
            PrintFull4D(&Change_CurrentNode->RemNode_CNode->Node,Change_Remnodebuf);

         else
            strcpy(Change_Remnodebuf,"No node");

         LT_SetAttributes(changehandle,1900,GTTX_Text,Change_Remnodebuf,TAG_END);
         break;

   }
}

void Change_SetSelectGroups(void)
{
   if(Change_SelectGroups[0]==0)
      strcpy(Change_SelectGroupsbuf,"<Any group>");

   else
      strcpy(Change_SelectGroupsbuf,Change_SelectGroups);

   LT_SetAttributes(changehandle,11,GTTX_Text,Change_SelectGroupsbuf,TAG_END);
}

void Change_MakeDesc(struct ChangeNode *chnode)
{
   UBYTE buf[50],buf2[50];
   ULONG c;
   
   switch(chnode->Type)
   {
      case CHANGENODE_AREATYPE:
         sprintf(chnode->nodedesc,"Type: %s",Change_AreaTypes[chnode->AreaType_AreaType]);
         break;

      case CHANGENODE_PATH:
         sprintf(chnode->nodedesc,"Path: %s",chnode->Path_Path);
         break;

      case CHANGENODE_GROUP:
         if(chnode->Group_Group == 0)
            strcpy(buf,"<No group>");

         else
            sprintf(buf,"%lc: %s",
               chnode->Group_Group,cfg_GroupNames[chnode->Group_Group-'A']);

         sprintf(chnode->nodedesc,"Group: %s",buf);
         break;

      case CHANGENODE_AKA:
         if(chnode->Aka_Aka)
            PrintFull4D(&chnode->Aka_Aka->Node,buf);

         else
            strcpy(buf,"No aka");

         sprintf(chnode->nodedesc,"Aka: %s",buf);
         break;

      case CHANGENODE_DEFAULTCHRS:
         for(c=0;Change_DefaultCHRS[c];c++)
            if(Change_DefaultData[c]==Change_CurrentNode->DefCHRS_DefCHRS) break;

         sprintf(chnode->nodedesc,"Default CHRS: %s",Change_ExportCHRS[c]);
         break;

      case CHANGENODE_EXPORTCHRS:
         for(c=0;Change_ExportCHRS[c];c++)
            if(Change_ExportData[c]==Change_CurrentNode->ExpCHRS_ExpCHRS) break;

         sprintf(chnode->nodedesc,"Export CHRS: %s",Change_ExportCHRS[c]);
         break;

      case CHANGENODE_KEEPNUM:
         sprintf(chnode->nodedesc,"Keep num: %ld",Change_CurrentNode->KeepNum_KeepNum);
         break;

      case CHANGENODE_KEEPDAYS:
         sprintf(chnode->nodedesc,"Keep days: %ld",Change_CurrentNode->KeepDays_KeepDays);
         break;

      case CHANGENODE_ADDNODE:
         if(chnode->AddNode_CNode)
            PrintFull4D(&chnode->AddNode_CNode->Node,buf);

         else
            strcpy(buf,"No node");

         if(chnode->AddNode_Flags & TOSSNODE_READONLY)
            strcpy(buf2,"Read-only");

         else if(chnode->AddNode_Flags & TOSSNODE_WRITEONLY)
            strcpy(buf2,"Write-only");

         else if(chnode->AddNode_Flags & TOSSNODE_FEED)
            strcpy(buf2,"Feed");

         else
            strcpy(buf2,"Normal");

         sprintf(chnode->nodedesc,"Add node: %s, %s",buf,buf2);
         break;

      case CHANGENODE_REMNODE:
         if(chnode->RemNode_CNode)
            PrintFull4D(&chnode->RemNode_CNode->Node,buf);

         else
            strcpy(buf,"No node");

         sprintf(chnode->nodedesc,"Remove node: %s",buf);
         break;
   }
}

void Change_UpdateDesc(struct ChangeNode *chnode)
{
   LT_SetAttributes(changehandle,501,GTLV_Labels,~0,TAG_END);
   Change_MakeDesc(chnode);
   LT_SetAttributes(changehandle,501,GTLV_Labels,&Change_DoList,TAG_END);
}

void Change_RenumberNodes(void)
{
   ULONG num;
   struct ChangeNode *chnode;

   num=0;

   for(chnode=(struct ChangeNode *)Change_DoList.lh_Head;chnode->Node.ln_Succ;chnode=(struct ChangeNode *)chnode->Node.ln_Succ)
      chnode->num=num++;
}

void Change_Add(void)
{
   struct ChangeNode *chnode;

   if(!(chnode=AllocMem(sizeof(struct ChangeNode),MEMF_CLEAR)))
   {
      DisplayBeep(NULL);
      return;
   }

   LT_SetAttributes(changehandle,501,GTLV_Labels,~0,TAG_END);

   chnode->Node.ln_Name=chnode->nodedesc;
   Change_MakeDesc(chnode);
   AddTail(&Change_DoList,(struct Node *)chnode);
   Change_RenumberNodes();

   LT_SetAttributes(changehandle,501,GTLV_Labels,&Change_DoList,TAG_END);

   chnode=(struct ChangeNode *)Change_DoList.lh_TailPred;

   Change_ChangedNum();
   Change_SetCurrent(chnode->num);
}

void Change_Remove(void)
{
   ULONG tmp;

   tmp=Change_CurrentNode->num;

   if(!Change_CurrentNode->Node.ln_Succ->ln_Succ)
      tmp--;

   LT_SetAttributes(changehandle,501,GTLV_Labels,~0,TAG_END);
   Remove((struct Node *)Change_CurrentNode);
   FreeMem(Change_CurrentNode,sizeof(struct ChangeNode));
   LT_SetAttributes(changehandle,501,GTLV_Labels,&Change_DoList,TAG_END);

   Change_RenumberNodes();
   Change_ChangedNum();
   Change_SetCurrent(tmp);
}

void MakePath(UBYTE *dest,UBYTE *ctrl,UBYTE *path,ULONG max)
{
   ULONG c,d,e;

   d=0;
   for(c=0;c<strlen(ctrl) && d!=max-1;c++)
   {
      if(ctrl[c]=='%' && (ctrl[c+1]|32)=='s')
      {
         for(e=0;e<strlen(path) && d!=max-1;e++)
            dest[d++]=path[e];

         c++;
      }
      else dest[d++]=ctrl[c];
   }
   dest[d]=0;
}

void DoChange(void)
{
   struct Area *area;
   struct TossNode *tnode;
   UBYTE parsedpattern[400];
   BOOL changed;
   ULONG changedareas,unalteredareas;
   UBYTE buf[300];
   UBYTE newpath[80];
   struct ChangeNode *chnode;

   changedareas=0;
   unalteredareas=0;

   if(ParsePatternNoCase(Change_SelectPattern,parsedpattern,400)==-1)
   {
      rtEZRequestTags("Invalid pattern","Ok",NULL,NULL,
            RT_Underscore,'_',
            RT_Window,changewin,
            RT_WaitPointer,TRUE,
            RT_LockWindow, TRUE,
             TAG_END);

      return;
   }

   for(area=(struct Area *)AreaList.First;area;area=area->Next)
   {
      if(!(area->Flags & AREA_BAD) && !(area->Flags & AREA_DEFAULT) && !(area->Flags & AREA_NETMAIL))
      {
         if(MatchPatternNoCase(parsedpattern,area->Tagname) && (Change_SelectGroups[0] == 0 || CheckFlags(area->Group,Change_SelectGroups)))
         {
            changed=FALSE;

            for(chnode=(struct ChangeNode *)Change_DoList.lh_Head;chnode->Node.ln_Succ;chnode=(struct ChangeNode *)chnode->Node.ln_Succ)
            {
               switch(chnode->Type)
               {
                  case CHANGENODE_AREATYPE:
                     if(chnode->AreaType_AreaType != area->AreaType)
                     {
                        area->AreaType=chnode->AreaType_AreaType;
                        changed=TRUE;
                     }
                     break;

                  case CHANGENODE_PATH:
                     MakePath(newpath,chnode->Path_Path,area->Tagname,80);

                     if(strcmp(newpath,area->Path) != 0)
                     {
                        strcpy(area->Path,newpath);
                        changed=TRUE;
                     }
                     break;

                  case CHANGENODE_GROUP:
                     if(chnode->Group_Group != area->Group)
                     {
                        area->Group=chnode->Group_Group;
                        changed=TRUE;
                     }
                     break;

                  case CHANGENODE_AKA:
                     if(chnode->Aka_Aka && chnode->Aka_Aka != area->Aka)
                     {
                        area->Aka=chnode->Aka_Aka;
                        changed=TRUE;
                     }
                     break;

                  case CHANGENODE_DEFAULTCHRS:
                     if(chnode->DefCHRS_DefCHRS != area->DefaultCHRS)
                     {
                        area->DefaultCHRS=chnode->DefCHRS_DefCHRS;
                     }
                     break;

                  case CHANGENODE_EXPORTCHRS:
                     if(chnode->ExpCHRS_ExpCHRS != area->ExportCHRS)
                     {
                        area->ExportCHRS=chnode->ExpCHRS_ExpCHRS;
                     }
                     break;

                  case CHANGENODE_KEEPNUM:
                     if(chnode->KeepNum_KeepNum != area->KeepNum)
                     {
                        area->KeepNum=chnode->KeepNum_KeepNum;
                     }
                     break;

                  case CHANGENODE_KEEPDAYS:
                     if(chnode->KeepDays_KeepDays != area->KeepDays)
                     {
                        area->KeepDays=chnode->KeepDays_KeepDays;
                     }
                     break;

                  case CHANGENODE_ADDNODE:
                     if(chnode->AddNode_CNode)
                     {
                        for(tnode=(struct TossNode *)area->TossNodes.First;tnode;tnode=tnode->Next)
                           if(tnode->ConfigNode == chnode->AddNode_CNode) break;
                  
                        if(!tnode)
                        {
                           if(tnode=AllocMem(sizeof(struct TossNode),MEMF_CLEAR))
                           {
                              tnode->ConfigNode=chnode->AddNode_CNode;
                              tnode->Flags|=chnode->AddNode_Flags;
                              jbAddNode(&area->TossNodes,(struct jbNode *)tnode);
                              changed=TRUE;
                           }
                        }
                     }
                     break;

                  case CHANGENODE_REMNODE:
                     if(chnode->RemNode_CNode)
                     {
                        for(tnode=(struct TossNode *)area->TossNodes.First;tnode;tnode=tnode->Next)
                           if(tnode->ConfigNode == chnode->RemNode_CNode) break;

                        if(tnode)
                        {
                           jbFreeNode(&area->TossNodes,(struct jbNode *)tnode,sizeof(struct TossNode));
                           changed=TRUE;
                        }
                     }
                     break;
               }
            }

            if(changed) changedareas++;
            else        unalteredareas++;
         }
      }
   }
   
   sprintf(buf,"%lu areas were changed.\n%lu areas matched but were unaltered.",
      changedareas,unalteredareas);

   rtEZRequestTags(buf,"Ok",NULL,NULL,RT_Underscore,'_',
                                      RT_Window,changewin,
                                      RT_WaitPointer,TRUE,
                                      RT_LockWindow, TRUE,
                                      RTEZ_Flags, EZREQF_CENTERTEXT,
                                      TAG_END);

   if(changedareas)
      saveconfig=TRUE;
}

void ChangeAreas(void)
{
   struct IntuiMessage *IntuiMessage;
   APTR iaddress;
   ULONG class,code,qualifier;
   struct Aka *aka;
   UBYTE group;
   struct Change *chnode;
   struct ConfigNode *cnode;

   NewList(&Change_DoList);

   changehandle = LT_CreateHandleTags(scr,LH_EditHook,     &StrEditHook,
                                          LH_RawKeyFilter, FALSE,
                                          TAG_DONE);

   if(!changehandle)
      return;

   LT_New(changehandle,
      LA_Type, VERTICAL_KIND,
      TAG_DONE);

      LT_New(changehandle,
         LA_Type,      HORIZONTAL_KIND,
         LA_LabelText, "Select",
         LAGR_Spread,TRUE,
         TAG_DONE);

         LT_New(changehandle,
            LA_Type, VERTICAL_KIND,
            TAG_DONE);

            LT_New(changehandle,
               LA_LabelText,     "Pattern",
               LA_Chars,         40,
               LA_Type,          STRING_KIND,
               GTST_MaxChars,    99,
               LA_ID,            10,
               LA_STRPTR,        Change_SelectPattern,
               TAG_DONE);

            LT_New(changehandle,
               LA_LabelText,     "Groups",
               LA_Chars,         40,
               LA_Type,          TEXT_KIND,
               LATX_Picker,      TRUE,
               GTTX_Border,      TRUE,
               LA_ID,            11,
               TAG_DONE);

         LT_EndGroup(changehandle);

         LT_New(changehandle,
            LA_Type, HORIZONTAL_KIND,
            TAG_DONE);

            LT_New(changehandle,
               LA_Type,      YBAR_KIND,
               TAG_DONE);

         LT_EndGroup(changehandle);

         LT_New(changehandle,
            LA_Type, HORIZONTAL_KIND,
            TAG_DONE);

            LT_New(changehandle,
               LA_Type,      BUTTON_KIND,
               LA_LabelText, "Change!",
               LA_ID,        15,
               TAG_DONE);

         LT_EndGroup(changehandle);

      LT_EndGroup(changehandle);

      LT_New(changehandle,
         LA_Type,      VERTICAL_KIND,
         LA_LabelText, "Change",
         TAG_DONE);

         LT_New(changehandle,
            LA_Type,      VERTICAL_KIND,
            TAG_DONE);

            LT_New(changehandle,
               LA_Type,       LISTVIEW_KIND,
               LALV_Lines,    5,
               LALV_CursorKey,TRUE,
               LA_ID,         501,
               LA_Chars,      60,
               LALV_Link,     NIL_LINK,
               LALV_LockSize, TRUE,
               TAG_DONE);

            LT_New(changehandle,
               LA_Type,      HORIZONTAL_KIND,
               LAGR_SameSize,TRUE,
               LAGR_Spread,  TRUE,
               TAG_DONE);

               LT_New(changehandle,
                  LA_Type,      BUTTON_KIND,
                  LA_LabelText, "Add",
                  LA_Chars,     30,
                  LA_ID,        510,
                  TAG_DONE);

               LT_New(changehandle,
                  LA_Type,      BUTTON_KIND,
                  LA_LabelText, "Remove",
                  LA_Chars,     30,
                  LA_ID,        511,
                  TAG_DONE);

            LT_EndGroup(changehandle);

         LT_EndGroup(changehandle);

         LT_New(changehandle,
            LA_Type,      XBAR_KIND,
            TAG_DONE);

         LT_New(changehandle,
            LA_Type,      VERTICAL_KIND,
            TAG_DONE);

            LT_New(changehandle,
               LA_Type,          CYCLE_KIND,
               LA_ID,            100,
               GTCY_Labels,      Change_Pagenames,
               TAG_DONE);

            LT_New(changehandle,
                LA_Type,      VERTICAL_KIND,
                LA_ID,        99,
                LAGR_ActivePage,0,
                TAG_DONE);

               LT_New(changehandle,
                  LA_Type,      VERTICAL_KIND,
                  TAG_DONE);

                  LT_New(changehandle,
                     LA_Type,      VERTICAL_KIND,
                     TAG_DONE);

                     LT_New(changehandle,
                        LA_Type,          CYCLE_KIND,
                        LA_LabelText,     "Type",
                        GTCY_Labels,      Change_AreaTypes,
                        LA_ID,            1000,
                        TAG_DONE);

                  LT_EndGroup(changehandle);

               LT_EndGroup(changehandle);

               LT_New(changehandle,
                  LA_Type,      VERTICAL_KIND,
                  TAG_DONE);

                  LT_New(changehandle,
                     LA_Type,      VERTICAL_KIND,
                     TAG_DONE);

                     LT_New(changehandle,
                        LA_LabelText,     "Path",
                        LA_Chars,         50,
                        LA_Type,          STRING_KIND,
                        GTST_MaxChars,    79,
                        LAST_Picker,      TRUE,
                        LA_ID,            1100,
                        TAG_DONE);

                  LT_EndGroup(changehandle);

               LT_EndGroup(changehandle);

               LT_New(changehandle,
                  LA_Type,      VERTICAL_KIND,
                  TAG_DONE);

                  LT_New(changehandle,
                     LA_Type,      VERTICAL_KIND,
                     TAG_DONE);

                     LT_New(changehandle,
                        LA_LabelText,     "Group",
                        LA_Chars,         20,
                        LA_Type,          TEXT_KIND,
                        LATX_Picker,      TRUE,
                        GTTX_Border,      TRUE,
                        LA_ID,            1200,
                        TAG_DONE);

                  LT_EndGroup(changehandle);

               LT_EndGroup(changehandle);

               LT_New(changehandle,
                  LA_Type,      VERTICAL_KIND,
                  TAG_DONE);

                  LT_New(changehandle,
                     LA_Type,      VERTICAL_KIND,
                     TAG_DONE);

                     LT_New(changehandle,
                        LA_LabelText,     "Aka",
                        LA_Chars,         20,
                        LA_Type,          TEXT_KIND,
                        LATX_Picker,      TRUE,
                        GTTX_Border,      TRUE,
                        LA_ID,            1300,
                        TAG_DONE);

                  LT_EndGroup(changehandle);

               LT_EndGroup(changehandle);

               LT_New(changehandle,
                  LA_Type,      VERTICAL_KIND,
                  TAG_DONE);

                  LT_New(changehandle,
                     LA_Type,      VERTICAL_KIND,
                     TAG_DONE);

                     LT_New(changehandle,
                        LA_Type,          CYCLE_KIND,
                        LA_LabelText,     "Default CHRS",
                        GTCY_Labels,      Change_DefaultCHRS,
                        LA_ID,            1400,
                        TAG_DONE);

                  LT_EndGroup(changehandle);

               LT_EndGroup(changehandle);

               LT_New(changehandle,
                  LA_Type,      VERTICAL_KIND,
                  TAG_DONE);

                  LT_New(changehandle,
                     LA_Type,      VERTICAL_KIND,
                     TAG_DONE);

                     LT_New(changehandle,
                        LA_Type,          CYCLE_KIND,
                        LA_LabelText,     "Export CHRS",
                        GTCY_Labels,      Change_ExportCHRS,
                        LA_ID,            1500,
                        TAG_DONE);

                  LT_EndGroup(changehandle);

               LT_EndGroup(changehandle);

               LT_New(changehandle,
                  LA_Type,      VERTICAL_KIND,
                  TAG_DONE);

                  LT_New(changehandle,
                     LA_Type,      VERTICAL_KIND,
                     TAG_DONE);

                     LT_New(changehandle,
                        LA_Type,          INTEGER_KIND,
                        LA_LabelText,     "Keep num",
                        GTCY_Labels,      Change_ExportCHRS,
                        LA_Chars,         5,
                        LA_ID,            1600,
                        TAG_DONE);

                  LT_EndGroup(changehandle);

               LT_EndGroup(changehandle);

               LT_New(changehandle,
                  LA_Type,      VERTICAL_KIND,
                  TAG_DONE);

                  LT_New(changehandle,
                     LA_Type,      VERTICAL_KIND,
                     TAG_DONE);

                     LT_New(changehandle,
                        LA_Type,          INTEGER_KIND,
                        LA_LabelText,     "Keep days",
                        LA_Chars,         5,
                        GTCY_Labels,      Change_ExportCHRS,
                        LA_ID,            1700,
                        TAG_DONE);

                  LT_EndGroup(changehandle);

               LT_EndGroup(changehandle);


               LT_New(changehandle,
                  LA_Type,      VERTICAL_KIND,
                  TAG_DONE);

                  LT_New(changehandle,
                     LA_Type,      HORIZONTAL_KIND,
                     TAG_DONE);

                     LT_New(changehandle,
                        LA_LabelText,     "Add node",
                        LA_Chars,         20,
                        LA_Type,          TEXT_KIND,
                        LATX_Picker,      TRUE,
                        GTTX_Border,      TRUE,
                        LA_ID,            1800,
                        TAG_DONE);

                     LT_New(changehandle,
                        LA_Type,          CYCLE_KIND,
                        GTCY_Labels,      Change_Nodeflags,
                        LA_ID,            1801,
                        TAG_DONE);

                  LT_EndGroup(changehandle);

               LT_EndGroup(changehandle);

               LT_New(changehandle,
                  LA_Type,      VERTICAL_KIND,
                  TAG_DONE);

                  LT_New(changehandle,
                     LA_Type,      VERTICAL_KIND,
                     TAG_DONE);

                     LT_New(changehandle,
                        LA_LabelText,     "Remove node",
                        LA_Chars,         20,
                        LA_Type,          TEXT_KIND,
                        LATX_Picker,      TRUE,
                        GTTX_Border,      TRUE,
                        LA_ID,            1900,
                        TAG_DONE);

                  LT_EndGroup(changehandle);

               LT_EndGroup(changehandle);

            LT_EndGroup(changehandle);

         LT_EndGroup(changehandle);

      LT_EndGroup(changehandle);

   LT_EndGroup(changehandle);

   changewin=LT_Build(changehandle,LAWN_IDCMP,    IDCMP_CLOSEWINDOW|IDCMP_RAWKEY,
                                   LAWN_Parent,   partwin,
                                   LAWN_HelpHook, &ChangeManyHelpHook,
                                   LAWN_Title,    "Change areas",
                                   WA_Flags,      WFLG_ACTIVATE|WFLG_CLOSEGADGET|WFLG_DEPTHGADGET|WFLG_DRAGBAR|WFLG_NEWLOOKMENUS,
                                   TAG_END);

   if(!changewin)
   {
      LT_DeleteHandle(changehandle);
      DisplayBeep(NULL);
      return;
   }

   Change_SetCurrent(0);
   Change_ChangedNum();

   Change_SetSelectGroups();

   for(;;)
   {
      while(IntuiMessage=(struct IntuiMessage *)LT_GetIMsg(changehandle))
      {
         class=IntuiMessage->Class;
         code=IntuiMessage->Code;
         iaddress=IntuiMessage->IAddress;
         qualifier=IntuiMessage->Qualifier;

         LT_ReplyIMsg(IntuiMessage);

         switch(class)
         {
            case IDCMP_IDCMPUPDATE:    if(((struct Gadget *)iaddress)->GadgetID == 11)
                                       {
                                          if(EditGroups(Change_SelectGroups,"Edit groups",changewin))
                                             Change_SetSelectGroups();
                                       }

                                       if(Change_CurrentNode)
                                       {
                                          switch(((struct Gadget *)iaddress)->GadgetID)
                                          {
                                             case 1100:
                                               OpenReqDir(Change_CurrentNode->Path_Path,79,"Select directory",changewin);
                                               Change_UpdateDesc(Change_CurrentNode);
                                               Change_SetCurrent(Change_CurrentNode->num);
                                               break;

                                             case 1200:
                                               group=AskGroup(changewin,"<No group>");

                                               if(group != -1)
                                               {
                                                   Change_CurrentNode->Group_Group=group;
                                                   Change_UpdateDesc(Change_CurrentNode);
                                                   Change_SetCurrent(Change_CurrentNode->num);
                                               }
                                               break;

                                             case 1300:
                                                if(aka=AskAka(changewin))
                                                {
                                                   Change_CurrentNode->Aka_Aka=aka;
                                                   Change_UpdateDesc(Change_CurrentNode);
                                                   Change_SetCurrent(Change_CurrentNode->num);
                                                }
                                                break;

                                             case 1800:
                                                if(cnode=AskCNode(changewin))
                                                {
                                                   Change_CurrentNode->AddNode_CNode=cnode;
                                                   Change_UpdateDesc(Change_CurrentNode);
                                                   Change_SetCurrent(Change_CurrentNode->num);
                                                }
                                                break;

                                             case 1900:
                                                if(cnode=AskCNode(changewin))
                                                {
                                                   Change_CurrentNode->RemNode_CNode=cnode;
                                                   Change_UpdateDesc(Change_CurrentNode);
                                                   Change_SetCurrent(Change_CurrentNode->num);
                                                }
                                                break;
                                          }
                                       }
                                       break;

            case IDCMP_GADGETUP:       /* No current node necessary */

                                       switch(((struct Gadget *)iaddress)->GadgetID)
                                       {
                                          case 510:
                                             Change_Add();
                                             break;

                                          case 15:
                                             LT_UpdateStrings(changehandle);
                                             DoChange();
                                             break;
                                       }

                                       /* Current node necessary */

                                       if(Change_CurrentNode)
                                       {
                                          switch(((struct Gadget *)iaddress)->GadgetID)
                                          {
                                             case 100:
                                                Change_CurrentNode->Type=code;
                                                Change_UpdateDesc(Change_CurrentNode);
                                                Change_SetCurrent(Change_CurrentNode->num);
                                                break;

                                             case 1000:
                                                Change_CurrentNode->AreaType_AreaType=code;
                                                Change_UpdateDesc(Change_CurrentNode);
                                                Change_SetCurrent(Change_CurrentNode->num);
                                                break;

                                             case 1100:
                                                strncpy(Change_CurrentNode->Path_Path,(UBYTE *)LT_GetAttributes(changehandle,1100,TAG_END),79);
                                                Change_CurrentNode->Path_Path[79]=0;
                                                Change_UpdateDesc(Change_CurrentNode);
                                                Change_SetCurrent(Change_CurrentNode->num);
                                                break;

                                             case 1400:
                                                Change_CurrentNode->DefCHRS_DefCHRS=Change_DefaultData[code];
                                                Change_UpdateDesc(Change_CurrentNode);
                                                Change_SetCurrent(Change_CurrentNode->num);
                                                break;

                                             case 1500:
                                                Change_CurrentNode->ExpCHRS_ExpCHRS=Change_ExportData[code];
                                                Change_UpdateDesc(Change_CurrentNode);
                                                Change_SetCurrent(Change_CurrentNode->num);
                                                break;

                                             case 1600:
                                                Change_CurrentNode->KeepNum_KeepNum=(ULONG)LT_GetAttributes(changehandle,1600,TAG_END);
                                                Change_UpdateDesc(Change_CurrentNode);
                                                Change_SetCurrent(Change_CurrentNode->num);
                                                break;

                                             case 1700:
                                                Change_CurrentNode->KeepDays_KeepDays=(ULONG)LT_GetAttributes(changehandle,1700,TAG_END);
                                                Change_UpdateDesc(Change_CurrentNode);
                                                Change_SetCurrent(Change_CurrentNode->num);
                                                break;

                                             case 1801:
                                                if(code == 0)
                                                   Change_CurrentNode->AddNode_Flags=0;

                                                if(code == 1)
                                                   Change_CurrentNode->AddNode_Flags = TOSSNODE_READONLY;

                                                if(code == 2)
                                                   Change_CurrentNode->AddNode_Flags = TOSSNODE_WRITEONLY;

                                                if(code == 3)
                                                   Change_CurrentNode->AddNode_Flags = TOSSNODE_FEED;

                                                Change_UpdateDesc(Change_CurrentNode);
                                                Change_SetCurrent(Change_CurrentNode->num);
                                                break;

                                             case 501:
                                                Change_SetCurrent(code);
                                                break;

                                             case 511:
                                                Change_Remove();
                                                break;

                                          }
                                      }
                                      break;

            case IDCMP_CLOSEWINDOW:   LT_DeleteHandle(changehandle);
                                      changehandle=NULL;

                                      while(chnode=(struct Change *)RemTail(&Change_DoList))
                                       FreeMem(chnode,sizeof(struct ChangeNode));

                                      return;

         }
      }
      WaitPort(changewin->UserPort);
   }
}


/* lockwindow */