/*----------------------------------------------------------------------*
  gfunc.c Version 3.0 - © Copyright 1990-91 Jaba Development

  Author : Jan van den Baard
  Purpose: functions called by user via menu and keyboard
 *----------------------------------------------------------------------*/

extern struct Window        *MainWindow;
extern struct Screen        *MainScreen;
extern struct RastPort      *MainRP;
extern struct FileSelector  *IODir;
extern struct Library       *SysBase;
extern struct GadgetList     Gadgets;
extern struct ge_prefs       prefs;
extern struct Gadget         TextGadget;
extern struct NewWindow      nw_main;
extern struct MemoryChain    Memory;
extern struct SharedList     Images;
extern ULONG                 IDCMPFlags, WindowFlags, Class;
extern BOOL                  Saved, REQUESTER, WBSCREEN;
extern USHORT                FrontPen, Code, GadgetCount, id, BackFill;
extern USHORT                Colors[32],DEPTH, WDBackFill;
extern SHORT                 MainX,MainY,text_num;
extern UBYTE                 name[256], wdt[80], wlb[MAXLABEL];

struct Gadget *wait_for_gadget();

BOOL    bo_added            = TRUE;

/*
 * switch on/off the coords.
 */
void switch_coords( long how )
{
    Forbid();
    if(NOT how) {
        if(TestBits((ULONG)prefs.flag_bits,GP_COORDS))
            MainWindow->Flags &= ~REPORTMOUSE;
    } else {
        if(TestBits((ULONG)prefs.flag_bits,GP_COORDS))
            MainWindow->Flags |= REPORTMOUSE;
    }
    Permit();
}

/*
 * remove all 'BORDERONLY' gadgets from the edit window
 * so they won't interferre with your editing
 */
void rem_bo( void )
{
    register struct MyGadget *g;

    if(NOT Gadgets.Head->Succ) return;

    if(bo_added) {
        for(g = Gadgets.Head; g->Succ; g = g->Succ) {
            if(TestBits((ULONG)g->SpecialFlags,BORDERONLY)) {
                bo_added = FALSE;
                RemoveGList(MainWindow,&g->Gadget,1);
            }
        }
    }
}

/*
 * put back all 'BORDERONLY' gadgets in the edit window
 * so they may be selected to be moved, re-sized, deleted,
 * copied and edited
 */
void add_bo( void )
{
    register struct MyGadget *g;

    if(NOT Gadgets.Head->Succ) return;

    if(NOT bo_added) {
        for(g = Gadgets.Head; g->Succ; g = g->Succ) {
            if(TestBits((ULONG)g->SpecialFlags,BORDERONLY)) {
                bo_added = TRUE;
                AddGList(MainWindow,&g->Gadget,-1L,1,NULL);
            }
        }
    }
}

/*
 * remove all normal gadgets from the edit window
 * so they won't interferre with text placing and gadget resizing.
 */
void rem_no( void )
{
    register struct MyGadget *g;

    if(NOT Gadgets.Head->Succ) return;

    for(g = Gadgets.Head; g->Succ; g = g->Succ) {
        if(NOT TestBits((ULONG)g->SpecialFlags,BORDERONLY))
            RemoveGList(MainWindow,&g->Gadget,1);
    }
}

/*
 * put back all normal gadgets in the edit window
 * so they may be selected to be moved, re-sized, deleted,
 * copied and edited
 */
void add_no( void )
{
    register struct MyGadget *g;

    if(NOT Gadgets.Head->Succ) return;

    for(g = Gadgets.Head; g->Succ; g = g->Succ) {
        if(NOT TestBits((ULONG)g->SpecialFlags,BORDERONLY))
            AddGList(MainWindow,&g->Gadget,-1L,1,NULL);
    }
}

/*
 * refresh the complete display
 */
void refresh( void )
{
    USHORT br,bt,bb,bl;

    Forbid();
    while(read_msg(MainWindow));
    Permit();

    ModifyIDCMP(MainWindow,SIZEVERIFY);

    buisy();

    SetDrMd(MainRP,JAM1);

    add_bo();

    if(REQUESTER) {
        SetAPen(MainRP,BackFill);
        RectFill(MainRP,0,0,MainWindow->GZZWidth,MainWindow->GZZHeight);
        RefreshWindowFrame(MainWindow);
    } else {
        RefreshWindowFrame(MainWindow);
        SetAPen(MainRP,WDBackFill);
        br = MainWindow->BorderRight;
        bt = MainWindow->BorderTop;
        bb = MainWindow->BorderBottom;
        bl = MainWindow->BorderLeft;
        if(SysBase->lib_Version < 36)
            RectFill(MainRP,bl-2,bt-1,MainWindow->Width-bl+1,MainWindow->Height-2);
        else
            RectFill(MainRP,bl,bt,MainWindow->Width-br-1,MainWindow->Height-bb-1);

        RefreshGList(MainWindow->FirstGadget,MainWindow,NULL,-1L);
    }
    if(TextGadget.GadgetText) PrintIText(MainRP,TextGadget.GadgetText,0,0);
    rem_bo();

    ok();

    if(NOT strlen(&wdt[0]))
        SetWindowTitles(MainWindow,(char *)-1L,(char *)TITLE);
    else
        SetWindowTitles(MainWindow,(char *)&wdt[0],(char *)TITLE);

    Forbid();
    while(read_msg(MainWindow));
    Permit();

    ModifyIDCMP(MainWindow,nw_main.IDCMPFlags);
}

/*
 * get the pointer to the MyGadget structure in which gadget 'g'
 * is defined
 */
struct MyGadget *get_mg( struct Gadget *g )
{
    register struct MyGadget *ret;

    for(ret = Gadgets.Head; ret ->Succ; ret = ret->Succ)
        if(g == &ret->Gadget) return(ret);
}

/*
 * check to see if there are already gadgets on the
 * edit window that are not 'BORDERONLY'
 */
long is_gadget( void )
{
    register struct MyGadget *tmp;

    for(tmp = Gadgets.Head; tmp->Succ ; tmp = tmp->Succ) {
        if(NOT TestBits((ULONG)tmp->SpecialFlags,BORDERONLY)) return(TRUE);
    }
    return(FALSE);
}

/*
 * make a copy of a gadget
 */
void copy_gadget( void )
{
    struct Gadget     *gad;
    struct MyGadget   *gadget, *mg;
    struct Border     *border,*border1;
    struct StringInfo *sinfo, *sinfo1;
    struct PropInfo   *pinfo;
    struct Image      *image, *image1;
    struct IntuiText  *to, *tn, *tnl;
    SHORT              x,y,w,h,xo,yo,ls,ds;
    ULONG              ps;

    if(NOT Gadgets.Head->Succ) return;

    add_bo();
    sst("PICK GADGET TO COPY....");
    if(NOT(gad = wait_for_gadget(MainWindow))) {
        rem_bo();
        return;
    }

    rem_bo();
    rem_no();

    Saved = FALSE;
    mg    = get_mg(gad);

    if(NOT(gadget = (struct MyGadget *)Alloc(&Memory,(ULONG)sizeof(struct MyGadget)))) {
        Error("Out of Memory !");
        return;
    }

    un_grel(MainWindow,gad);
    CopyMem((void *)gad,(void *)&gadget->Gadget,sizeof(struct Gadget));

    gadget->Gadget.GadgetText   = NULL;
    gadget->Gadget.GadgetRender = NULL;
    gadget->Gadget.SelectRender = NULL;
    gadget->Gadget.SpecialInfo  = NULL;
    gadget->Gadget.LeftEdge     = gad->LeftEdge + 5;
    gadget->Gadget.TopEdge      = gad->TopEdge  + 5;
    gadget->SpecialFlags        = mg->SpecialFlags;

    if(TestBits((ULONG)gadget->SpecialFlags,USERLABEL))
        gadget->SpecialFlags       ^= USERLABEL;

    GadgetCount++;

    if(NOT TestBits((ULONG)gad->GadgetType,PROPGADGET)) {
        if((NOT TestBits((ULONG)gad->Flags,GADGIMAGE)) OR
           (NOT prefs.image_copy)) {
            border = (struct Border *)gad->GadgetRender;
            if((NOT TestBits((ULONG)gadget->SpecialFlags,BORDERONLY)) AND
               (NOT TestBits((ULONG)gadget->SpecialFlags,NOBORDER))) {
                AddUser(border);
                gadget->Gadget.GadgetRender = (APTR)border;
            } else {
                if(NOT add_border(gadget))
                    goto NoMem;
                ((struct Border *)gadget->Gadget.GadgetRender)->FrontPen = border->FrontPen;
                if(TestBits((ULONG)gadget->SpecialFlags,OS20BORDER))
                    ((struct Border *)gadget->Gadget.GadgetRender)->NextBorder->FrontPen = border->NextBorder->FrontPen;
            }
        }
        if(TestBits(gadget->SpecialFlags,OS20HIGHBORDER)) {
            border  = (struct Border *)gad->SelectRender;
            AddUser(border);
            gadget->Gadget.SelectRender = (APTR)border;
        }
    } else {
        if(NOT(pinfo = (struct PropInfo *)Alloc(&Memory,(ULONG)sizeof(struct PropInfo))))
            goto NoMem;
        CopyMem((void *)gad->SpecialInfo,(void *)pinfo,sizeof(struct PropInfo));

        if((NOT(TestBits((ULONG)gad->Flags,GADGIMAGE))) OR
           (prefs.image_copy == FALSE)) {
            if(NOT(gadget->Gadget.GadgetRender = Alloc(&Memory,(ULONG)sizeof(struct Image))))
                goto NoMem;
            pinfo->Flags |= AUTOKNOB;
        }
        gadget->Gadget.SpecialInfo = (APTR)pinfo;
    }

    if((TestBits((ULONG)gad->Flags,GADGIMAGE)) AND (prefs.image_copy == TRUE)) {
        image = (struct Image *)gad->GadgetRender;
        add_user(image);
        gadget->Gadget.GadgetRender = (APTR)image;
    } else if((TestBits((ULONG)gad->Flags,GADGIMAGE)) AND (prefs.image_copy == FALSE))
        gadget->Gadget.Flags ^= GADGIMAGE;

    if((TestBits((ULONG)gad->Flags,GADGHIMAGE)) AND
       (prefs.image_copy == TRUE) AND
       (NOT TestBits((ULONG)gad->Flags,GADGHBOX)) AND
       (NOT TestBits((ULONG)gadget->SpecialFlags,OS20HIGHBORDER))) {
        image = (struct Image *)gad->SelectRender;
        add_user(image);
        gadget->Gadget.SelectRender = (APTR)image;
    } else if((TestBits((ULONG)gad->Flags,GADGHIMAGE)) AND
              (NOT TestBits(gadget->SpecialFlags,OS20HIGHBORDER)) AND
              (prefs.image_copy == FALSE)) {
        gadget->Gadget.SelectRender = NULL;
        gadget->Gadget.Flags ^= GADGHIMAGE;
    }

    if((gad->GadgetText) AND (prefs.text_copy == TRUE)) {
        to = gad->GadgetText;
        if(NOT(tn = (struct IntuiText *)Alloc(&Memory,(ULONG)sizeof(struct IntuiText))))
            goto NoMem;
        CopyMem((char *)to,(char *)tn,(ULONG)sizeof(struct IntuiText));
        if(NOT(tn->IText = (UBYTE *)Alloc(&Memory,80L)))
            goto NoMem;
        CopyMem((char *)to->IText,(char *)tn->IText,80L);
        gadget->Gadget.GadgetText = tn;
        if(to = to->NextText) {
            while(1) {
                if(NOT(tnl = (struct IntuiText *)Alloc(&Memory,(ULONG)sizeof(struct IntuiText))))
                    goto NoMem;
                CopyMem((char *)to,(char *)tnl,(ULONG)sizeof(struct IntuiText));
                if(NOT(tnl->IText = (UBYTE *)Alloc(&Memory,80L)))
                    goto NoMem;
                CopyMem((char *)to->IText,(char *)tnl->IText,80L);
                tn->NextText = tnl;
                tn = tnl;
                if(NOT(to = to->NextText)) break;
            }
        }
    }

    if((TestBits((ULONG)gad->GadgetType,STRGADGET))) {
        sinfo1 = (struct StringInfo *)gad->SpecialInfo;
        if(NOT(sinfo = (struct StringInfo *)Alloc(&Memory,(ULONG)sizeof(struct StringInfo))))
            goto NoMem;
        CopyMem((void *)sinfo1,(void *)sinfo,sizeof(struct StringInfo));
        if(NOT(sinfo->Buffer = (UBYTE *)Alloc(&Memory,sinfo->MaxChars)))
            goto NoMem;
        CopyMem((void *)sinfo1->Buffer,(void *)sinfo->Buffer,sinfo->MaxChars);
        if(sinfo->UndoBuffer) {
            if(NOT(sinfo1->UndoBuffer = (UBYTE *)Alloc(&Memory,sinfo->MaxChars)))
                goto NoMem;
        }
        gadget->Gadget.SpecialInfo = (APTR)sinfo;
    }

    switch_coords(FALSE);
    set_info(0);
    x = gadget->Gadget.LeftEdge-1;
    y = gadget->Gadget.TopEdge-1;
    w = gadget->Gadget.Width+1;
    h = gadget->Gadget.Height+1;
    SetDrMd(MainRP,COMPLEMENT);
    SetAPen(MainRP,FrontPen);
    draw_box(MainWindow,x,y,x+w,y+h);
    do_info(0,x,y,x+w,y+h);
    xo = MainX-x;
    yo = MainY-y;

    while(Code != SELECTDOWN) {
        while(read_msg(MainWindow)) {
            if(Class == MENUPICK) set_info(0);
            do_info(0,x,y,x+w,y+h);
        }
        get_xy(&MainX,&MainY);
        if((MainX != (x + xo)) OR (MainY != (y + yo))) {
            draw_box(MainWindow,x,y,x+w,y+h);
            x = MainX - xo;
            y = MainY - yo;
            draw_box(MainWindow,x,y,x+w,y+h);
            do_info(0,x,y,x+w,y+h);
        }
    }

    gadget->Gadget.LeftEdge = x+1;
    gadget->Gadget.TopEdge  = y+1;
    AddHead((void *)&Gadgets,(void *)gadget);
    grel(MainWindow,&gadget->Gadget);
    grel(MainWindow,gad);
    add_no();
    switch_coords(TRUE);
    renumber();
    refresh();
    return;
NoMem:
    FreeGadget(gadget);
    Error("Out of Memory !");
}

/*
 * delete a gadget
 */
void delete( void )
{
    struct Gadget   *gd;
    struct MyGadget *gadget;
    USHORT           i=0;

    if(NOT Gadgets.Head->Succ) return;

    add_bo();
    sst("PICK GADGET TO DELETE.....");
    if(NOT(gd = wait_for_gadget(MainWindow))) {
        rem_bo();
        return;
    }

    Saved = FALSE;

    for(gadget = Gadgets.Head; gadget->Succ; gadget = gadget->Succ) {
        if(gd == &gadget->Gadget) {
            Remove((void *)gadget);
            un_grel(MainWindow,gd);
            RemoveGList(MainWindow,gd,1);
            FreeGadget(gadget);
            break;
        }
    }
    GadgetCount--;
    renumber();
    rem_bo();
    refresh();
}

/*
 * Get a IFF ILBM brush as gadget render
 */
void render( void )
{
    struct MyGadget *mg;
    struct Gadget   *gadget;
    struct PropInfo *info;
    struct Border   *border;
    struct Image    *image, *image1, *image_bank();
    ULONG            Pos, ps, rc;

    if(NOT Gadgets.Head->Succ) return;
    if(NOT is_gadget()) return;
    sst("PICK GADGET TO RENDER.....");
    if(NOT(gadget = wait_for_gadget(MainWindow))) return;

    if(TestBits((ULONG)gadget->Flags,GADGIMAGE)) {
        if(Ask("Gadget already has an Image !",
               "Do you wish to over-write it ?") == FALSE) return;
    }

    Saved = FALSE;

    if(NOT(image = image_bank(TRUE)))
        return;

    add_user(image);

    disable_window();

    mg = get_mg(gadget);

    Pos = RemoveGList(MainWindow,gadget,1);
    un_grel(MainWindow,gadget);

    if(TestBits((ULONG)gadget->Flags,GADGIMAGE)) {
        image1 = (struct Image *)gadget->GadgetRender;
        rem_user(image1);
    } else if(TestBits((ULONG)gadget->GadgetType,PROPGADGET))
        FreeItem(&Memory,gadget->GadgetRender,(long)sizeof(struct Image));
    else {
        FreeRender(mg);
        if(TestBits((ULONG)mg->SpecialFlags,OS20HIGHBORDER)) {
            mg->SpecialFlags ^= OS20HIGHBORDER;
            mg->SpecialFlags ^= OS20BORDER;
            gadget->Flags    ^= GADGHIMAGE;
        }
    }

    if(NOT(TestBits((ULONG)gadget->GadgetType,PROPGADGET))) {
        if(prefs.auto_size) {
            gadget->Width  = image->Width;
            gadget->Height = image->Height;
        }
    } else {
        info = (struct PropInfo *)gadget->SpecialInfo;
        info->Flags ^= AUTOKNOB;
    }

    gadget->Flags       |= GADGIMAGE;
    gadget->GadgetRender = (APTR)image;
    grel(MainWindow,gadget);
    AddGList(MainWindow,gadget,Pos,1,NULL);
    enable_window();
    refresh();
}

/*
 * read an IFF ILBM brush as select render
 */
void sel_render( void )
{
    struct MyGadget *mg;
    struct Gadget   *gadget;
    struct PropInfo *info;
    struct Image    *image, *image1, *image_bank();
    ULONG            Pos, ps, rc;

    if(NOT Gadgets.Head->Succ) return;
    if(NOT is_gadget()) return;
    sst("PICK GADGET TO SELECT RENDER.....");
    if(NOT(gadget = wait_for_gadget(MainWindow))) return;

    mg = get_mg(gadget);

    if(NOT(TestBits((ULONG)gadget->Flags,GADGIMAGE))) {
        Error("Not an Image Gadget !");
        return;
    }

    if((TestBits((ULONG)gadget->Flags,GADGHIMAGE)) AND
       (NOT TestBits((ULONG)gadget->Flags,GADGHBOX)) AND
       (NOT TestBits((ULONG)mg->SpecialFlags,OS20HIGHBORDER))) {
        if(Ask("Gadget already has an Image !",
               "Do you wish to over-write it ?") == FALSE) return;
    }

    Saved = FALSE;

    if(NOT(image = image_bank(TRUE)))
        return;

    add_user(image);

    disable_window();

    Pos = RemoveGList(MainWindow,gadget,1);
    un_grel(MainWindow,gadget);

    if((TestBits((ULONG)gadget->Flags,GADGHBOX)) AND
       (NOT TestBits((ULONG)gadget->Flags,GADGHIMAGE)))
           gadget->Flags ^= GADGHBOX;

    if((TestBits((ULONG)gadget->Flags,GADGHIMAGE)) AND
       (NOT TestBits((ULONG)gadget->Flags,GADGHBOX))) {
        image1 = (struct Image *)gadget->SelectRender;
        rem_user(image1);
    }

    gadget->Flags       |= GADGHIMAGE;
    gadget->SelectRender = (APTR)image;
    grel(MainWindow,gadget);
    AddGList(MainWindow,gadget,Pos,1,NULL);
    enable_window();
    refresh();
}

/*
 * read and set the CMAP of an IFF ILBM picture
 */
void do_cmap( void )
{
    ULONG rc;

    strcpy((char *)IODir->fr_HeadLine,"Load IFF ColorMap");

    IODir->fr_Screen = MainScreen;
    IODir->fr_Caller = MainWindow;
    IODir->fr_Flags |= FR_NoInfo;

    rc = FileRequest(IODir);

    strcpy((char *)&name,(char *)IODir->fr_DirName);
    strcat((char *)&name,(char *)IODir->fr_FileName);

    if(rc == FREQ_CANCELED) return;
    else if(rc) {
        Error("FileRequester Won't Open !");
        return;
    }

    Saved = FALSE;
    disable_window();
    ReadCMAP(name,NULL);
    enable_window();
}

/*
 * resize a gadget
 */
void size_gadget( void )
{
    struct MyGadget *mg;
    struct Gadget   *gadget;
    SHORT            x,y,w,h,xo,yo, *XY;
    ULONG            Pos;

    if(NOT Gadgets.Head->Succ) return;

    add_bo();
    sst("PICK GADGET TO RE-SIZE.....");
    if(NOT(gadget = wait_for_gadget(MainWindow))) {
        rem_bo();
        return;
    }

    rem_bo();
    rem_no();

    mg    = get_mg(gadget);
    Saved = FALSE;

    un_grel(MainWindow,gadget);
    x = gadget->LeftEdge-1;
    y = gadget->TopEdge-1;
    w = gadget->Width+1;
    h = gadget->Height+1;

    switch_coords(FALSE);
    set_info(0);
    SetDrMd(MainRP,COMPLEMENT);
    SetAPen(MainRP,FrontPen);
    draw_box(MainWindow,x,y,x+w,y+h);
    do_info(0,x,y,x+w,y+h);
    xo = (x+w)-MainX;
    yo = (y+h)-MainY;


    while(Code != SELECTDOWN) {
        while(read_msg(MainWindow)) {
            if(Class == MENUPICK) set_info(0);
            do_info(0,x,y,x+w,y+h);
        }
        get_xy(&MainX,&MainY);
        if((MainX != ((x + w) - xo)) OR (MainY != ((y + h) - yo))) {
            draw_box(MainWindow,x,y,x+w,y+h);
            if(((MainX - x) + xo) >= 9)  w = (MainX - x) + xo;
            if(((MainY - y) + yo) >= 9)  h = (MainY - y) + yo;
            draw_box(MainWindow,x,y,x+w,y+h);
            do_info(0,x,y,x+w,y+h);
        }
    }

    add_bo();
    add_no();
    draw_box(MainWindow,x,y,x+w,y+h);

    if(NOT(TestBits((ULONG)gadget->GadgetType,PROPGADGET))) {
        if(NOT(TestBits((ULONG)gadget->Flags,GADGIMAGE))) {
            if(NOT TestBits((ULONG)mg->SpecialFlags,OS20BORDER)) {
                XY = (((struct Border *)gadget->GadgetRender)->XY);
                XY[2] = XY[4] = w-1;
                XY[5] = XY[7] = h-1;
            } else {
                if(NOT TestBits((ULONG)gadget->GadgetType,STRGADGET)) {
                    w -= 2;
                    h -= 2;
                } else {
                    w--;
                    h--;
                }
                XY = (((struct Border *)gadget->GadgetRender)->XY);
                XY[3] = h;
                XY[5] = h-1;
                XY[8] = w-1;
                XY = ((((struct Border *)gadget->GadgetRender)->NextBorder)->XY);
                XY[1] = XY[3] = XY[9] = h;
                XY[2] = XY[4] = w-1;
                XY[6] = XY[8] = w;
            }
        }
    }

    if(TestBits((ULONG)mg->SpecialFlags,OS20BORDER)) {
        if(NOT TestBits((ULONG)gadget->GadgetType,STRGADGET)) {
            w += 2;
            h += 2;
        } else {
            w++;
            h++;
        }
    }

    for(mg = Gadgets.Head; mg; mg = mg->Succ) {
        if(mg->Gadget.GadgetRender == gadget->GadgetRender) {
            mg->Gadget.Width  = w-1;
            mg->Gadget.Height = h-1;
        }
    }

    grel(MainWindow,gadget);
    switch_coords(TRUE);
    rem_bo();
    refresh();
}

/*
 * move a gadget
 */
void move_gadget( void )
{
    struct MyGadget *mg;
    struct Gadget   *gadget;
    SHORT            x,y,w,h,xo,yo;
    ULONG            Pos;

    if(NOT Gadgets.Head->Succ) return;

    add_bo();
    sst("PICK GADGET TO MOVE....");
    if(NOT(gadget = wait_for_gadget(MainWindow))) {
        rem_bo();
        return;
    }

    Saved = FALSE;

    rem_bo();
    rem_no();

    mg = get_mg(gadget);
    switch_coords(FALSE);
    set_info(0);
    un_grel(MainWindow,gadget);
    x = gadget->LeftEdge-1;
    y = gadget->TopEdge-1;
    w = gadget->Width+1;
    h = gadget->Height+1;
    SetDrMd(MainRP,COMPLEMENT);
    SetAPen(MainRP,FrontPen);
    draw_box(MainWindow,x,y,x+w,y+h);
    do_info(0,x,y,x+w,y+h);
    xo = MainX-x;
    yo = MainY-y;

    while(Code != SELECTDOWN) {
        while(read_msg(MainWindow)) {
            if(Class == MENUPICK) set_info(0);
            do_info(0,x,y,x+w,y+h);
        }
        get_xy(&MainX,&MainY);
        if((MainX != (x + xo)) OR (MainY != (y + yo))) {
            draw_box(MainWindow,x,y,x+w,y+h);
            x = MainX - xo;
            y = MainY - yo;
            draw_box(MainWindow,x,y,x+w,y+h);
            do_info(0,x,y,x+w,y+h);
        }
    }

    add_bo();
    add_no();
    draw_box(MainWindow,x,y,x+w,y+h);
    gadget->LeftEdge = x+1;
    gadget->TopEdge  = y+1;
    grel(MainWindow,gadget);
    switch_coords(TRUE);
    rem_bo();
    refresh();
}

/*
 * edit a gadget
 */
void edit( void )
{
    struct MyGadget *mg;
    struct Gadget   *g;
    ULONG            Pos;
    BOOL             suc;

    if(NOT Gadgets.Head->Succ) return;

    add_bo();
    sst("PICK GADGET TO EDIT....");
    if(NOT(g = wait_for_gadget(MainWindow))) {
        rem_bo();
        return;
    }

    Saved = FALSE;

    mg = get_mg(g);
    Pos = RemoveGList(MainWindow,g,1);
    un_grel(MainWindow,g);
    disable_window();
    suc = edit_gadget(mg);
    enable_window();
    grel(MainWindow,g);

    if(NOT suc) {
        Remove((void *)mg);
        FreeGadget(mg);
    }
    else
        AddGList(MainWindow,g,Pos,1,NULL);

    rem_bo();
    refresh();
}

/*
 * erase all gadgets and set the window to default
 */
void new( void )
{
    if(Saved == FALSE) {
        if(Ask("Current work isn't saved !","Are you sure ?") == FALSE)
            return;
    }

    FreeGList();
    FreeMenuStrip();

    if(Images.Head->Succ) {
        if(Ask("There are images in the Image Bank!","Delete them too ?") == TRUE)
            free_all();
    }

    nw_main.LeftEdge    = 50;
    nw_main.TopEdge     = 25;
    nw_main.Width       = 175;
    nw_main.Height      = 50;
    WDBackFill          = 0;
    BackFill            = 1;

    if(get_config(TRUE)) {
        change_depth(DEPTH);
        WindowFlags = WINDOWDRAG+WINDOWSIZING+WINDOWCLOSE+WINDOWDEPTH+NOCAREREFRESH+SMART_REFRESH+ACTIVATE;
        IDCMPFlags  = GADGETUP+GADGETDOWN+CLOSEWINDOW;
    } else {
        ClearMenuStrip(MainWindow);
        CloseWindow(MainWindow);
        MainWindow = NULL;
        if(REQUESTER) {
            strcpy((char *)&wlb[0],"requester");
            strcpy((char *)&wdt[0],"Requester");
            nw_main.Flags = WINDOWDRAG+WINDOWSIZING+SIZEBRIGHT+SIZEBBOTTOM+GIMMEZEROZERO+BORDERLESS+NOCAREREFRESH+SMART_REFRESH+ACTIVATE;
        } else {
            strcpy((char *)&wlb[0],"new_window");
            strcpy((char *)&wdt[0],"Work Window");
            nw_main.Flags = WINDOWSIZING+WINDOWDRAG+WINDOWCLOSE+WINDOWDEPTH+NOCAREREFRESH+SMART_REFRESH+ACTIVATE;
        }
        WindowFlags = WINDOWDRAG+WINDOWSIZING+WINDOWCLOSE+WINDOWDEPTH+NOCAREREFRESH+SMART_REFRESH+ACTIVATE;
        IDCMPFlags  = GADGETUP+GADGETDOWN+CLOSEWINDOW;
        open_display();
        SetMenu(MainWindow);
    }

    if(!WBSCREEN)
        LoadRGB4(&MainScreen->ViewPort,(void *)&Colors,(1 << DEPTH));
    bo_added = TRUE;
    refresh();
}

/*
 * delete the render images of a gadget
 */
void delete_images( void )
{
    struct MyGadget *mg;
    struct Gadget   *g;
    struct Image    *i;
    struct PropInfo *p;
    ULONG            pos,ds;

    if(NOT Gadgets.Head->Succ) return;

    if(NOT is_gadget()) return;
    sst("PICK GADGET TO DELETE IMAGES....");
    if(NOT(g = wait_for_gadget(MainWindow))) return;

    if(NOT(TestBits((ULONG)g->Flags,GADGIMAGE))) {
        Error("Gadget has no Images to delete !");
        return;
    }

    mg = get_mg(g);

    Saved = FALSE;

    pos = RemoveGList(MainWindow,g,1);
    un_grel(MainWindow,g);
    i = (struct Image *)g->GadgetRender;
    rem_user(i);
    g->Flags ^= GADGIMAGE;
    if((TestBits((ULONG)g->Flags,GADGHIMAGE)) AND
       (NOT TestBits((ULONG)g->Flags,GADGHBOX))AND
       (NOT TestBits((ULONG)mg->SpecialFlags,OS20HIGHBORDER))) {
        i = (struct Image *)g->SelectRender;
        rem_user(i);
        g->Flags ^= GADGHIMAGE;
        g->SelectRender = NULL;
    }

    if(TestBits((ULONG)g->GadgetType,PROPGADGET)) {
        g->GadgetRender = (APTR)Alloc(&Memory,(ULONG)sizeof(struct Image));
        p = (struct PropInfo *)g->SpecialInfo;
        p->Flags |= AUTOKNOB;
    } else
        add_border(get_mg(g));

    grel(MainWindow,g);
    AddGList(MainWindow,g,pos,1,NULL);
    refresh();
}

long center( struct IntuiText *t, long which )
{
    long ret;

    disable_window();
    if(REQUESTER) {
        if(NOT which)
            ret = ((MainWindow->GZZWidth >> 1) - (IntuiTextLength(t) >> 1));
        else
            ret = ((MainWindow->GZZHeight >> 1) - 3);
    } else {
        if(NOT which)
            ret = ((MainWindow->Width >> 1) - (IntuiTextLength(t) >> 1));
        else
            ret = ((MainWindow->Height >> 1) - 3);
    }
    enable_window();
    return(ret);
}

/*
 * add a text to a gadget or the window/requester
 */
void add_text( ULONG which )
{
    struct Gadget    *g;
    struct IntuiText *t, *edit_text();
    ULONG             pos;
    SHORT             x,y,le,te;

    if(NOT which) {
        if(NOT Gadgets.Head->Succ) return;
        if(NOT is_gadget()) return;
        sst("PICK GADGET TO ADD TEXT....");
        if(NOT(g = wait_for_gadget(MainWindow))) return;
    } else
        g = &TextGadget;

    if(NOT(t = edit_text(g,0,0,which))) return;

    Delay(5);

    rem_no();
    Saved = FALSE;

    le = g->LeftEdge;
    te = g->TopEdge;

    un_grel(MainWindow,g);
    switch_coords(FALSE);
    get_xy(&x,&y);
    SetDrMd(MainRP,COMPLEMENT);
    SetAPen(MainRP,FrontPen);
    Move(MainRP,x,y);
    Text(MainRP,(char *)t->IText,strlen((char *)t->IText));
    set_info(1);
    do_info(1,x-le,y-te,x-le,y-te);

    while(Code != SELECTDOWN) {
        while(read_msg(MainWindow)) {
            if(Class == MENUPICK) set_info(1);
            do_info(1,x-le,y-te,x-le,y-te);
            if(Class == RAWKEY) {
                switch(Code) {
                    case F1:
                        if(NOT which) {
                            t->LeftEdge = ((g->Width >> 1) - (IntuiTextLength(t) >> 1));
                            t->TopEdge  = ((g->Height >> 1) - 3);
                            while(read_msg(MainWindow));
                            goto placeText;
                        }
                        break;
                    case F2:
                        if(which) {
                            t->TopEdge  = y - te - 6;
                            t->LeftEdge = center(t,0);
                            while(read_msg(MainWindow));
                            goto placeText;
                        }
                        break;
                    case F3:
                        if(which) {
                            t->TopEdge  = center(t,1);
                            t->LeftEdge = x-le;
                            while(read_msg(MainWindow));
                            goto placeText;
                        }
                    break;
                }
            }
        }
        get_xy(&MainX,&MainY);
        if((MainX != x) OR (MainY != y)) {
            Move(MainRP,x,y);
            Text(MainRP,(char *)t->IText,strlen((char *)t->IText));
            x = MainX;
            y = MainY;
            Move(MainRP,x,y);
            Text(MainRP,(char *)t->IText,strlen((char *)t->IText));
            do_info(1,x-le,y-te,x-le,y-te);
        }
    }

    Move(MainRP,x,y);
    Text(MainRP,(char *)t->IText,strlen((char *)t->IText));

    t->LeftEdge = x - le;
    t->TopEdge  = y - te - 6;

placeText:

    if(NOT which)
        grel(MainWindow,g);
    switch_coords(TRUE);
    add_no();
    refresh();
}

/*
 * move a gadget or window/requester text
 */
void move_text( ULONG which )
{
    struct Gadget    *g;
    struct IntuiText *t, *GetPtr();
    ULONG             pos;
    LONG              tnum;
    SHORT             x,y,le,te;

    if(NOT which) {
        if(NOT Gadgets.Head->Succ) return;
        if(NOT is_gadget()) return;
        sst("PICK GADGET TO MOVE TEXT....");
        if(NOT(g = wait_for_gadget(MainWindow))) return;
    } else
        g = &TextGadget;

    if(NOT g->GadgetText) {
        if(NOT which)       Error("Gadget has no text(s) to move !");
        else if(which == 1) Error("Window has no text(s) to move !");
        else                Error("Requester has no text(s) to move !");
        return;
    }

    if((tnum = text_select(g,1,which)) == -1L) return;

    Saved = FALSE;

    Delay(5);

    le = g->LeftEdge;
    te = g->TopEdge;

    t = GetPtr(g,tnum);

    rem_no();
    switch_coords(FALSE);
    set_info(1);
    un_grel(MainWindow,g);
    get_xy(&x,&y);
    SetDrMd(MainRP,COMPLEMENT);
    SetAPen(MainRP,FrontPen);
    Move(MainRP,x,y);
    Text(MainRP,(char *)t->IText,strlen((char *)t->IText));
    do_info(1,x-le,y-te,x-le,y-te);

    while(Code != SELECTDOWN) {
        while(read_msg(MainWindow)) {
            if(Class == MENUPICK) set_info(1);
            do_info(1,x-le,y-te,x-le,y-te);
            if(Class == RAWKEY) {
                switch(Code) {
                    case F1:
                        if(NOT which) {
                            t->LeftEdge = ((g->Width >> 1) - (IntuiTextLength(t) >> 1));
                            t->TopEdge  = ((g->Height >> 1) - 3);
                            while(read_msg(MainWindow));
                            goto placeText;
                        }
                        break;
                    case F2:
                        if(which) {
                            t->TopEdge  = y - te - 6;
                            t->LeftEdge = center(t,0);
                            while(read_msg(MainWindow));
                            goto placeText;
                        }
                        break;
                    case F3:
                        if(which) {
                            t->TopEdge  = center(t,1);
                            t->LeftEdge = x-le;
                            while(read_msg(MainWindow));
                            goto placeText;
                        }
                    break;
                }
            }
        }
        get_xy(&MainX,&MainY);
        if((MainX != x) OR (MainY != y)) {
            Move(MainRP,x,y);
            Text(MainRP,(char *)t->IText,strlen((char *)t->IText));
            x = MainX;
            y = MainY;
            Move(MainRP,x,y);
            Text(MainRP,(char *)t->IText,strlen((char *)t->IText));
            do_info(1,x-le,y-te,x-le,y-te);
        }
    }

    Move(MainRP,x,y);
    Text(MainRP,(char *)t->IText,strlen((char *)t->IText));
    text_num = tnum;
    clear_text(g);
    t->LeftEdge = x - le;
    t->TopEdge  = y - te - 6;
placeText:
    if(NOT which)
        grel(MainWindow,g);
    switch_coords(TRUE);
    add_no();
    refresh();
}

/*
 * modify a gadget or window/requester text
 */
void modify( ULONG which )
{
    struct Gadget *g;
    ULONG          pos;

    if(NOT which) {
        if(NOT Gadgets.Head->Succ) return;
        if(NOT is_gadget()) return;
        sst("PICK GADGET TO MODIFY TEXT....");
        if(NOT(g = wait_for_gadget(MainWindow))) return;
    } else
        g = &TextGadget;

    if(NOT g->GadgetText) {
        if(NOT which)       Error("Gadget has no text(s) to modify !");
        else if(which == 1) Error("Window has no text(s) to modify !");
        else                Error("Requester has no text(s) to modify !");
        return;
    }

    Saved = FALSE;
    rem_no();
    text_select(g,2,which);
    add_no();
    refresh();
}

/*
 * delete a gadget or window/requester text
 */
void text_delete( ULONG which )
{
    struct Gadget *g;
    ULONG          pos;

    if(NOT which) {
        if(NOT Gadgets.Head->Succ) return;
        if(NOT is_gadget()) return;
        sst("PICK GADGET TO DELETE TEXT....");
        if(NOT(g = wait_for_gadget(MainWindow))) return;
    } else
        g = &TextGadget;

    if(NOT g->GadgetText) {
        if(NOT which)       Error("Gadget has no text(s) to delete !");
        else if(which == 1) Error("Window has no text(s) to delete !");
        else                Error("Requester has no text(s) to delete !");
        return;
    }
    Saved = FALSE;
    rem_no();
    text_select(g,3,which);
    add_no();
    refresh();
}
